/* oxlint-disable executor/no-try-catch-or-throw, executor/no-error-constructor, executor/no-instanceof-error, executor/no-unknown-error-message, executor/no-json-parse -- boundary: one-shot provider service split planner preserves the throwing dry-run contract used by migration tooling */import { createHash } from "node:crypto"; import { googleCatalog, googlePresetForDiscoveryUrl,} from "@executor-js/plugin-openapi/providers/google";import { MICROSOFT_GRAPH_DEFAULT_PRESET_IDS, microsoftCatalog,} from "@executor-js/plugin-openapi/providers/microsoft";import type { IntegrationPreset } from "@executor-js/sdk/core"; type MonolithPluginId = "google" | "microsoft"; const normalizeUrl = (url: string): string => { const trimmed = url.trim(); if (!URL.canParse(trimmed)) return trimmed.replace(/\/$/, ""); const parsed = new URL(trimmed); parsed.hash = ""; parsed.searchParams.sort(); return parsed.toString().replace(/\/$/, "");}; const googleCatalogByDiscoveryUrl = new Map( googleCatalog.flatMap((preset) => preset.url ? [[normalizeUrl(preset.url), preset] as const] : [], ),); const matchPattern = (pattern: string, toolId: string): boolean => { if (pattern === "*") return true; const patternSegments = pattern.split("."); const toolSegments = toolId.split("."); for (let index = 0; index < patternSegments.length; index += 1) { const segment = patternSegments[index]!; if (segment === "*") { if (index === patternSegments.length - 1) return toolSegments.length >= index; if (index >= toolSegments.length) return false; continue; } if (index >= toolSegments.length || toolSegments[index] !== segment) return false; } return patternSegments.length === toolSegments.length;}; export type PluginId = "openapi"; export interface IntegrationRow { readonly tenant: string; readonly slug: string; readonly plugin_id: string; readonly name: string | null; readonly description: string | null; readonly config: unknown; readonly health_check?: unknown; readonly config_revised_at?: string | number | bigint | null; readonly can_remove: boolean; readonly can_refresh: boolean; readonly created_at: string; readonly updated_at: string; readonly row_id: string;} export interface ConnectionRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly integration: string; readonly name: string; readonly template: string; readonly provider: string; readonly item_ids: unknown; readonly identity_label: string | null; readonly description?: string | null; readonly last_health?: unknown; readonly tools_synced_at?: string | number | bigint | null; readonly oauth_client: string | null; readonly oauth_client_owner: string | null; readonly refresh_item_id: string | null; readonly expires_at: string | number | bigint | null; readonly oauth_scope: string | null; readonly oauth_token_url?: string | null; readonly provider_state: unknown; readonly created_at: string; readonly updated_at: string; readonly row_id: string;} export interface ToolRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly integration: string; readonly connection: string; readonly plugin_id: string; readonly name: string; readonly description?: string; readonly input_schema?: unknown; readonly output_schema?: unknown; readonly annotations?: unknown; readonly created_at?: string; readonly updated_at?: string; readonly row_id: string;} export interface PluginStorageRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly plugin_id: string; readonly collection: string; readonly key: string; readonly data: unknown; readonly created_at: string; readonly updated_at: string; readonly row_id: string;} export interface BlobRow { readonly id: string; readonly namespace: string; readonly key: string;} export interface ToolPolicyRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly id: string; readonly pattern: string; readonly action: string; readonly position: string; readonly created_at: string; readonly updated_at: string; readonly row_id: string;} export interface MigrationInput { readonly integrations: readonly IntegrationRow[]; readonly connections: readonly ConnectionRow[]; readonly tools: readonly ToolRow[]; readonly pluginStorage?: readonly PluginStorageRow[]; readonly blobs?: readonly BlobRow[]; readonly policies: readonly ToolPolicyRow[]; readonly completedTenants?: readonly string[]; readonly trafficLastTenant?: string; readonly collectPolicyErrors?: boolean; readonly orphanPolicyMode?: "hard_error" | "retarget_all"; readonly blobBackend?: "database" | "external"; readonly assumeExternalBlobSourcePresent?: boolean; readonly bootRailCreateToolImpliedServices?: boolean;} export interface ServiceTarget { readonly family: MonolithPluginId; readonly pluginId: PluginId; readonly presetId: string; readonly slug: string; readonly name: string; readonly description: string; readonly specUrl?: string; readonly specFormat: "google-discovery" | "microsoft-graph"; readonly authenticationTemplate?: readonly unknown[]; readonly healthCheck?: unknown;} export interface PlannedIntegration { readonly source: Pick<IntegrationRow, "tenant" | "slug" | "plugin_id" | "name">; readonly sourceContributions: readonly { readonly source: IntegrationRow; readonly specHash?: string; readonly operationsToBuild: number; readonly operationToolNames: readonly string[]; readonly specBlobPresent: boolean; readonly defsBlobPresent: boolean; }[]; readonly target: ServiceTarget; readonly action: "create" | "skip_existing"; readonly config: unknown; readonly healthCheck?: unknown; readonly servingState: { readonly specHash?: string; readonly specSource: string; readonly blobBackend: "database" | "external"; readonly specBlobPresent: boolean; readonly defsBlobPresent: boolean; readonly operationsToBuild: number; readonly operationToolNames: readonly string[]; readonly expectedZeroOperations: boolean; };} export interface PlannedBlobCopy { readonly source: Pick<IntegrationRow, "tenant" | "slug" | "plugin_id">; readonly specHash: string; readonly key: string; readonly sourceNamespace: string; readonly targetNamespace: string; readonly backend: "database" | "external"; readonly sourcePresent: boolean; readonly targetPresent: boolean; readonly sourceObjectName: string; readonly targetObjectName: string;} export interface PlannedConnection { readonly source: Pick<ConnectionRow, "tenant" | "owner" | "subject" | "integration" | "name">; readonly targetIntegration: string; readonly action: "clone" | "skip_existing"; readonly tokenReuse: "copy_item_ids_and_oauth_columns";} export interface PlannedPolicyRewrite { readonly policy: Pick< ToolPolicyRow, "tenant" | "owner" | "subject" | "id" | "pattern" | "action" | "position" >; readonly action: "rewrite"; readonly afterPatterns: readonly string[]; readonly matchedServices: readonly string[];} export interface OrgPlan { readonly tenant: string; readonly tenantHash: string; readonly completed: boolean; readonly integrations: readonly PlannedIntegration[]; readonly connections: readonly PlannedConnection[]; readonly policies: readonly PlannedPolicyRewrite[]; readonly blobCopies: readonly PlannedBlobCopy[]; readonly deleteMonoliths: readonly Pick< IntegrationRow, "tenant" | "slug" | "plugin_id" | "name" >[]; readonly clonedToolRows: number; readonly operationsToBuild: number; readonly hardErrors: readonly string[];} export interface MigrationPlan { readonly orgs: readonly OrgPlan[]; readonly summary: { readonly orgs: number; readonly completedOrgs: number; readonly integrationsCreate: number; readonly integrationsSkipExisting: number; readonly connectionsClone: number; readonly connectionsSkipExisting: number; readonly policiesRewrite: number; readonly policiesSkip: number; readonly policyRowsAfter: number; readonly monolithDeletes: number; readonly clonedToolRows: number; readonly operationsToBuild: number; readonly integrationsMissingSpecBlob: number; readonly integrationsMissingDefsBlob: number; readonly hardErrorOrgs: number; readonly policyHardErrors: number; };} const GOOGLE_IDENTITY_DISCOVERY_URL = "https://www.googleapis.com/discovery/v1/apis/oauth2/v2/rest"; const GOOGLE_TOOL_PREFIX_TO_PRESET_ID: ReadonlyMap<string, string> = new Map([ ["calendar", "google-calendar"], ["gmail", "google-gmail"], ["sheets", "google-sheets"], ["drive", "google-drive"], ["docs", "google-docs"], ["slides", "google-slides"], ["forms", "google-forms"], ["tasks", "google-tasks"], ["people", "google-people"], ["photoslibrary", "google-photos-library"], ["photospicker", "google-photos-picker"], ["chat", "google-chat"], ["keep", "google-keep"], ["youtube", "google-youtube-data"], ["searchconsole", "google-search-console"], ["webmasters", "google-search-console"], ["classroom", "google-classroom"], ["directory", "google-admin-directory"], ["reports", "google-admin-reports"], ["script", "google-apps-script"], ["bigquery", "google-bigquery"], ["cloudresourcemanager", "google-cloud-resource-manager"],]); const unique = <T>(values: Iterable<T>): readonly T[] => [...new Set(values)]; export const tenantHash = (tenant: string): string => createHash("sha256").update(tenant).digest("hex").slice(0, 12); const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value); const recordFromJsonLike = (value: unknown): Record<string, unknown> => { if (isRecord(value)) return value; if (typeof value !== "string") return {}; try { const parsed = JSON.parse(value) as unknown; return isRecord(parsed) ? parsed : {}; } catch { return {}; }}; const stringArray = (value: unknown): readonly string[] => Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : []; const configRecord = (integration: IntegrationRow): Record<string, unknown> => recordFromJsonLike(integration.config); const toolAddress = ( tool: Pick<ToolRow, "integration" | "owner" | "connection" | "name">,): string => `${tool.integration}.${tool.owner}.${tool.connection}.${tool.name}`; const withoutToolsPrefix = (pattern: string): string => pattern.startsWith("tools.") ? pattern.slice("tools.".length) : pattern; const withOriginalToolsPrefix = (original: string, rewrittenTail: string): string => original.startsWith("tools.") ? `tools.${rewrittenTail}` : rewrittenTail; const integrationPatternSegment = ( pattern: string,): { readonly prefix: boolean; readonly integration: string } => { const prefix = pattern.startsWith("tools."); const tail = prefix ? pattern.slice("tools.".length) : pattern; return { prefix, integration: tail.split(".")[0] ?? "" };}; const googleCatalogById: ReadonlyMap<string, IntegrationPreset> = new Map( googleCatalog.map((preset) => [preset.id, preset]),); const microsoftCatalogByMonolithPresetId: ReadonlyMap<string, IntegrationPreset> = new Map( microsoftCatalog.map((preset) => [preset.id.replace(/^microsoft-/, ""), preset]),); const MICROSOFT_UNMIGRATABLE_UMBRELLA_PRESET_IDS = new Set(["me-surface", "users", "groups"]);const MICROSOFT_TOOL_IMPLIED_PRESET_IDS = new Set(MICROSOFT_GRAPH_DEFAULT_PRESET_IDS);const microsoftCatalogBackedPresetIds = new Set( microsoftCatalog .filter((preset) => preset.defaultSlug && preset.defaultSlug.length > 0) .map((preset) => preset.id.replace(/^microsoft-/, "")),); export const microsoftToolFirstSegmentPresetIds: ReadonlyMap<string, readonly string[]> = new Map([ ["chats", ["teams-chat"]], ["chatsChat", ["teams-chat"]], ["communications", ["meetings-calls"]], ["communicationsCall", ["meetings-calls"]], ["communicationsOnlineMeeting", ["meetings-calls"]], ["communicationsPresence", ["meetings-calls"]], ["drives", ["files"]], ["drivesDrive", ["files"]], ["drivesDriveItem", ["files"]], ["groupsDrive", ["files"]], ["groupsDrives", ["files"]], ["groupsOnenote", ["onenote"]], ["groupsTeam", ["teams-channels"]], ["meCalendar", ["calendar"]], ["meCalendarGroups", ["calendar"]], ["meCalendars", ["calendar"]], ["meCalendarView", ["calendar"]], ["meChat", ["teams-chat"]], ["meChats", ["teams-chat"]], ["meContact", ["contacts"]], ["meContactFolder", ["contacts"]], ["meContactFolders", ["contacts"]], ["meContacts", ["contacts"]], ["meDrive", ["files"]], ["meDrives", ["files"]], ["meEvent", ["calendar"]], ["meEvents", ["calendar"]], ["meFindMeetingTimes", ["calendar"]], ["meFollowedSites", ["files"]], ["meGetMailTips", ["mail"]], ["meInferenceClassification", ["mail"]], ["meJoinedTeams", ["teams-channels"]], ["meMailFolder", ["mail"]], ["meMailFolders", ["mail"]], ["meMailboxSettings", ["mail"]], ["meMessage", ["mail"]], ["meMessages", ["mail"]], ["meOnlineMeeting", ["meetings-calls"]], ["meOnlineMeetings", ["meetings-calls"]], ["meOnenote", ["onenote"]], ["meOutlook", ["mail"]], ["meOutlookUser", ["mail"]], ["mePeople", ["contacts"]], ["mePerson", ["contacts"]], ["mePhoto", ["profile"]], ["meProfilePhoto", ["profile"]], ["meReminderView", ["calendar"]], ["meSendMail", ["mail"]], ["meSite", ["files"]], ["meTeam", ["teams-channels"]], ["meTodo", ["tasks"]], ["meUser", ["profile"]], ["meUserActions", ["profile"]], ["meUserFunctions", ["profile"]], ["shares", ["files"]], ["sites", ["sites"]], ["sitesOnenote", ["onenote"]], ["sitesSite", ["sites"]], ["teams", ["teams-channels"]], ["teamsChannel", ["teams-channels"]], ["teamsTeam", ["teams-channels"]], ["teamsTemplates", ["teams-channels"]], ["teamwork", ["teams-channels"]], ["usersCalendar", ["calendar"]], ["usersCalendarGroups", ["calendar"]], ["usersCalendars", ["calendar"]], ["usersCalendarView", ["calendar"]], ["usersContact", ["contacts"]], ["usersContactFolder", ["contacts"]], ["usersContactFolders", ["contacts"]], ["usersContacts", ["contacts"]], ["usersDrive", ["files"]], ["usersDrives", ["files"]], ["usersEvent", ["calendar"]], ["usersEvents", ["calendar"]], ["usersFindMeetingTimes", ["calendar"]], ["usersMailFolder", ["mail"]], ["usersMailFolders", ["mail"]], ["usersMessage", ["mail"]], ["usersMessages", ["mail"]], ["usersOnlineMeeting", ["meetings-calls"]], ["usersOnlineMeetings", ["meetings-calls"]], ["usersOnenote", ["onenote"]], ["usersOutlook", ["mail"]], ["usersPeople", ["contacts"]], ["usersPerson", ["contacts"]], ["usersReminderView", ["calendar"]], ["usersSendMail", ["mail"]], ["usersTodo", ["tasks"]], ["usersUser", ["profile"]], ["usersUserActions", ["profile"]], ["usersUserFunctions", ["profile"]],]); const MICROSOFT_WORKBOOK_FIRST_SEGMENTS = new Set([ "drivesDriveItem", "groupsDrive", "meDrive", "usersDrive",]); const microsoftFirstSegmentOwnershipKey = (firstSegment: string): string | undefined => [...microsoftToolFirstSegmentPresetIds.keys()] .filter( (key) => firstSegment === key || (firstSegment.startsWith(key) && firstSegment[key.length]?.toUpperCase() === firstSegment[key.length]), ) .sort((left, right) => right.length - left.length)[0]; const serviceSlugForPreset = (family: MonolithPluginId, presetId: string): string | undefined => { const preset = family === "google" ? googleCatalogById.get(presetId) : microsoftCatalogByMonolithPresetId.get(presetId); return preset?.defaultSlug;}; const serviceTargetForPreset = ( family: MonolithPluginId, presetId: string,): ServiceTarget | undefined => { if (family === "google") { const preset = googleCatalogById.get(presetId); if (!preset) return undefined; return { family, pluginId: "openapi", presetId, slug: preset.defaultSlug ?? preset.id, name: preset.name, description: preset.summary, ...(preset.url ? { specUrl: preset.url } : {}), specFormat: "google-discovery", ...(preset.authTemplate ? { authenticationTemplate: preset.authTemplate } : {}), ...(preset.healthCheck ? { healthCheck: preset.healthCheck } : {}), }; } const preset = microsoftCatalogByMonolithPresetId.get(presetId); if (!preset) return undefined; return { family, pluginId: "openapi", presetId, slug: preset.defaultSlug ?? preset.id, name: preset.name, description: preset.summary, ...(preset.url ? { specUrl: preset.url } : {}), specFormat: "microsoft-graph", ...(preset.authTemplate ? { authenticationTemplate: preset.authTemplate } : {}),Lines 1–500 of 1347. Load more
/* oxlint-disable executor/no-try-catch-or-throw, executor/no-error-constructor, executor/no-instanceof-error, executor/no-unknown-error-message, executor/no-json-parse -- boundary: one-shot provider service split planner preserves the throwing dry-run contract used by migration tooling */ import { createHash } from "node:crypto"; import { googleCatalog, googlePresetForDiscoveryUrl, } from "@executor-js/plugin-openapi/providers/google"; import { MICROSOFT_GRAPH_DEFAULT_PRESET_IDS, microsoftCatalog, } from "@executor-js/plugin-openapi/providers/microsoft"; import type { IntegrationPreset } from "@executor-js/sdk/core"; type MonolithPluginId = "google" | "microsoft"; const normalizeUrl = (url: string): string => { const trimmed = url.trim(); if (!URL.canParse(trimmed)) return trimmed.replace(/\/$/, ""); const parsed = new URL(trimmed); parsed.hash = ""; parsed.searchParams.sort(); return parsed.toString().replace(/\/$/, ""); }; const googleCatalogByDiscoveryUrl = new Map( googleCatalog.flatMap((preset) => preset.url ? [[normalizeUrl(preset.url), preset] as const] : [], ), ); const matchPattern = (pattern: string, toolId: string): boolean => { if (pattern === "*") return true; const patternSegments = pattern.split("."); const toolSegments = toolId.split("."); for (let index = 0; index < patternSegments.length; index += 1) { const segment = patternSegments[index]!; if (segment === "*") { if (index === patternSegments.length - 1) return toolSegments.length >= index; if (index >= toolSegments.length) return false; continue; } if (index >= toolSegments.length || toolSegments[index] !== segment) return false; } return patternSegments.length === toolSegments.length; }; export type PluginId = "openapi"; export interface IntegrationRow { readonly tenant: string; readonly slug: string; readonly plugin_id: string; readonly name: string | null; readonly description: string | null; readonly config: unknown; readonly health_check?: unknown; readonly config_revised_at?: string | number | bigint | null; readonly can_remove: boolean; readonly can_refresh: boolean; readonly created_at: string; readonly updated_at: string; readonly row_id: string; } export interface ConnectionRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly integration: string; readonly name: string; readonly template: string; readonly provider: string; readonly item_ids: unknown; readonly identity_label: string | null; readonly description?: string | null; readonly last_health?: unknown; readonly tools_synced_at?: string | number | bigint | null; readonly oauth_client: string | null; readonly oauth_client_owner: string | null; readonly refresh_item_id: string | null; readonly expires_at: string | number | bigint | null; readonly oauth_scope: string | null; readonly oauth_token_url?: string | null; readonly provider_state: unknown; readonly created_at: string; readonly updated_at: string; readonly row_id: string; } export interface ToolRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly integration: string; readonly connection: string; readonly plugin_id: string; readonly name: string; readonly description?: string; readonly input_schema?: unknown; readonly output_schema?: unknown; readonly annotations?: unknown; readonly created_at?: string; readonly updated_at?: string; readonly row_id: string; } export interface PluginStorageRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly plugin_id: string; readonly collection: string; readonly key: string; readonly data: unknown; readonly created_at: string; readonly updated_at: string; readonly row_id: string; } export interface BlobRow { readonly id: string; readonly namespace: string; readonly key: string; } export interface ToolPolicyRow { readonly tenant: string; readonly owner: string; readonly subject: string; readonly id: string; readonly pattern: string; readonly action: string; readonly position: string; readonly created_at: string; readonly updated_at: string; readonly row_id: string; } export interface MigrationInput { readonly integrations: readonly IntegrationRow[]; readonly connections: readonly ConnectionRow[]; readonly tools: readonly ToolRow[]; readonly pluginStorage?: readonly PluginStorageRow[]; readonly blobs?: readonly BlobRow[]; readonly policies: readonly ToolPolicyRow[]; readonly completedTenants?: readonly string[]; readonly trafficLastTenant?: string; readonly collectPolicyErrors?: boolean; readonly orphanPolicyMode?: "hard_error" | "retarget_all"; readonly blobBackend?: "database" | "external"; readonly assumeExternalBlobSourcePresent?: boolean; readonly bootRailCreateToolImpliedServices?: boolean; } export interface ServiceTarget { readonly family: MonolithPluginId; readonly pluginId: PluginId; readonly presetId: string; readonly slug: string; readonly name: string; readonly description: string; readonly specUrl?: string; readonly specFormat: "google-discovery" | "microsoft-graph"; readonly authenticationTemplate?: readonly unknown[]; readonly healthCheck?: unknown; } export interface PlannedIntegration { readonly source: Pick<IntegrationRow, "tenant" | "slug" | "plugin_id" | "name">; readonly sourceContributions: readonly { readonly source: IntegrationRow; readonly specHash?: string; readonly operationsToBuild: number; readonly operationToolNames: readonly string[]; readonly specBlobPresent: boolean; readonly defsBlobPresent: boolean; }[]; readonly target: ServiceTarget; readonly action: "create" | "skip_existing"; readonly config: unknown; readonly healthCheck?: unknown; readonly servingState: { readonly specHash?: string; readonly specSource: string; readonly blobBackend: "database" | "external"; readonly specBlobPresent: boolean; readonly defsBlobPresent: boolean; readonly operationsToBuild: number; readonly operationToolNames: readonly string[]; readonly expectedZeroOperations: boolean; }; } export interface PlannedBlobCopy { readonly source: Pick<IntegrationRow, "tenant" | "slug" | "plugin_id">; readonly specHash: string; readonly key: string; readonly sourceNamespace: string; readonly targetNamespace: string; readonly backend: "database" | "external"; readonly sourcePresent: boolean; readonly targetPresent: boolean; readonly sourceObjectName: string; readonly targetObjectName: string; } export interface PlannedConnection { readonly source: Pick<ConnectionRow, "tenant" | "owner" | "subject" | "integration" | "name">; readonly targetIntegration: string; readonly action: "clone" | "skip_existing"; readonly tokenReuse: "copy_item_ids_and_oauth_columns"; } export interface PlannedPolicyRewrite { readonly policy: Pick< ToolPolicyRow, "tenant" | "owner" | "subject" | "id" | "pattern" | "action" | "position" >; readonly action: "rewrite"; readonly afterPatterns: readonly string[]; readonly matchedServices: readonly string[]; } export interface OrgPlan { readonly tenant: string; readonly tenantHash: string; readonly completed: boolean; readonly integrations: readonly PlannedIntegration[]; readonly connections: readonly PlannedConnection[]; readonly policies: readonly PlannedPolicyRewrite[]; readonly blobCopies: readonly PlannedBlobCopy[]; readonly deleteMonoliths: readonly Pick< IntegrationRow, "tenant" | "slug" | "plugin_id" | "name" >[]; readonly clonedToolRows: number; readonly operationsToBuild: number; readonly hardErrors: readonly string[]; } export interface MigrationPlan { readonly orgs: readonly OrgPlan[]; readonly summary: { readonly orgs: number; readonly completedOrgs: number; readonly integrationsCreate: number; readonly integrationsSkipExisting: number; readonly connectionsClone: number; readonly connectionsSkipExisting: number; readonly policiesRewrite: number; readonly policiesSkip: number; readonly policyRowsAfter: number; readonly monolithDeletes: number; readonly clonedToolRows: number; readonly operationsToBuild: number; readonly integrationsMissingSpecBlob: number; readonly integrationsMissingDefsBlob: number; readonly hardErrorOrgs: number; readonly policyHardErrors: number; }; } const GOOGLE_IDENTITY_DISCOVERY_URL = "https://www.googleapis.com/discovery/v1/apis/oauth2/v2/rest"; const GOOGLE_TOOL_PREFIX_TO_PRESET_ID: ReadonlyMap<string, string> = new Map([ ["calendar", "google-calendar"], ["gmail", "google-gmail"], ["sheets", "google-sheets"], ["drive", "google-drive"], ["docs", "google-docs"], ["slides", "google-slides"], ["forms", "google-forms"], ["tasks", "google-tasks"], ["people", "google-people"], ["photoslibrary", "google-photos-library"], ["photospicker", "google-photos-picker"], ["chat", "google-chat"], ["keep", "google-keep"], ["youtube", "google-youtube-data"], ["searchconsole", "google-search-console"], ["webmasters", "google-search-console"], ["classroom", "google-classroom"], ["directory", "google-admin-directory"], ["reports", "google-admin-reports"], ["script", "google-apps-script"], ["bigquery", "google-bigquery"], ["cloudresourcemanager", "google-cloud-resource-manager"], ]); const unique = <T>(values: Iterable<T>): readonly T[] => [...new Set(values)]; export const tenantHash = (tenant: string): string => createHash("sha256").update(tenant).digest("hex").slice(0, 12); const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value); const recordFromJsonLike = (value: unknown): Record<string, unknown> => { if (isRecord(value)) return value; if (typeof value !== "string") return {}; try { const parsed = JSON.parse(value) as unknown; return isRecord(parsed) ? parsed : {}; } catch { return {}; } }; const stringArray = (value: unknown): readonly string[] => Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : []; const configRecord = (integration: IntegrationRow): Record<string, unknown> => recordFromJsonLike(integration.config); const toolAddress = ( tool: Pick<ToolRow, "integration" | "owner" | "connection" | "name">, ): string => `${tool.integration}.${tool.owner}.${tool.connection}.${tool.name}`; const withoutToolsPrefix = (pattern: string): string => pattern.startsWith("tools.") ? pattern.slice("tools.".length) : pattern; const withOriginalToolsPrefix = (original: string, rewrittenTail: string): string => original.startsWith("tools.") ? `tools.${rewrittenTail}` : rewrittenTail; const integrationPatternSegment = ( pattern: string, ): { readonly prefix: boolean; readonly integration: string } => { const prefix = pattern.startsWith("tools."); const tail = prefix ? pattern.slice("tools.".length) : pattern; return { prefix, integration: tail.split(".")[0] ?? "" }; }; const googleCatalogById: ReadonlyMap<string, IntegrationPreset> = new Map( googleCatalog.map((preset) => [preset.id, preset]), ); const microsoftCatalogByMonolithPresetId: ReadonlyMap<string, IntegrationPreset> = new Map( microsoftCatalog.map((preset) => [preset.id.replace(/^microsoft-/, ""), preset]), ); const MICROSOFT_UNMIGRATABLE_UMBRELLA_PRESET_IDS = new Set(["me-surface", "users", "groups"]); const MICROSOFT_TOOL_IMPLIED_PRESET_IDS = new Set(MICROSOFT_GRAPH_DEFAULT_PRESET_IDS); const microsoftCatalogBackedPresetIds = new Set( microsoftCatalog .filter((preset) => preset.defaultSlug && preset.defaultSlug.length > 0) .map((preset) => preset.id.replace(/^microsoft-/, "")), ); export const microsoftToolFirstSegmentPresetIds: ReadonlyMap<string, readonly string[]> = new Map([ ["chats", ["teams-chat"]], ["chatsChat", ["teams-chat"]], ["communications", ["meetings-calls"]], ["communicationsCall", ["meetings-calls"]], ["communicationsOnlineMeeting", ["meetings-calls"]], ["communicationsPresence", ["meetings-calls"]], ["drives", ["files"]], ["drivesDrive", ["files"]], ["drivesDriveItem", ["files"]], ["groupsDrive", ["files"]], ["groupsDrives", ["files"]], ["groupsOnenote", ["onenote"]], ["groupsTeam", ["teams-channels"]], ["meCalendar", ["calendar"]], ["meCalendarGroups", ["calendar"]], ["meCalendars", ["calendar"]], ["meCalendarView", ["calendar"]], ["meChat", ["teams-chat"]], ["meChats", ["teams-chat"]], ["meContact", ["contacts"]], ["meContactFolder", ["contacts"]], ["meContactFolders", ["contacts"]], ["meContacts", ["contacts"]], ["meDrive", ["files"]], ["meDrives", ["files"]], ["meEvent", ["calendar"]], ["meEvents", ["calendar"]], ["meFindMeetingTimes", ["calendar"]], ["meFollowedSites", ["files"]], ["meGetMailTips", ["mail"]], ["meInferenceClassification", ["mail"]], ["meJoinedTeams", ["teams-channels"]], ["meMailFolder", ["mail"]], ["meMailFolders", ["mail"]], ["meMailboxSettings", ["mail"]], ["meMessage", ["mail"]], ["meMessages", ["mail"]], ["meOnlineMeeting", ["meetings-calls"]], ["meOnlineMeetings", ["meetings-calls"]], ["meOnenote", ["onenote"]], ["meOutlook", ["mail"]], ["meOutlookUser", ["mail"]], ["mePeople", ["contacts"]], ["mePerson", ["contacts"]], ["mePhoto", ["profile"]], ["meProfilePhoto", ["profile"]], ["meReminderView", ["calendar"]], ["meSendMail", ["mail"]], ["meSite", ["files"]], ["meTeam", ["teams-channels"]], ["meTodo", ["tasks"]], ["meUser", ["profile"]], ["meUserActions", ["profile"]], ["meUserFunctions", ["profile"]], ["shares", ["files"]], ["sites", ["sites"]], ["sitesOnenote", ["onenote"]], ["sitesSite", ["sites"]], ["teams", ["teams-channels"]], ["teamsChannel", ["teams-channels"]], ["teamsTeam", ["teams-channels"]], ["teamsTemplates", ["teams-channels"]], ["teamwork", ["teams-channels"]], ["usersCalendar", ["calendar"]], ["usersCalendarGroups", ["calendar"]], ["usersCalendars", ["calendar"]], ["usersCalendarView", ["calendar"]], ["usersContact", ["contacts"]], ["usersContactFolder", ["contacts"]], ["usersContactFolders", ["contacts"]], ["usersContacts", ["contacts"]], ["usersDrive", ["files"]], ["usersDrives", ["files"]], ["usersEvent", ["calendar"]], ["usersEvents", ["calendar"]], ["usersFindMeetingTimes", ["calendar"]], ["usersMailFolder", ["mail"]], ["usersMailFolders", ["mail"]], ["usersMessage", ["mail"]], ["usersMessages", ["mail"]], ["usersOnlineMeeting", ["meetings-calls"]], ["usersOnlineMeetings", ["meetings-calls"]], ["usersOnenote", ["onenote"]], ["usersOutlook", ["mail"]], ["usersPeople", ["contacts"]], ["usersPerson", ["contacts"]], ["usersReminderView", ["calendar"]], ["usersSendMail", ["mail"]], ["usersTodo", ["tasks"]], ["usersUser", ["profile"]], ["usersUserActions", ["profile"]], ["usersUserFunctions", ["profile"]], ]); const MICROSOFT_WORKBOOK_FIRST_SEGMENTS = new Set([ "drivesDriveItem", "groupsDrive", "meDrive", "usersDrive", ]); const microsoftFirstSegmentOwnershipKey = (firstSegment: string): string | undefined => [...microsoftToolFirstSegmentPresetIds.keys()] .filter( (key) => firstSegment === key || (firstSegment.startsWith(key) && firstSegment[key.length]?.toUpperCase() === firstSegment[key.length]), ) .sort((left, right) => right.length - left.length)[0]; const serviceSlugForPreset = (family: MonolithPluginId, presetId: string): string | undefined => { const preset = family === "google" ? googleCatalogById.get(presetId) : microsoftCatalogByMonolithPresetId.get(presetId); return preset?.defaultSlug; }; const serviceTargetForPreset = ( family: MonolithPluginId, presetId: string, ): ServiceTarget | undefined => { if (family === "google") { const preset = googleCatalogById.get(presetId); if (!preset) return undefined; return { family, pluginId: "openapi", presetId, slug: preset.defaultSlug ?? preset.id, name: preset.name, description: preset.summary, ...(preset.url ? { specUrl: preset.url } : {}), specFormat: "google-discovery", ...(preset.authTemplate ? { authenticationTemplate: preset.authTemplate } : {}), ...(preset.healthCheck ? { healthCheck: preset.healthCheck } : {}), }; } const preset = microsoftCatalogByMonolithPresetId.get(presetId); if (!preset) return undefined; return { family, pluginId: "openapi", presetId, slug: preset.defaultSlug ?? preset.id, name: preset.name, description: preset.summary, ...(preset.url ? { specUrl: preset.url } : {}), specFormat: "microsoft-graph", ...(preset.authTemplate ? { authenticationTemplate: preset.authTemplate } : {}),