Files
cosmos-explorer/src/Contracts/ViewModels.ts
T
Jade Welton 78d0d8deef Remove Phoenix and notebooks (Phase 6)
Complete the final removal phase by deleting Juno and analytical schema integration, residual Phoenix and notebook contracts, configuration, localization, and assets. Preserve CloudShell behavior and numeric compatibility contracts while cleaning stale UI terminology.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8730a951-831c-4cc2-9c91-83e237683d46
2026-08-27 13:59:10 -07:00

481 lines
13 KiB
TypeScript

import {
ItemDefinition,
JSONObject,
QueryMetrics,
Resource,
StoredProcedureDefinition,
TriggerDefinition,
UserDefinedFunctionDefinition,
} from "@azure/cosmos";
import type Explorer from "../Explorer/Explorer";
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/ConsoleData";
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
import ConflictId from "../Explorer/Tree/ConflictId";
import DocumentId from "../Explorer/Tree/DocumentId";
import StoredProcedure from "../Explorer/Tree/StoredProcedure";
import Trigger from "../Explorer/Tree/Trigger";
import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction";
import { SelfServeType } from "../SelfServe/SelfServeUtils";
import { CollectionCreationDefaults } from "../UserContext";
import { SqlTriggerResource } from "../Utils/arm/generatedClients/cosmos/types";
import * as DataModels from "./DataModels";
import { SubscriptionType } from "./SubscriptionType";
export interface TokenProvider {
getAuthHeader(): Promise<Headers>;
}
export interface UploadDetailsRecord {
fileName: string;
numSucceeded: number;
numFailed: number;
numThrottled: number;
errors: string[];
resources?: ItemDefinition[];
}
export type BulkInsertResult = Omit<UploadDetailsRecord, "fileName">;
export interface QueryResultsMetadata {
hasMoreResults: boolean;
firstItemIndex: number;
lastItemIndex: number;
itemCount: number;
}
export interface QueryResults extends QueryResultsMetadata {
documents: any[];
activityId: string;
requestCharge: number;
roundTrips?: number;
headers?: any;
queryMetrics?: QueryMetrics;
ruThresholdExceeded?: boolean;
}
export interface Button {
visible: ko.Computed<boolean>;
enabled: ko.Computed<boolean>;
isSelected?: ko.Computed<boolean>;
}
export interface NotificationConsole {
filteredConsoleData: ko.ObservableArray<ConsoleData>;
isConsoleExpanded: ko.Observable<boolean>;
expandConsole(source: any, evt: MouseEvent): void;
collapseConsole(source: any, evt: MouseEvent): void;
}
export interface WaitsForTemplate {
isTemplateReady: ko.Observable<boolean>;
}
export interface TreeNode {
nodeKind: string;
rid: string;
id: ko.Observable<string>;
database?: Database;
collection?: Collection;
onNewQueryClick?(source: any, event: MouseEvent): void;
onNewStoredProcedureClick?(source: Collection, event: MouseEvent): void;
onNewUserDefinedFunctionClick?(source: Collection, event: MouseEvent): void;
onNewTriggerClick?(source: Collection, event: MouseEvent): void;
}
export interface Database extends TreeNode {
container: Explorer;
self: string;
id: ko.Observable<string>;
collections: ko.ObservableArray<Collection>;
offer: ko.Observable<DataModels.Offer>;
isDatabaseExpanded: ko.Observable<boolean>;
isDatabaseShared: ko.Computed<boolean>;
isSampleDB?: boolean;
collectionsContinuationToken?: string;
selectedSubnodeKind: ko.Observable<CollectionTabKind>;
expandDatabase(): Promise<void>;
collapseDatabase(): void;
loadCollections(restart?: boolean): Promise<void>;
findCollectionWithId(collectionId: string): Collection;
openAddCollection(database: Database, event: MouseEvent): void;
onSettingsClick: () => void;
loadOffer(): Promise<void>;
}
export interface CollectionBase extends TreeNode {
container: Explorer;
databaseId: string;
self: string;
rawDataModel: DataModels.Collection;
partitionKey: DataModels.PartitionKey;
partitionKeyProperties: string[];
partitionKeyPropertyHeaders: string[];
id: ko.Observable<string>;
selectedSubnodeKind: ko.Observable<CollectionTabKind>;
children: ko.ObservableArray<TreeNode>;
isCollectionExpanded: ko.Observable<boolean>;
isSampleCollection?: boolean;
onDocumentDBDocumentsClick(): void;
onNewQueryClick(
source: any,
event?: MouseEvent,
queryText?: string,
splitterDirection?: "horizontal" | "vertical",
queryViewSizePercent?: number,
): void;
expandCollection(): void;
collapseCollection(): void;
getDatabase(): Database;
}
export interface Collection extends CollectionBase {
defaultTtl: ko.Observable<number>;
analyticalStorageTtl: ko.Observable<number>;
vectorEmbeddingPolicy: ko.Observable<DataModels.VectorEmbeddingPolicy>;
fullTextPolicy: ko.Observable<DataModels.FullTextPolicy>;
dataMaskingPolicy: ko.Observable<DataModels.DataMaskingPolicy>;
indexingPolicy: ko.Observable<DataModels.IndexingPolicy>;
uniqueKeyPolicy: DataModels.UniqueKeyPolicy;
usageSizeInKB: ko.Observable<number>;
offer: ko.Observable<DataModels.Offer>;
conflictResolutionPolicy: ko.Observable<DataModels.ConflictResolutionPolicy>;
changeFeedPolicy: ko.Observable<DataModels.ChangeFeedPolicy>;
geospatialConfig: ko.Observable<DataModels.GeospatialConfig>;
documentIds: ko.ObservableArray<DocumentId>;
computedProperties: ko.Observable<DataModels.ComputedProperties>;
materializedViews: ko.Observable<DataModels.MaterializedView[]>;
materializedViewDefinition: ko.Observable<DataModels.MaterializedViewDefinition>;
cassandraKeys: CassandraTableKeys;
cassandraSchema: CassandraTableKey[];
onConflictsClick(): void;
onTableEntitiesClick(): void;
onGraphDocumentsClick(): void;
onMongoDBDocumentsClick(): void;
openTab(): void;
onSettingsClick: () => Promise<void>;
onNewGraphClick(): void;
onNewMongoQueryClick(
source: any,
event?: MouseEvent,
queryText?: string,
splitterDirection?: "horizontal" | "vertical",
queryViewSizePercent?: number,
): void;
onNewMongoShellClick(): void;
onNewStoredProcedureClick(source: Collection, event?: MouseEvent): void;
onNewUserDefinedFunctionClick(source: Collection, event?: MouseEvent): void;
onNewTriggerClick(source: Collection, event?: MouseEvent): void;
storedProcedures: ko.Computed<StoredProcedure[]>;
userDefinedFunctions: ko.Computed<UserDefinedFunction[]>;
triggers: ko.Computed<Trigger[]>;
isStoredProceduresExpanded: ko.Observable<boolean>;
isTriggersExpanded: ko.Observable<boolean>;
isUserDefinedFunctionsExpanded: ko.Observable<boolean>;
expandStoredProcedures(): void;
expandUserDefinedFunctions(): void;
expandTriggers(): void;
collapseStoredProcedures(): void;
collapseUserDefinedFunctions(): void;
collapseTriggers(): void;
loadUserDefinedFunctions(): Promise<any>;
loadStoredProcedures(): Promise<any>;
loadTriggers(): Promise<any>;
loadOffer(): Promise<void>;
showStoredProcedures: ko.Observable<boolean>;
showTriggers: ko.Observable<boolean>;
showUserDefinedFunctions: ko.Observable<boolean>;
showConflicts: ko.Observable<boolean>;
createStoredProcedureNode(data: StoredProcedureDefinition & Resource): StoredProcedure;
createUserDefinedFunctionNode(data: UserDefinedFunctionDefinition & Resource): UserDefinedFunction;
createTriggerNode(data: TriggerDefinition | SqlTriggerResource): Trigger;
findStoredProcedureWithId(sprocRid: string): StoredProcedure;
findTriggerWithId(triggerRid: string): Trigger;
findUserDefinedFunctionWithId(udfRid: string): UserDefinedFunction;
onDragOver(source: Collection, event: { originalEvent: DragEvent }): void;
onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
uploadFiles(fileList: FileList): Promise<{ data: UploadDetailsRecord[] }>;
bulkInsertDocuments(documents: JSONObject[]): Promise<{
numSucceeded: number;
numFailed: number;
numThrottled: number;
errors: string[];
}>;
}
/**
* Options used to initialize pane
*/
export interface PaneOptions {
id: string;
visible: ko.Observable<boolean>;
container?: Explorer;
}
/**
* Graph configuration
*/
export enum NeighborType {
SOURCES_ONLY,
TARGETS_ONLY,
BOTH,
}
export interface IGraphConfigUiData {
showNeighborType: NeighborType;
nodeProperties: string[];
nodePropertiesWithNone: string[];
nodeCaptionChoice: string;
nodeColorKeyChoice: string;
nodeIconChoice: string;
nodeIconSet: string;
}
/**
* User input for creating new vertex
*/
export interface NewVertexData {
label: string;
properties: InputProperty[];
}
export type GremlinPropertyValueType = string | boolean | number | null | undefined;
export type InputPropertyValueTypeString = "string" | "number" | "boolean" | "null";
export interface InputPropertyValue {
value: GremlinPropertyValueType;
type: InputPropertyValueTypeString;
}
/**
* Property input by user
*/
export interface InputProperty {
key: string;
values: InputPropertyValue[];
}
export interface Editable<T> extends ko.Observable<T> {
setBaseline(baseline: T): void;
editableIsDirty: ko.Computed<boolean>;
editableIsValid: ko.Observable<boolean>;
getEditableCurrentValue?: ko.Computed<T>;
getEditableOriginalValue?: ko.Computed<T>;
edits?: ko.ObservableArray<T>;
validations?: ko.ObservableArray<(value: T) => boolean>;
}
export interface QueryError {
message: string;
start: string;
end: string;
code: string;
severity: string;
}
export interface DocumentRequestContainer {
self: string;
rid?: string;
resourceName?: string;
}
export interface DocumentClientOption {
endpoint?: string;
masterKey?: string;
requestTimeoutMs?: number;
}
// Tab options
export interface TabOptions {
tabKind: CollectionTabKind;
title: string;
tabPath: string;
isTabsContentExpanded?: ko.Observable<boolean>;
onLoadStartKey?: number;
// TODO Remove the flag and use a context to handle this
// TODO: 145357 Remove dependency on collection/database and add abstraction
collection?: CollectionBase;
database?: Database;
rid?: string;
node?: TreeNode;
theme?: string;
index?: number;
}
export interface DocumentsTabOptions extends TabOptions {
partitionKey: DataModels.PartitionKey;
documentIds: ko.ObservableArray<DocumentId>;
container?: Explorer;
isPreferredApiMongoDB?: boolean;
resourceTokenPartitionKey?: string;
}
export interface ConflictsTabOptions extends TabOptions {
partitionKey: DataModels.PartitionKey;
conflictIds: ko.ObservableArray<ConflictId>;
container?: Explorer;
}
export interface QueryTabOptions extends TabOptions {
partitionKey?: DataModels.PartitionKey;
queryText?: string;
resourceTokenPartitionKey?: string;
splitterDirection?: "horizontal" | "vertical";
queryViewSizePercent?: number;
}
export interface ScriptTabOption extends TabOptions {
resource: any;
isNew: boolean;
partitionKey?: DataModels.PartitionKey;
}
export interface EditorPosition {
line: number;
column: number;
}
export enum DocumentExplorerState {
noDocumentSelected,
newDocumentValid,
newDocumentInvalid,
existingDocumentNoEdits,
existingDocumentDirtyValid,
existingDocumentDirtyInvalid,
}
export enum IndexingPolicyEditorState {
noCollectionSelected,
noEdits,
dirtyValid,
dirtyInvalid,
}
export enum ScriptEditorState {
newInvalid,
newValid,
existingNoEdits,
existingDirtyValid,
existingDirtyInvalid,
}
export enum CollectionTabKind {
Documents = 0,
Settings = 1,
StoredProcedures = 2,
UserDefinedFunctions = 3,
Triggers = 4,
Query = 5,
Graph = 6,
QueryTables = 9,
MongoShell = 10,
DatabaseSettings = 11,
Conflicts = 12,
Terminal = 14,
SparkMasterTab = 16 /* Deprecated */,
CollectionSettingsV2 = 20,
DatabaseSettingsV2 = 21,
}
export enum TerminalKind {
Default = 0,
Mongo = 1,
Cassandra = 2,
Postgres = 3,
VCoreMongo = 4,
CosmosDB = 5,
}
export interface DataExplorerInputsFrame {
databaseAccount: any;
subscriptionId?: string;
resourceGroup?: string;
tenantId?: string;
userName?: string;
masterKey?: string;
hasWriteAccess?: boolean;
authorizationToken?: string;
csmEndpoint?: string;
dnsSuffix?: string;
serverId?: string;
portalBackendEndpoint?: string;
mongoProxyEndpoint?: string;
cassandraProxyEndpoint?: string;
subscriptionType?: SubscriptionType;
quotaId?: string;
isTryCosmosDBSubscription?: boolean;
loadDatabaseAccountTimestamp?: number;
sharedThroughputMinimum?: number;
sharedThroughputMaximum?: number;
sharedThroughputDefault?: number;
dataExplorerVersion?: string;
defaultCollectionThroughput?: CollectionCreationDefaults;
isPostgresAccount?: boolean;
isReplica?: boolean;
isVCoreMongoAccount?: boolean;
clientIpAddress?: string;
// TODO: Update this param in the OSS extension to remove isFreeTier, isMarlinServerGroup, and make nodes a flat array instead of an nested array
connectionStringParams?: any;
flights?: readonly string[];
features?: {
[key: string]: string;
};
feedbackPolicies?: any;
aadToken?: string;
containerCopyEnabled?: boolean;
sessionId?: string;
theme?: {
mode: number;
};
}
export interface SelfServeFrameInputs {
selfServeType: SelfServeType;
databaseAccount: any;
subscriptionId: string;
resourceGroup: string;
authorizationToken: string;
csmEndpoint: string;
flights?: readonly string[];
catalogAPIKey: string;
}
export class MonacoEditorSettings {
public readonly language: string;
public readonly readOnly: boolean;
constructor(supportedLanguage: string, isReadOnly: boolean) {
this.language = supportedLanguage;
this.readOnly = isReadOnly;
}
}
export interface AuthorizationTokenHeaderMetadata {
header: string;
token: string;
}
export interface DropdownOption<T> {
text: string;
value: T;
disable?: boolean;
}
// Remove the duplicate Explorer interface and export the type
export type { Explorer };