1179 lines · 40.3 KB · TypeScript
RawDownload
import { createHash } from "node:crypto"; interface ServicePreset {  readonly id: string;  readonly name: string;  readonly summary: string;  readonly url?: string;  readonly scopes?: readonly string[];} const gd = (service: string, version: string): string =>  `https://www.googleapis.com/discovery/v1/apis/${service}/${version}/rest`; const googleOpenApiPresets: readonly ServicePreset[] = [  {    id: "google-calendar",    name: "Google Calendar",    summary: "Calendars, events, ACLs, and scheduling.",    url: gd("calendar", "v3"),  },  {    id: "google-gmail",    name: "Gmail",    summary: "Messages, threads, labels, and drafts.",    url: gd("gmail", "v1"),  },  {    id: "google-sheets",    name: "Google Sheets",    summary: "Spreadsheets, values, ranges, and formatting.",    url: gd("sheets", "v4"),  },  {    id: "google-drive",    name: "Google Drive",    summary: "Files, folders, permissions, and shared drives.",    url: gd("drive", "v3"),  },  {    id: "google-docs",    name: "Google Docs",    summary: "Documents, structural edits, and formatting.",    url: gd("docs", "v1"),  },  {    id: "google-slides",    name: "Google Slides",    summary: "Presentations, slides, page elements, and deck updates.",    url: gd("slides", "v1"),  },  {    id: "google-forms",    name: "Google Forms",    summary: "Forms, questions, responses, and quizzes.",    url: "https://forms.googleapis.com/$discovery/rest?version=v1",  },  {    id: "google-tasks",    name: "Google Tasks",    summary: "Task lists, task items, notes, and due dates.",    url: gd("tasks", "v1"),  },  {    id: "google-people",    name: "Google People",    summary: "Contacts, profiles, directory people, and contact groups.",    url: gd("people", "v1"),  },  {    id: "google-photos-library",    name: "Google Photos Library",    summary: "Albums, uploads, and app-created media through Google Photos.",    url: gd("photoslibrary", "v1"),  },  {    id: "google-photos-picker",    name: "Google Photos Picker",    summary: "Picker sessions and user-selected Google Photos media items.",    url: "https://photospicker.googleapis.com/$discovery/rest?version=v1",  },  {    id: "google-chat",    name: "Google Chat",    summary: "Spaces, messages, members, reactions, and chat workflows.",    url: gd("chat", "v1"),  },  {    id: "google-keep",    name: "Google Keep",    summary: "Notes, lists, attachments, and annotations.",    url: "https://keep.googleapis.com/$discovery/rest?version=v1",  },  {    id: "google-youtube-data",    name: "YouTube Data",    summary: "Channels, playlists, videos, comments, and uploads.",    url: gd("youtube", "v3"),  },  {    id: "google-search-console",    name: "Google Search Console",    summary: "Sites, sitemaps, URL inspection, and search performance.",    url: gd("searchconsole", "v1"),  },  {    id: "google-classroom",    name: "Google Classroom",    summary: "Courses, rosters, coursework, and grading.",    url: gd("classroom", "v1"),  },  {    id: "google-admin-directory",    name: "Google Admin Directory",    summary: "Users, groups, org units, roles, and domain resources.",    url: "https://www.googleapis.com/discovery/v1/apis/admin/directory_v1/rest",  },  {    id: "google-admin-reports",    name: "Google Admin Reports",    summary: "Audit events, usage reports, and admin activity logs.",    url: "https://www.googleapis.com/discovery/v1/apis/admin/reports_v1/rest",  },  {    id: "google-apps-script",    name: "Google Apps Script",    summary: "Projects, deployments, and script execution.",    url: gd("script", "v1"),  },  {    id: "google-bigquery",    name: "Google BigQuery",    summary: "Datasets, tables, jobs, and analytical queries.",    url: gd("bigquery", "v2"),  },  {    id: "google-cloud-resource-manager",    name: "Google Cloud Resource Manager",    summary: "Projects, folders, organizations, and IAM hierarchy.",    url: "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v3",  },]; const microsoftGraphScopePresets: readonly ServicePreset[] = [  {    id: "profile",    name: "Profile",    summary: "Signed-in user profile and photo.",    scopes: ["User.Read"],  },  {    id: "me-surface",    name: "My Graph Operations",    summary: "All operation groups rooted under /me.",    scopes: ["User.Read"],  },  {    id: "mail",    name: "Outlook Mail",    summary: "Messages, folders, attachments, settings, and send mail.",    scopes: ["Mail.ReadWrite", "Mail.Send", "MailboxSettings.ReadWrite"],  },  {    id: "calendar",    name: "Outlook Calendar",    summary: "Calendars, events, and scheduling.",    scopes: ["Calendars.ReadWrite"],  },  {    id: "contacts",    name: "Outlook Contacts",    summary: "Contacts, contact folders, and people suggestions.",    scopes: ["Contacts.ReadWrite", "People.Read.All"],  },  {    id: "tasks",    name: "To Do Tasks",    summary: "Task lists, tasks, and checklist items.",    scopes: ["Tasks.ReadWrite"],  },  {    id: "planner",    name: "Planner",    summary: "Plans, buckets, tasks, assignments, and Planner user data.",    scopes: ["Tasks.ReadWrite"],  },  {    id: "files",    name: "OneDrive Files",    summary: "Drives, files, folders, sharing links, and permissions.",    scopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"],  },  {    id: "excel",    name: "Excel Workbooks",    summary: "Workbook tables, worksheets, ranges, charts, and sessions.",    scopes: ["Files.ReadWrite.All"],  },  {    id: "sites",    name: "SharePoint Sites",    summary: "Sites, lists, pages, columns, content types, and stores.",    scopes: ["Sites.ReadWrite.All"],  },  {    id: "onenote",    name: "OneNote",    summary: "Notebooks, sections, pages, and page content.",    scopes: ["Notes.ReadWrite"],  },  {    id: "teams-chat",    name: "Teams Chats",    summary: "Chats, chat messages, installed apps, and members.",    scopes: ["Chat.ReadWrite"],  },  {    id: "teams-channels",    name: "Teams Channels",    summary: "Teams, channels, channel messages, replies, and joined teams.",    scopes: [      "Team.ReadBasic.All",      "Channel.ReadBasic.All",      "ChannelMessage.Read.All",      "ChannelMessage.Send",    ],  },  {    id: "meetings-calls",    name: "Meetings and Calls",    summary: "Online meetings, calls, call records, and presence.",    scopes: ["OnlineMeetings.ReadWrite", "Calls.AccessMedia.All"],  },]; const MICROSOFT_GRAPH_DEFAULT_PRESET_IDS: readonly string[] = [  "profile",  "mail",  "calendar",  "contacts",  "tasks",  "files",  "excel",  "sites",  "onenote",  "teams-chat",  "teams-channels",  "meetings-calls",]; const googleServiceSlug = (presetId: string): string => presetId.replaceAll("-", "_");const microsoftServiceSlug = (presetId: string): string =>  `microsoft_${presetId.replaceAll("-", "_")}`;const microsoftGraphScopesForPresetIds = (  presetIds: Iterable<string>,  customScopes: Iterable<string> = [],): readonly string[] =>  unique([    ...[...presetIds].flatMap((presetId) => microsoftPresetById.get(presetId)?.scopes ?? []),    ...customScopes,  ]); 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 googlePresetByNormalizedUrl = new Map(  googleOpenApiPresets.flatMap((preset) =>    preset.url ? [[normalizeUrl(preset.url), preset] as const] : [],  ),); const googlePresetForDiscoveryUrl = (url: string): ServicePreset | undefined =>  googlePresetByNormalizedUrl.get(normalizeUrl(url)); 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 = "google" | "microsoft"; 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 blobBackend?: "database" | "external";} export interface ServiceTarget {  readonly pluginId: PluginId;  readonly presetId: string;  readonly slug: string;  readonly name: string;  readonly description: string;} export interface PlannedIntegration {  readonly source: Pick<IntegrationRow, "tenant" | "slug" | "plugin_id" | "name">;  readonly target: ServiceTarget;  readonly action: "create" | "skip_existing";  readonly config: 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[];  };} 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 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"],  ["admin", "google-admin-directory"],

Lines 1–500 of 1179.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t