@backstage/plugin-catalog-backend-module-msgraph-incremental 0.1.4 → 0.1.5-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend-module-msgraph-incremental
|
|
2
2
|
|
|
3
|
+
## 0.1.5-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-plugin-api@1.11.0-next.1
|
|
9
|
+
- @backstage/plugin-catalog-backend-module-incremental-ingestion@0.9.0-next.1
|
|
10
|
+
- @backstage/plugin-catalog-backend-module-msgraph@0.10.7-next.1
|
|
11
|
+
- @backstage/plugin-catalog-node@2.2.6-next.1
|
|
12
|
+
|
|
13
|
+
## 0.1.5-next.0
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @backstage/config@1.3.10-next.0
|
|
19
|
+
- @backstage/plugin-catalog-backend-module-incremental-ingestion@0.9.0-next.0
|
|
20
|
+
- @backstage/backend-plugin-api@1.10.2-next.0
|
|
21
|
+
- @backstage/plugin-catalog-backend-module-msgraph@0.10.7-next.0
|
|
22
|
+
- @backstage/catalog-model@1.10.2-next.0
|
|
23
|
+
- @backstage/plugin-catalog-node@2.2.6-next.0
|
|
24
|
+
|
|
3
25
|
## 0.1.4
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MicrosoftGraphIncrementalEntityProvider.cjs.js","sources":["../src/MicrosoftGraphIncrementalEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport crypto from 'node:crypto';\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n IncrementalEntityProvider,\n EntityIteratorResult,\n} from '@backstage/plugin-catalog-backend-module-incremental-ingestion';\nimport { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport limiterFactory from 'p-limit';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport {\n GroupTransformer,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n ProviderConfigTransformer,\n UserTransformer,\n defaultGroupTransformer,\n defaultOrganizationTransformer,\n defaultUserTransformer,\n readProviderConfigs,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { getUserPhotoGated, requestOnePage } from './clientHelpers';\n\nconst USER_PAGE_SIZE = 999;\n// Groups phase fetches members for every group on the page, so a smaller page\n// size keeps each burst within its time budget.\nconst GROUP_PAGE_SIZE = 100;\n\n/**\n * Backstage entity names must be ≤63 chars ([a-zA-Z0-9] separated by [-_.]).\n * When MS Graph UPNs exceed that (e.g. calendar/booking accounts), we truncate\n * to 54 chars and append an 8-char SHA-1 hash to preserve uniqueness.\n */\nfunction capEntityName(name: string): string {\n if (name.length <= 63) return name;\n const hash = crypto.createHash('sha1').update(name).digest('hex').slice(0, 8);\n return `${name.slice(0, 54)}_${hash}`;\n}\n\n/** Stamps `annotations.backstage.io/location` on an entity using the MS Graph UID. */\nfunction withLocations(providerId: string, entity: Entity): Entity {\n const uid =\n entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] ||\n entity.metadata.name;\n const location = `msgraph:${providerId}/${encodeURIComponent(uid)}`;\n return {\n ...entity,\n metadata: {\n ...entity.metadata,\n annotations: {\n ...entity.metadata.annotations,\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n };\n}\n\n/**\n * Pagination cursor used by {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * The `nextLink` field holds the `@odata.nextLink` URL returned by the\n * Microsoft Graph API, which encodes all state needed to resume a paged\n * request. An absent value means the current phase is starting fresh.\n *\n * @public\n */\nexport type MSGraphCursor = {\n phase: 'users' | 'groups';\n nextLink?: string;\n};\n\n/**\n * Context passed to each burst of {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * @public\n */\nexport type MSGraphContext = {\n client: MicrosoftGraphClient;\n provider: MicrosoftGraphProviderConfig;\n};\n\n/**\n * Options for {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * @public\n */\nexport interface MicrosoftGraphIncrementalEntityProviderOptions {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n userTransformer?: UserTransformer | Record<string, UserTransformer>;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n organizationTransformer?:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>;\n\n /**\n * The function that transforms provider config dynamically before each sync.\n * Optionally, you can pass separate transformers per provider ID.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\n}\n\n/**\n * Incrementally reads user and group entries out of Microsoft Graph, one page\n * at a time, and provides them as User and Group entities for the catalog.\n *\n * Unlike `MicrosoftGraphOrgEntityProvider`, this provider never holds the full\n * dataset in memory at once. Each burst processes a single page (up to 999\n * users or 100 groups). This makes it suitable for very large tenants and\n * avoids the memory pressure and long-running task issues of the full-scan\n * provider.\n *\n * The Microsoft Graph `@odata.nextLink` URL is stored as the cursor, so a pod\n * restart during ingestion resumes from the last completed page.\n *\n * Group membership (`spec.members`) is resolved inline during the groups phase\n * by fetching the direct members of each group. The catalog's built-in relation\n * stitching derives `spec.memberOf` on users from these group membership lists.\n *\n * @remarks\n * `userGroupMemberFilter`, `userGroupMemberSearch`, `userGroupMemberPath`, and\n * `groupIncludeSubGroups` are not supported. Use `userFilter` / `userPath` to\n * restrict which users are ingested, and `groupFilter` / `groupSearch` to\n * restrict which groups. Switch to `MicrosoftGraphOrgEntityProvider` if you\n * require any of these options.\n *\n * @public\n */\nexport class MicrosoftGraphIncrementalEntityProvider\n implements IncrementalEntityProvider<MSGraphCursor, MSGraphContext>\n{\n /**\n * Create one provider instance per provider entry in\n * `catalog.providers.microsoftGraphOrg`.\n */\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphIncrementalEntityProviderOptions,\n ): MicrosoftGraphIncrementalEntityProvider[] {\n function getTransformer<T extends Function>(\n id: string,\n transformers?: T | Record<string, T>,\n ): T | undefined {\n if (['undefined', 'function'].includes(typeof transformers)) {\n return transformers as T;\n }\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(\n providerConfig =>\n new MicrosoftGraphIncrementalEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger: options.logger,\n userTransformer: getTransformer(\n providerConfig.id,\n options.userTransformer,\n ),\n groupTransformer: getTransformer(\n providerConfig.id,\n options.groupTransformer,\n ),\n organizationTransformer: getTransformer(\n providerConfig.id,\n options.organizationTransformer,\n ),\n providerConfigTransformer: getTransformer(\n providerConfig.id,\n options.providerConfigTransformer,\n ),\n }),\n );\n }\n\n private readonly options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n };\n\n constructor(options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n }) {\n this.options = options;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend-module-incremental-ingestion#IncrementalEntityProvider.getProviderName} */\n getProviderName(): string {\n return `MicrosoftGraphIncrementalEntityProvider:${this.options.id}`;\n }\n\n /**\n * Sets up the Microsoft Graph client for the duration of a full ingestion\n * cycle. The optional `providerConfigTransformer` is applied here so that\n * dynamic config changes (e.g., rotating credentials) take effect at the\n * start of each cycle rather than mid-way through.\n */\n async around(\n burst: (context: MSGraphContext) => Promise<void>,\n ): Promise<void> {\n const provider = this.options.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n\n if (\n provider.userGroupMemberFilter ||\n provider.userGroupMemberSearch ||\n provider.userGroupMemberPath\n ) {\n this.options.logger.warn(\n `${this.getProviderName()}: userGroupMemberFilter/Search/Path are not supported by ` +\n `MicrosoftGraphIncrementalEntityProvider. Users will be fetched via the standard ` +\n `userFilter/userPath options instead. Switch to MicrosoftGraphOrgEntityProvider if ` +\n `you require userGroupMember-based ingestion.`,\n );\n }\n\n if (provider.groupIncludeSubGroups) {\n this.options.logger.warn(\n `${this.getProviderName()}: groupIncludeSubGroups is not supported by ` +\n `MicrosoftGraphIncrementalEntityProvider and will be ignored. ` +\n `Switch to MicrosoftGraphOrgEntityProvider if you require this option.`,\n );\n }\n\n const client = MicrosoftGraphClient.create(provider);\n await burst({ client, provider });\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend-module-incremental-ingestion#IncrementalEntityProvider.next} */\n async next(\n { client, provider }: MSGraphContext,\n cursor?: MSGraphCursor,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const phase = cursor?.phase ?? 'users';\n const nextLink = cursor?.nextLink;\n\n if (phase === 'users') {\n return this.readUsersPage(client, provider, nextLink);\n }\n return this.readGroupsPage(client, provider, nextLink);\n }\n\n private async readUsersPage(\n client: MicrosoftGraphClient,\n provider: MicrosoftGraphProviderConfig,\n nextLink: string | undefined,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const { items: rawUsers, nextLink: newNextLink } =\n await requestOnePage<MicrosoftGraph.User>(\n client,\n provider.userPath ?? 'users',\n {\n query: {\n filter: provider.userFilter,\n expand: provider.userExpand,\n select: provider.userSelect,\n top: USER_PAGE_SIZE,\n },\n queryMode: provider.queryMode,\n nextLink,\n },\n );\n\n const transformer = this.options.userTransformer ?? defaultUserTransformer;\n const limiter = limiterFactory(10);\n const entities: DeferredEntity[] = [];\n\n await Promise.all(\n rawUsers.map(user =>\n limiter(async () => {\n let userPhoto: string | undefined;\n if (user.id && provider.loadUserPhotos !== false) {\n try {\n userPhoto = await getUserPhotoGated(client, user.id, 120);\n } catch (e) {\n this.options.logger.debug(\n `${this.getProviderName()}: failed to load photo for user ${\n user.id\n }`,\n { error: e },\n );\n }\n }\n\n const entity = await transformer(user, userPhoto);\n if (entity) {\n entity.metadata.name = capEntityName(entity.metadata.name);\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n });\n }\n }),\n ),\n );\n\n this.options.logger.debug(\n `${this.getProviderName()}: read ${entities.length} users`,\n { phase: 'users', hasNextPage: !!newNextLink },\n );\n\n if (newNextLink) {\n return {\n done: false,\n entities,\n cursor: { phase: 'users', nextLink: newNextLink },\n };\n }\n\n return {\n done: false,\n entities,\n cursor: { phase: 'groups' },\n };\n }\n\n private async readGroupsPage(\n client: MicrosoftGraphClient,\n provider: MicrosoftGraphProviderConfig,\n nextLink: string | undefined,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const { items: rawGroups, nextLink: newNextLink } =\n await requestOnePage<MicrosoftGraph.Group>(\n client,\n provider.groupPath ?? 'groups',\n {\n query: {\n filter: provider.groupFilter,\n search: provider.groupSearch,\n expand: provider.groupExpand,\n select: provider.groupSelect,\n top: GROUP_PAGE_SIZE,\n },\n queryMode: provider.queryMode,\n nextLink,\n },\n );\n\n const groupTransformer =\n this.options.groupTransformer ?? defaultGroupTransformer;\n const userTransformer =\n this.options.userTransformer ?? defaultUserTransformer;\n const limiter = limiterFactory(10);\n const entities: DeferredEntity[] = [];\n\n // Emit the tenant root group on the very first groups page\n if (!nextLink) {\n try {\n const organization = await client.getOrganization(provider.tenantId);\n const orgTransformer =\n this.options.organizationTransformer ??\n defaultOrganizationTransformer;\n const rootGroup = await orgTransformer(organization);\n if (rootGroup) {\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, rootGroup),\n });\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: failed to read organization root group`,\n { error: e },\n );\n }\n }\n\n await Promise.all(\n rawGroups.map(group =>\n limiter(async () => {\n const entity = await groupTransformer(group);\n if (!entity) {\n return;\n }\n entity.metadata.name = capEntityName(entity.metadata.name);\n\n const userRefs: string[] = [];\n const childRefs: string[] = [];\n\n for await (const member of client.getGroupMembers(group.id!, {\n top: GROUP_PAGE_SIZE,\n // Request the minimum fields needed by defaultUserTransformer and\n // defaultGroupTransformer so member objects are never sparse.\n select: [\n 'id',\n 'displayName',\n 'mail',\n 'mailNickname',\n 'userPrincipalName',\n 'description',\n 'securityEnabled',\n ],\n })) {\n if (member['@odata.type'] === '#microsoft.graph.user') {\n try {\n const userEntity = await userTransformer(\n member as MicrosoftGraph.User,\n );\n if (userEntity) {\n userEntity.metadata.name = capEntityName(\n userEntity.metadata.name,\n );\n userRefs.push(stringifyEntityRef(userEntity));\n } else {\n this.options.logger.debug(\n `${this.getProviderName()}: group member user ${\n member.id\n } could not be transformed (sparse object?), skipping`,\n );\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: group member user ${\n member.id\n } failed to transform, skipping`,\n { error: e },\n );\n }\n } else if (member['@odata.type'] === '#microsoft.graph.group') {\n // Only emit child refs when no group filter/search is active.\n // With a filter, child groups may not be ingested themselves,\n // which would produce dangling spec.children references.\n if (!provider.groupFilter && !provider.groupSearch) {\n try {\n const childEntity = await groupTransformer(\n member as MicrosoftGraph.Group,\n );\n if (childEntity) {\n childEntity.metadata.name = capEntityName(\n childEntity.metadata.name,\n );\n childRefs.push(stringifyEntityRef(childEntity));\n } else {\n this.options.logger.debug(\n `${this.getProviderName()}: group member child group ${\n member.id\n } could not be transformed (sparse object?), skipping`,\n );\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: group member child group ${\n member.id\n } failed to transform, skipping`,\n { error: e },\n );\n }\n }\n }\n }\n\n // Merge fetched membership with any members/children the transformer\n // may have pre-populated, so custom transformers can augment the list.\n const existingMembers = Array.isArray(entity.spec?.members)\n ? (entity.spec.members as string[])\n : [];\n const existingChildren = Array.isArray(entity.spec?.children)\n ? (entity.spec.children as string[])\n : [];\n\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, {\n ...entity,\n spec: {\n ...entity.spec,\n members: [...new Set([...existingMembers, ...userRefs])],\n children: [...new Set([...existingChildren, ...childRefs])],\n },\n }),\n });\n }),\n ),\n );\n\n this.options.logger.debug(\n `${this.getProviderName()}: read ${rawGroups.length} groups`,\n { phase: 'groups', hasNextPage: !!newNextLink },\n );\n\n if (newNextLink) {\n return {\n done: false,\n entities,\n cursor: { phase: 'groups', nextLink: newNextLink },\n };\n }\n\n return { done: true, entities };\n }\n}\n"],"names":["crypto","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION","readProviderConfigs","MicrosoftGraphClient","requestOnePage","defaultUserTransformer","limiterFactory","getUserPhotoGated","defaultGroupTransformer","defaultOrganizationTransformer","stringifyEntityRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MicrosoftGraphIncrementalEntityProvider.cjs.js","sources":["../src/MicrosoftGraphIncrementalEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport crypto from 'node:crypto';\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n IncrementalEntityProvider,\n EntityIteratorResult,\n} from '@backstage/plugin-catalog-backend-module-incremental-ingestion';\nimport { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport limiterFactory from 'p-limit';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport {\n GroupTransformer,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n ProviderConfigTransformer,\n UserTransformer,\n defaultGroupTransformer,\n defaultOrganizationTransformer,\n defaultUserTransformer,\n readProviderConfigs,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { getUserPhotoGated, requestOnePage } from './clientHelpers';\n\nconst USER_PAGE_SIZE = 999;\n// Groups phase fetches members for every group on the page, so a smaller page\n// size keeps each burst within its time budget.\nconst GROUP_PAGE_SIZE = 100;\n\n/**\n * Backstage entity names must be ≤63 chars ([a-zA-Z0-9] separated by [-_.]).\n * When MS Graph UPNs exceed that (e.g. calendar/booking accounts), we truncate\n * to 54 chars and append an 8-char SHA-1 hash to preserve uniqueness.\n */\nfunction capEntityName(name: string): string {\n if (name.length <= 63) return name;\n const hash = crypto.createHash('sha1').update(name).digest('hex').slice(0, 8);\n return `${name.slice(0, 54)}_${hash}`;\n}\n\n/** Stamps `annotations.backstage.io/location` on an entity using the MS Graph UID. */\nfunction withLocations(providerId: string, entity: Entity): Entity {\n const uid =\n entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] ||\n entity.metadata.name;\n const location = `msgraph:${providerId}/${encodeURIComponent(uid)}`;\n return {\n ...entity,\n metadata: {\n ...entity.metadata,\n annotations: {\n ...entity.metadata.annotations,\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n };\n}\n\n/**\n * Pagination cursor used by {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * The `nextLink` field holds the `@odata.nextLink` URL returned by the\n * Microsoft Graph API, which encodes all state needed to resume a paged\n * request. An absent value means the current phase is starting fresh.\n *\n * @public\n */\nexport type MSGraphCursor = {\n phase: 'users' | 'groups';\n nextLink?: string;\n};\n\n/**\n * Context passed to each burst of {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * @public\n */\nexport type MSGraphContext = {\n client: MicrosoftGraphClient;\n provider: MicrosoftGraphProviderConfig;\n};\n\n/**\n * Options for {@link MicrosoftGraphIncrementalEntityProvider}.\n *\n * @public\n */\nexport interface MicrosoftGraphIncrementalEntityProviderOptions {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n userTransformer?: UserTransformer | Record<string, UserTransformer>;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n organizationTransformer?:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>;\n\n /**\n * The function that transforms provider config dynamically before each sync.\n * Optionally, you can pass separate transformers per provider ID.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\n}\n\n/**\n * Incrementally reads user and group entries out of Microsoft Graph, one page\n * at a time, and provides them as User and Group entities for the catalog.\n *\n * Unlike `MicrosoftGraphOrgEntityProvider`, this provider never holds the full\n * dataset in memory at once. Each burst processes a single page (up to 999\n * users or 100 groups). This makes it suitable for very large tenants and\n * avoids the memory pressure and long-running task issues of the full-scan\n * provider.\n *\n * The Microsoft Graph `@odata.nextLink` URL is stored as the cursor, so a pod\n * restart during ingestion resumes from the last completed page.\n *\n * Group membership (`spec.members`) is resolved inline during the groups phase\n * by fetching the direct members of each group. The catalog's built-in relation\n * stitching derives `spec.memberOf` on users from these group membership lists.\n *\n * @remarks\n * `userGroupMemberFilter`, `userGroupMemberSearch`, `userGroupMemberPath`, and\n * `groupIncludeSubGroups` are not supported. Use `userFilter` / `userPath` to\n * restrict which users are ingested, and `groupFilter` / `groupSearch` to\n * restrict which groups. Switch to `MicrosoftGraphOrgEntityProvider` if you\n * require any of these options.\n *\n * @public\n */\nexport class MicrosoftGraphIncrementalEntityProvider\n implements IncrementalEntityProvider<MSGraphCursor, MSGraphContext>\n{\n /**\n * Create one provider instance per provider entry in\n * `catalog.providers.microsoftGraphOrg`.\n */\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphIncrementalEntityProviderOptions,\n ): MicrosoftGraphIncrementalEntityProvider[] {\n function getTransformer<T extends Function>(\n id: string,\n transformers?: T | Record<string, T>,\n ): T | undefined {\n if (['undefined', 'function'].includes(typeof transformers)) {\n return transformers as T;\n }\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(\n providerConfig =>\n new MicrosoftGraphIncrementalEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger: options.logger,\n userTransformer: getTransformer(\n providerConfig.id,\n options.userTransformer,\n ),\n groupTransformer: getTransformer(\n providerConfig.id,\n options.groupTransformer,\n ),\n organizationTransformer: getTransformer(\n providerConfig.id,\n options.organizationTransformer,\n ),\n providerConfigTransformer: getTransformer(\n providerConfig.id,\n options.providerConfigTransformer,\n ),\n }),\n );\n }\n\n private readonly options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n };\n\n constructor(options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n }) {\n this.options = options;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend-module-incremental-ingestion#IncrementalEntityProvider.getProviderName} */\n getProviderName(): string {\n return `MicrosoftGraphIncrementalEntityProvider:${this.options.id}`;\n }\n\n /**\n * Sets up the Microsoft Graph client for the duration of a full ingestion\n * cycle. The optional `providerConfigTransformer` is applied here so that\n * dynamic config changes (e.g., rotating credentials) take effect at the\n * start of each cycle rather than mid-way through.\n */\n async around(\n burst: (context: MSGraphContext) => Promise<void>,\n ): Promise<void> {\n const provider = this.options.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n\n if (\n provider.userGroupMemberFilter ||\n provider.userGroupMemberSearch ||\n provider.userGroupMemberPath\n ) {\n this.options.logger.warn(\n `${this.getProviderName()}: userGroupMemberFilter/Search/Path are not supported by ` +\n `MicrosoftGraphIncrementalEntityProvider. Users will be fetched via the standard ` +\n `userFilter/userPath options instead. Switch to MicrosoftGraphOrgEntityProvider if ` +\n `you require userGroupMember-based ingestion.`,\n );\n }\n\n if (provider.groupIncludeSubGroups) {\n this.options.logger.warn(\n `${this.getProviderName()}: groupIncludeSubGroups is not supported by ` +\n `MicrosoftGraphIncrementalEntityProvider and will be ignored. ` +\n `Switch to MicrosoftGraphOrgEntityProvider if you require this option.`,\n );\n }\n\n const client = MicrosoftGraphClient.create(provider);\n await burst({ client, provider });\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend-module-incremental-ingestion#IncrementalEntityProvider.next} */\n async next(\n { client, provider }: MSGraphContext,\n cursor?: MSGraphCursor,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const phase = cursor?.phase ?? 'users';\n const nextLink = cursor?.nextLink;\n\n if (phase === 'users') {\n return this.readUsersPage(client, provider, nextLink);\n }\n return this.readGroupsPage(client, provider, nextLink);\n }\n\n private async readUsersPage(\n client: MicrosoftGraphClient,\n provider: MicrosoftGraphProviderConfig,\n nextLink: string | undefined,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const { items: rawUsers, nextLink: newNextLink } =\n await requestOnePage<MicrosoftGraph.User>(\n client,\n provider.userPath ?? 'users',\n {\n query: {\n filter: provider.userFilter,\n expand: provider.userExpand,\n select: provider.userSelect,\n top: USER_PAGE_SIZE,\n },\n queryMode: provider.queryMode,\n nextLink,\n },\n );\n\n const transformer = this.options.userTransformer ?? defaultUserTransformer;\n const limiter = limiterFactory(10);\n const entities: DeferredEntity[] = [];\n\n await Promise.all(\n rawUsers.map(user =>\n limiter(async () => {\n let userPhoto: string | undefined;\n if (user.id && provider.loadUserPhotos !== false) {\n try {\n userPhoto = await getUserPhotoGated(client, user.id, 120);\n } catch (e) {\n this.options.logger.debug(\n `${this.getProviderName()}: failed to load photo for user ${\n user.id\n }`,\n { error: e },\n );\n }\n }\n\n const entity = await transformer(user, userPhoto);\n if (entity) {\n entity.metadata.name = capEntityName(entity.metadata.name);\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n });\n }\n }),\n ),\n );\n\n this.options.logger.debug(\n `${this.getProviderName()}: read ${entities.length} users`,\n { phase: 'users', hasNextPage: !!newNextLink },\n );\n\n if (newNextLink) {\n return {\n done: false,\n entities,\n cursor: { phase: 'users', nextLink: newNextLink },\n };\n }\n\n return {\n done: false,\n entities,\n cursor: { phase: 'groups' },\n };\n }\n\n private async readGroupsPage(\n client: MicrosoftGraphClient,\n provider: MicrosoftGraphProviderConfig,\n nextLink: string | undefined,\n ): Promise<EntityIteratorResult<MSGraphCursor>> {\n const { items: rawGroups, nextLink: newNextLink } =\n await requestOnePage<MicrosoftGraph.Group>(\n client,\n provider.groupPath ?? 'groups',\n {\n query: {\n filter: provider.groupFilter,\n search: provider.groupSearch,\n expand: provider.groupExpand,\n select: provider.groupSelect,\n top: GROUP_PAGE_SIZE,\n },\n queryMode: provider.queryMode,\n nextLink,\n },\n );\n\n const groupTransformer =\n this.options.groupTransformer ?? defaultGroupTransformer;\n const userTransformer =\n this.options.userTransformer ?? defaultUserTransformer;\n const limiter = limiterFactory(10);\n const entities: DeferredEntity[] = [];\n\n // Emit the tenant root group on the very first groups page\n if (!nextLink) {\n try {\n const organization = await client.getOrganization(provider.tenantId);\n const orgTransformer =\n this.options.organizationTransformer ??\n defaultOrganizationTransformer;\n const rootGroup = await orgTransformer(organization);\n if (rootGroup) {\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, rootGroup),\n });\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: failed to read organization root group`,\n { error: e },\n );\n }\n }\n\n await Promise.all(\n rawGroups.map(group =>\n limiter(async () => {\n const entity = await groupTransformer(group);\n if (!entity) {\n return;\n }\n entity.metadata.name = capEntityName(entity.metadata.name);\n\n const userRefs: string[] = [];\n const childRefs: string[] = [];\n\n for await (const member of client.getGroupMembers(group.id!, {\n top: GROUP_PAGE_SIZE,\n // Request the minimum fields needed by defaultUserTransformer and\n // defaultGroupTransformer so member objects are never sparse.\n select: [\n 'id',\n 'displayName',\n 'mail',\n 'mailNickname',\n 'userPrincipalName',\n 'description',\n 'securityEnabled',\n ],\n })) {\n if (member['@odata.type'] === '#microsoft.graph.user') {\n try {\n const userEntity = await userTransformer(\n member as MicrosoftGraph.User,\n );\n if (userEntity) {\n userEntity.metadata.name = capEntityName(\n userEntity.metadata.name,\n );\n userRefs.push(stringifyEntityRef(userEntity));\n } else {\n this.options.logger.debug(\n `${this.getProviderName()}: group member user ${\n member.id\n } could not be transformed (sparse object?), skipping`,\n );\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: group member user ${\n member.id\n } failed to transform, skipping`,\n { error: e },\n );\n }\n } else if (member['@odata.type'] === '#microsoft.graph.group') {\n // Only emit child refs when no group filter/search is active.\n // With a filter, child groups may not be ingested themselves,\n // which would produce dangling spec.children references.\n if (!provider.groupFilter && !provider.groupSearch) {\n try {\n const childEntity = await groupTransformer(\n member as MicrosoftGraph.Group,\n );\n if (childEntity) {\n childEntity.metadata.name = capEntityName(\n childEntity.metadata.name,\n );\n childRefs.push(stringifyEntityRef(childEntity));\n } else {\n this.options.logger.debug(\n `${this.getProviderName()}: group member child group ${\n member.id\n } could not be transformed (sparse object?), skipping`,\n );\n }\n } catch (e) {\n this.options.logger.warn(\n `${this.getProviderName()}: group member child group ${\n member.id\n } failed to transform, skipping`,\n { error: e },\n );\n }\n }\n }\n }\n\n // Merge fetched membership with any members/children the transformer\n // may have pre-populated, so custom transformers can augment the list.\n const existingMembers = Array.isArray(entity.spec?.members)\n ? (entity.spec.members as string[])\n : [];\n const existingChildren = Array.isArray(entity.spec?.children)\n ? (entity.spec.children as string[])\n : [];\n\n entities.push({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, {\n ...entity,\n spec: {\n ...entity.spec,\n members: [...new Set([...existingMembers, ...userRefs])],\n children: [...new Set([...existingChildren, ...childRefs])],\n },\n }),\n });\n }),\n ),\n );\n\n this.options.logger.debug(\n `${this.getProviderName()}: read ${rawGroups.length} groups`,\n { phase: 'groups', hasNextPage: !!newNextLink },\n );\n\n if (newNextLink) {\n return {\n done: false,\n entities,\n cursor: { phase: 'groups', nextLink: newNextLink },\n };\n }\n\n return { done: true, entities };\n }\n}\n"],"names":["crypto","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION","readProviderConfigs","MicrosoftGraphClient","requestOnePage","defaultUserTransformer","limiterFactory","getUserPhotoGated","defaultGroupTransformer","defaultOrganizationTransformer","stringifyEntityRef"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientHelpers.cjs.js","sources":["../src/clientHelpers.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n MicrosoftGraphClient,\n ODataQuery,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\n\n/**\n * Fetches a single page of Graph API results.\n *\n * When `options.nextLink` is provided it is followed directly (all query\n * parameters are already encoded in it). Otherwise the request is built from\n * `options.query`.\n *\n * MS Graph requires `ConsistencyLevel: eventual` + `$count=true` for advanced\n * queries using `ne`/`not` operators in `$filter` or using `$search`.\n */\nexport async function requestOnePage<T>(\n client: MicrosoftGraphClient,\n path: string,\n options: {\n query?: ODataQuery;\n queryMode?: 'basic' | 'advanced';\n nextLink?: string;\n signal?: AbortSignal;\n } = {},\n): Promise<{ items: T[]; nextLink?: string }> {\n const { query, queryMode, nextLink, signal } = options;\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // Microsoft Graph requires $count=true whenever ConsistencyLevel: eventual is set,\n // including plain listing requests with no $filter or $search.\n const finalQuery =\n appliedQueryMode === 'advanced' ? { ...(query ?? {}), count: true } : query;\n\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced' ? { ConsistencyLevel: 'eventual' } : {};\n\n const response = nextLink\n ? await client.requestRaw(nextLink, headers, 2, signal)\n : await client.requestApi(path, finalQuery, headers, signal);\n\n if (response.status !== 200) {\n let message = `HTTP ${response.status}`;\n try {\n const body = await response.json();\n const err = body?.error;\n if (err?.code || err?.message) {\n message = `${err.code} - ${err.message}`;\n }\n } catch {\n // Response body is not JSON; fall back to HTTP status above\n }\n throw new Error(\n `Error while reading ${\n nextLink ?? path\n } from Microsoft Graph: ${message}`,\n );\n }\n\n const result = await response.json();\n return {\n items: result.value as T[],\n nextLink: result['@odata.nextLink'],\n };\n}\n\n/**\n * Like `getUserPhotoWithSizeLimit` but skips the size-listing call for users\n * with no photo. For users without a photo: 1 fast check call. For users with\n * a photo: 1 check + the normal size-limited fetch (2 more calls).\n *\n * Returns `undefined` only for 404 (no photo assigned). Throws for any other\n * non-200 status so callers can distinguish \"no photo\" from real errors.\n */\nexport async function getUserPhotoGated(\n client: MicrosoftGraphClient,\n userId: string,\n maxSize: number,\n): Promise<string | undefined> {\n const check = await client.requestApi(`users/${userId}/photo`);\n if (check.status === 404) return undefined;\n if (check.status !== 200) {\n throw new Error(\n `Unexpected status ${check.status} when checking photo for user ${userId}`,\n );\n }\n return await client.getUserPhotoWithSizeLimit(userId, maxSize);\n}\n"],"names":[],"mappings":";;AA+BA,eAAsB,cAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAKI,EAAC,EACuC;AAC5C,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU,QAAO,GAAI,OAAA;AAC/C,EAAA,MAAM,gBAAA,GAAmB,KAAA,EAAO,MAAA,GAAS,UAAA,GAAa,SAAA,IAAa,OAAA;AAInE,EAAA,MAAM,UAAA,GACJ,gBAAA,KAAqB,UAAA,GAAa,EAAE,GAAI,SAAS,EAAC,EAAI,KAAA,EAAO,IAAA,EAAK,GAAI,KAAA;AAExE,EAAA,MAAM,UACJ,gBAAA,KAAqB,UAAA,GAAa,EAAE,gBAAA,EAAkB,UAAA,KAAe,EAAC;AAExE,EAAA,MAAM,WAAW,QAAA,GACb,MAAM,MAAA,CAAO,UAAA,CAAW,UAAU,OAAA,EAAS,CAAA,EAAG,MAAM,CAAA,GACpD,MAAM,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,UAAA,EAAY,SAAS,MAAM,CAAA;AAE7D,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,IAAI,OAAA,GAAU,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,MAAM,MAAM,IAAA,EAAM,KAAA;AAClB,MAAA,IAAI,GAAA,EAAK,IAAA,IAAQ,GAAA,EAAK,OAAA,EAAS;AAC7B,QAAA,OAAA,GAAU,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,GAAA,EAAM,IAAI,OAAO,CAAA,CAAA;AAAA,MACxC;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oBAAA,EACE,QAAA,IAAY,IACd,CAAA,uBAAA,EAA0B,OAAO,CAAA;AAAA,KACnC;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,EAAA,OAAO;AAAA,IACL,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,QAAA,EAAU,OAAO,iBAAiB;AAAA,GACpC;AACF;AAUA,eAAsB,iBAAA,CACpB,MAAA,EACA,MAAA,EACA,OAAA,EAC6B;AAC7B,EAAA,MAAM,QAAQ,MAAM,MAAA,CAAO,UAAA,CAAW,CAAA,MAAA,EAAS,MAAM,CAAA,MAAA,CAAQ,CAAA;AAC7D,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,GAAA,EAAK,OAAO,MAAA;AACjC,EAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kBAAA,EAAqB,KAAA,CAAM,MAAM,CAAA,8BAAA,EAAiC,MAAM,CAAA;AAAA,KAC1E;AAAA,EACF;AACA,EAAA,OAAO,MAAM,MAAA,CAAO,yBAAA,CAA0B,MAAA,EAAQ,OAAO,CAAA;AAC/D
|
|
1
|
+
{"version":3,"file":"clientHelpers.cjs.js","sources":["../src/clientHelpers.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n MicrosoftGraphClient,\n ODataQuery,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\n\n/**\n * Fetches a single page of Graph API results.\n *\n * When `options.nextLink` is provided it is followed directly (all query\n * parameters are already encoded in it). Otherwise the request is built from\n * `options.query`.\n *\n * MS Graph requires `ConsistencyLevel: eventual` + `$count=true` for advanced\n * queries using `ne`/`not` operators in `$filter` or using `$search`.\n */\nexport async function requestOnePage<T>(\n client: MicrosoftGraphClient,\n path: string,\n options: {\n query?: ODataQuery;\n queryMode?: 'basic' | 'advanced';\n nextLink?: string;\n signal?: AbortSignal;\n } = {},\n): Promise<{ items: T[]; nextLink?: string }> {\n const { query, queryMode, nextLink, signal } = options;\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // Microsoft Graph requires $count=true whenever ConsistencyLevel: eventual is set,\n // including plain listing requests with no $filter or $search.\n const finalQuery =\n appliedQueryMode === 'advanced' ? { ...(query ?? {}), count: true } : query;\n\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced' ? { ConsistencyLevel: 'eventual' } : {};\n\n const response = nextLink\n ? await client.requestRaw(nextLink, headers, 2, signal)\n : await client.requestApi(path, finalQuery, headers, signal);\n\n if (response.status !== 200) {\n let message = `HTTP ${response.status}`;\n try {\n const body = await response.json();\n const err = body?.error;\n if (err?.code || err?.message) {\n message = `${err.code} - ${err.message}`;\n }\n } catch {\n // Response body is not JSON; fall back to HTTP status above\n }\n throw new Error(\n `Error while reading ${\n nextLink ?? path\n } from Microsoft Graph: ${message}`,\n );\n }\n\n const result = await response.json();\n return {\n items: result.value as T[],\n nextLink: result['@odata.nextLink'],\n };\n}\n\n/**\n * Like `getUserPhotoWithSizeLimit` but skips the size-listing call for users\n * with no photo. For users without a photo: 1 fast check call. For users with\n * a photo: 1 check + the normal size-limited fetch (2 more calls).\n *\n * Returns `undefined` only for 404 (no photo assigned). Throws for any other\n * non-200 status so callers can distinguish \"no photo\" from real errors.\n */\nexport async function getUserPhotoGated(\n client: MicrosoftGraphClient,\n userId: string,\n maxSize: number,\n): Promise<string | undefined> {\n const check = await client.requestApi(`users/${userId}/photo`);\n if (check.status === 404) return undefined;\n if (check.status !== 200) {\n throw new Error(\n `Unexpected status ${check.status} when checking photo for user ${userId}`,\n );\n }\n return await client.getUserPhotoWithSizeLimit(userId, maxSize);\n}\n"],"names":[],"mappings":";;AA+BA,eAAsB,cAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAKI,EAAC,EACuC;AAC5C,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU,QAAO,GAAI,OAAA;AAC/C,EAAA,MAAM,gBAAA,GAAmB,KAAA,EAAO,MAAA,GAAS,UAAA,GAAa,SAAA,IAAa,OAAA;AAInE,EAAA,MAAM,UAAA,GACJ,gBAAA,KAAqB,UAAA,GAAa,EAAE,GAAI,SAAS,EAAC,EAAI,KAAA,EAAO,IAAA,EAAK,GAAI,KAAA;AAExE,EAAA,MAAM,UACJ,gBAAA,KAAqB,UAAA,GAAa,EAAE,gBAAA,EAAkB,UAAA,KAAe,EAAC;AAExE,EAAA,MAAM,WAAW,QAAA,GACb,MAAM,MAAA,CAAO,UAAA,CAAW,UAAU,OAAA,EAAS,CAAA,EAAG,MAAM,CAAA,GACpD,MAAM,MAAA,CAAO,UAAA,CAAW,IAAA,EAAM,UAAA,EAAY,SAAS,MAAM,CAAA;AAE7D,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,IAAI,OAAA,GAAU,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,MAAM,MAAM,IAAA,EAAM,KAAA;AAClB,MAAA,IAAI,GAAA,EAAK,IAAA,IAAQ,GAAA,EAAK,OAAA,EAAS;AAC7B,QAAA,OAAA,GAAU,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,GAAA,EAAM,IAAI,OAAO,CAAA,CAAA;AAAA,MACxC;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oBAAA,EACE,QAAA,IAAY,IACd,CAAA,uBAAA,EAA0B,OAAO,CAAA;AAAA,KACnC;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,EAAA,OAAO;AAAA,IACL,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,QAAA,EAAU,OAAO,iBAAiB;AAAA,GACpC;AACF;AAUA,eAAsB,iBAAA,CACpB,MAAA,EACA,MAAA,EACA,OAAA,EAC6B;AAC7B,EAAA,MAAM,QAAQ,MAAM,MAAA,CAAO,UAAA,CAAW,CAAA,MAAA,EAAS,MAAM,CAAA,MAAA,CAAQ,CAAA;AAC7D,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,GAAA,EAAK,OAAO,MAAA;AACjC,EAAA,IAAI,KAAA,CAAM,WAAW,GAAA,EAAK;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kBAAA,EAAqB,KAAA,CAAM,MAAM,CAAA,8BAAA,EAAiC,MAAM,CAAA;AAAA,KAC1E;AAAA,EACF;AACA,EAAA,OAAO,MAAM,MAAA,CAAO,yBAAA,CAA0B,MAAA,EAAQ,OAAO,CAAA;AAC/D;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogModuleMicrosoftGraphIncrementalEntityProvider.cjs.js","sources":["../../src/module/catalogModuleMicrosoftGraphIncrementalEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n createExtensionPoint,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { incrementalIngestionProvidersExtensionPoint } from '@backstage/plugin-catalog-backend-module-incremental-ingestion';\nimport {\n GroupTransformer,\n OrganizationTransformer,\n ProviderConfigTransformer,\n UserTransformer,\n readProviderConfigs,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\nimport { HumanDuration } from '@backstage/types';\nimport {\n MicrosoftGraphIncrementalEntityProvider,\n MSGraphContext,\n MSGraphCursor,\n} from '../MicrosoftGraphIncrementalEntityProvider';\n\n/**\n * Interface for\n * {@link microsoftGraphIncrementalEntityProviderTransformExtensionPoint}.\n *\n * @public\n */\nexport interface MicrosoftGraphIncrementalEntityProviderTransformsExtensionPoint {\n /**\n * Set the function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setUserTransformer(\n transformer: UserTransformer | Record<string, UserTransformer>,\n ): void;\n\n /**\n * Set the function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setGroupTransformer(\n transformer: GroupTransformer | Record<string, GroupTransformer>,\n ): void;\n\n /**\n * Set the function that transforms an organization entry in msgraph to an\n * entity. Optionally, you can pass separate transformers per provider ID.\n */\n setOrganizationTransformer(\n transformer:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>,\n ): void;\n\n /**\n * Set the function that transforms provider config dynamically.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setProviderConfigTransformer(\n transformer:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>,\n ): void;\n}\n\n/**\n * Extension point used to customize the transforms applied by the incremental\n * module.\n *\n * @public\n */\nexport const microsoftGraphIncrementalEntityProviderTransformExtensionPoint =\n createExtensionPoint<MicrosoftGraphIncrementalEntityProviderTransformsExtensionPoint>(\n {\n id: 'catalog.microsoftGraphIncrementalEntityProvider.transforms',\n },\n );\n\n/**\n * Registers {@link MicrosoftGraphIncrementalEntityProvider} instances with the\n * catalog's incremental ingestion extension point.\n *\n * This module requires `catalogModuleIncrementalIngestionEntityProvider` to\n * also be installed in the backend.\n *\n * @example\n * ```ts\n * // packages/backend/src/index.ts\n * backend.add(import('@backstage/plugin-catalog-backend-module-incremental-ingestion'));\n * backend.add(import('@backstage/plugin-catalog-backend-module-msgraph-incremental'));\n * ```\n *\n * @public\n */\nexport const catalogModuleMicrosoftGraphIncrementalEntityProvider =\n createBackendModule({\n pluginId: 'catalog',\n moduleId: 'microsoftGraphIncrementalEntityProvider',\n register(env) {\n let userTransformer:\n | UserTransformer\n | Record<string, UserTransformer>\n | undefined;\n let groupTransformer:\n | GroupTransformer\n | Record<string, GroupTransformer>\n | undefined;\n let organizationTransformer:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>\n | undefined;\n let providerConfigTransformer:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>\n | undefined;\n\n env.registerExtensionPoint(\n microsoftGraphIncrementalEntityProviderTransformExtensionPoint,\n {\n setUserTransformer(transformer) {\n if (userTransformer) {\n throw new Error('User transformer may only be set once');\n }\n userTransformer = transformer;\n },\n setGroupTransformer(transformer) {\n if (groupTransformer) {\n throw new Error('Group transformer may only be set once');\n }\n groupTransformer = transformer;\n },\n setOrganizationTransformer(transformer) {\n if (organizationTransformer) {\n throw new Error('Organization transformer may only be set once');\n }\n organizationTransformer = transformer;\n },\n setProviderConfigTransformer(transformer) {\n if (providerConfigTransformer) {\n throw new Error(\n 'Provider config transformer may only be set once',\n );\n }\n providerConfigTransformer = transformer;\n },\n },\n );\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n incremental: incrementalIngestionProvidersExtensionPoint,\n },\n async init({ config, logger, incremental }) {\n const providerConfigs = readProviderConfigs(config);\n\n for (const providerConfig of providerConfigs) {\n const provider = new MicrosoftGraphIncrementalEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger,\n userTransformer: resolveTransformer(\n providerConfig.id,\n userTransformer,\n ),\n groupTransformer: resolveTransformer(\n providerConfig.id,\n groupTransformer,\n ),\n organizationTransformer: resolveTransformer(\n providerConfig.id,\n organizationTransformer,\n ),\n providerConfigTransformer: resolveTransformer(\n providerConfig.id,\n providerConfigTransformer,\n ),\n });\n\n const restLength = deriveRestLength(providerConfig, logger);\n\n incremental.addProvider<MSGraphCursor, MSGraphContext>({\n provider,\n options: {\n burstInterval: { seconds: 3 },\n burstLength: { minutes: 5 },\n restLength,\n backoff: [\n { seconds: 30 },\n { minutes: 3 },\n { minutes: 30 },\n { hours: 3 },\n ],\n },\n });\n }\n },\n });\n },\n });\n\nfunction resolveTransformer<T extends Function>(\n id: string,\n transformer?: T | Record<string, T>,\n): T | undefined {\n if (['undefined', 'function'].includes(typeof transformer)) {\n return transformer as T;\n }\n return (transformer as Record<string, T>)[id];\n}\n\nfunction deriveRestLength(\n providerConfig: ReturnType<typeof readProviderConfigs>[number],\n logger: LoggerService,\n): HumanDuration {\n const freq = providerConfig.schedule?.frequency;\n // Only treat plain duration objects as restLength — exclude cron expressions\n // and any other non-duration schedule types (e.g. manual triggers).\n if (\n freq &&\n typeof freq === 'object' &&\n !('cron' in freq) &&\n !('trigger' in freq)\n ) {\n return freq as HumanDuration;\n }\n if (freq) {\n logger.warn(\n `MicrosoftGraphIncrementalEntityProvider:${providerConfig.id}: ` +\n `schedule.frequency is not a duration-based schedule; cannot derive restLength from it. ` +\n `Defaulting restLength to 8 hours.`,\n );\n }\n return { hours: 8 };\n}\n"],"names":["createExtensionPoint","createBackendModule","coreServices","incrementalIngestionProvidersExtensionPoint","readProviderConfigs","MicrosoftGraphIncrementalEntityProvider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"catalogModuleMicrosoftGraphIncrementalEntityProvider.cjs.js","sources":["../../src/module/catalogModuleMicrosoftGraphIncrementalEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n createExtensionPoint,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { incrementalIngestionProvidersExtensionPoint } from '@backstage/plugin-catalog-backend-module-incremental-ingestion';\nimport {\n GroupTransformer,\n OrganizationTransformer,\n ProviderConfigTransformer,\n UserTransformer,\n readProviderConfigs,\n} from '@backstage/plugin-catalog-backend-module-msgraph';\nimport { HumanDuration } from '@backstage/types';\nimport {\n MicrosoftGraphIncrementalEntityProvider,\n MSGraphContext,\n MSGraphCursor,\n} from '../MicrosoftGraphIncrementalEntityProvider';\n\n/**\n * Interface for\n * {@link microsoftGraphIncrementalEntityProviderTransformExtensionPoint}.\n *\n * @public\n */\nexport interface MicrosoftGraphIncrementalEntityProviderTransformsExtensionPoint {\n /**\n * Set the function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setUserTransformer(\n transformer: UserTransformer | Record<string, UserTransformer>,\n ): void;\n\n /**\n * Set the function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setGroupTransformer(\n transformer: GroupTransformer | Record<string, GroupTransformer>,\n ): void;\n\n /**\n * Set the function that transforms an organization entry in msgraph to an\n * entity. Optionally, you can pass separate transformers per provider ID.\n */\n setOrganizationTransformer(\n transformer:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>,\n ): void;\n\n /**\n * Set the function that transforms provider config dynamically.\n * Optionally, you can pass separate transformers per provider ID.\n */\n setProviderConfigTransformer(\n transformer:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>,\n ): void;\n}\n\n/**\n * Extension point used to customize the transforms applied by the incremental\n * module.\n *\n * @public\n */\nexport const microsoftGraphIncrementalEntityProviderTransformExtensionPoint =\n createExtensionPoint<MicrosoftGraphIncrementalEntityProviderTransformsExtensionPoint>(\n {\n id: 'catalog.microsoftGraphIncrementalEntityProvider.transforms',\n },\n );\n\n/**\n * Registers {@link MicrosoftGraphIncrementalEntityProvider} instances with the\n * catalog's incremental ingestion extension point.\n *\n * This module requires `catalogModuleIncrementalIngestionEntityProvider` to\n * also be installed in the backend.\n *\n * @example\n * ```ts\n * // packages/backend/src/index.ts\n * backend.add(import('@backstage/plugin-catalog-backend-module-incremental-ingestion'));\n * backend.add(import('@backstage/plugin-catalog-backend-module-msgraph-incremental'));\n * ```\n *\n * @public\n */\nexport const catalogModuleMicrosoftGraphIncrementalEntityProvider =\n createBackendModule({\n pluginId: 'catalog',\n moduleId: 'microsoftGraphIncrementalEntityProvider',\n register(env) {\n let userTransformer:\n | UserTransformer\n | Record<string, UserTransformer>\n | undefined;\n let groupTransformer:\n | GroupTransformer\n | Record<string, GroupTransformer>\n | undefined;\n let organizationTransformer:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>\n | undefined;\n let providerConfigTransformer:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>\n | undefined;\n\n env.registerExtensionPoint(\n microsoftGraphIncrementalEntityProviderTransformExtensionPoint,\n {\n setUserTransformer(transformer) {\n if (userTransformer) {\n throw new Error('User transformer may only be set once');\n }\n userTransformer = transformer;\n },\n setGroupTransformer(transformer) {\n if (groupTransformer) {\n throw new Error('Group transformer may only be set once');\n }\n groupTransformer = transformer;\n },\n setOrganizationTransformer(transformer) {\n if (organizationTransformer) {\n throw new Error('Organization transformer may only be set once');\n }\n organizationTransformer = transformer;\n },\n setProviderConfigTransformer(transformer) {\n if (providerConfigTransformer) {\n throw new Error(\n 'Provider config transformer may only be set once',\n );\n }\n providerConfigTransformer = transformer;\n },\n },\n );\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n incremental: incrementalIngestionProvidersExtensionPoint,\n },\n async init({ config, logger, incremental }) {\n const providerConfigs = readProviderConfigs(config);\n\n for (const providerConfig of providerConfigs) {\n const provider = new MicrosoftGraphIncrementalEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger,\n userTransformer: resolveTransformer(\n providerConfig.id,\n userTransformer,\n ),\n groupTransformer: resolveTransformer(\n providerConfig.id,\n groupTransformer,\n ),\n organizationTransformer: resolveTransformer(\n providerConfig.id,\n organizationTransformer,\n ),\n providerConfigTransformer: resolveTransformer(\n providerConfig.id,\n providerConfigTransformer,\n ),\n });\n\n const restLength = deriveRestLength(providerConfig, logger);\n\n incremental.addProvider<MSGraphCursor, MSGraphContext>({\n provider,\n options: {\n burstInterval: { seconds: 3 },\n burstLength: { minutes: 5 },\n restLength,\n backoff: [\n { seconds: 30 },\n { minutes: 3 },\n { minutes: 30 },\n { hours: 3 },\n ],\n },\n });\n }\n },\n });\n },\n });\n\nfunction resolveTransformer<T extends Function>(\n id: string,\n transformer?: T | Record<string, T>,\n): T | undefined {\n if (['undefined', 'function'].includes(typeof transformer)) {\n return transformer as T;\n }\n return (transformer as Record<string, T>)[id];\n}\n\nfunction deriveRestLength(\n providerConfig: ReturnType<typeof readProviderConfigs>[number],\n logger: LoggerService,\n): HumanDuration {\n const freq = providerConfig.schedule?.frequency;\n // Only treat plain duration objects as restLength — exclude cron expressions\n // and any other non-duration schedule types (e.g. manual triggers).\n if (\n freq &&\n typeof freq === 'object' &&\n !('cron' in freq) &&\n !('trigger' in freq)\n ) {\n return freq as HumanDuration;\n }\n if (freq) {\n logger.warn(\n `MicrosoftGraphIncrementalEntityProvider:${providerConfig.id}: ` +\n `schedule.frequency is not a duration-based schedule; cannot derive restLength from it. ` +\n `Defaulting restLength to 8 hours.`,\n );\n }\n return { hours: 8 };\n}\n"],"names":["createExtensionPoint","createBackendModule","coreServices","incrementalIngestionProvidersExtensionPoint","readProviderConfigs","MicrosoftGraphIncrementalEntityProvider"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog-backend-module-msgraph-incremental",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5-next.1",
|
|
4
4
|
"description": "A Backstage catalog backend module that incrementally ingests users and groups from Microsoft Graph",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin-module",
|
|
@@ -62,18 +62,18 @@
|
|
|
62
62
|
"test": "backstage-cli package test"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@backstage/backend-plugin-api": "
|
|
66
|
-
"@backstage/catalog-model": "
|
|
67
|
-
"@backstage/config": "
|
|
68
|
-
"@backstage/plugin-catalog-backend-module-incremental-ingestion": "
|
|
69
|
-
"@backstage/plugin-catalog-backend-module-msgraph": "
|
|
70
|
-
"@backstage/plugin-catalog-node": "
|
|
71
|
-
"@backstage/types": "
|
|
65
|
+
"@backstage/backend-plugin-api": "1.11.0-next.1",
|
|
66
|
+
"@backstage/catalog-model": "1.10.2-next.0",
|
|
67
|
+
"@backstage/config": "1.3.10-next.0",
|
|
68
|
+
"@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.9.0-next.1",
|
|
69
|
+
"@backstage/plugin-catalog-backend-module-msgraph": "0.10.7-next.1",
|
|
70
|
+
"@backstage/plugin-catalog-node": "2.2.6-next.1",
|
|
71
|
+
"@backstage/types": "1.2.2",
|
|
72
72
|
"@microsoft/microsoft-graph-types": "^2.6.0",
|
|
73
73
|
"p-limit": "^3.0.2"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@backstage/backend-test-utils": "
|
|
77
|
-
"@backstage/cli": "
|
|
76
|
+
"@backstage/backend-test-utils": "1.11.8-next.1",
|
|
77
|
+
"@backstage/cli": "0.36.7-next.0"
|
|
78
78
|
}
|
|
79
79
|
}
|