@backstage/plugin-catalog-backend-module-msgraph 0.8.1 → 0.8.2-next.0

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,17 @@
1
1
  # @backstage/plugin-catalog-backend-module-msgraph
2
2
 
3
+ ## 0.8.2-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 05f60e1: Refactored constructor parameter properties to explicit property declarations for compatibility with TypeScript's `erasableSyntaxOnly` setting. This internal refactoring maintains all existing functionality while ensuring TypeScript compilation compatibility.
8
+ - Updated dependencies
9
+ - @backstage/config@1.3.6-next.0
10
+ - @backstage/catalog-model@1.7.6-next.0
11
+ - @backstage/backend-plugin-api@1.4.5-next.0
12
+ - @backstage/plugin-catalog-common@1.1.7-next.0
13
+ - @backstage/plugin-catalog-node@1.19.2-next.0
14
+
3
15
  ## 0.8.1
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -287,8 +287,6 @@ type GroupMember = (MicrosoftGraph.Group & {
287
287
  * @public
288
288
  */
289
289
  declare class MicrosoftGraphClient {
290
- private readonly baseUrl;
291
- private readonly tokenCredential;
292
290
  /**
293
291
  * Factory method that instantiate `msal` client and return
294
292
  * an instance of `MicrosoftGraphClient`
@@ -303,6 +301,8 @@ declare class MicrosoftGraphClient {
303
301
  * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls
304
302
  *
305
303
  */
304
+ private readonly baseUrl;
305
+ private readonly tokenCredential;
306
306
  constructor(baseUrl: string, tokenCredential: TokenCredential);
307
307
  /**
308
308
  * Get a collection of resource from Graph API and
@@ -607,7 +607,6 @@ interface MicrosoftGraphOrgEntityProviderLegacyOptions {
607
607
  * @public
608
608
  */
609
609
  declare class MicrosoftGraphOrgEntityProvider implements EntityProvider {
610
- private options;
611
610
  private connection?;
612
611
  private scheduleFn?;
613
612
  static fromConfig(configRoot: Config, options: MicrosoftGraphOrgEntityProviderOptions): MicrosoftGraphOrgEntityProvider[];
@@ -615,6 +614,7 @@ declare class MicrosoftGraphOrgEntityProvider implements EntityProvider {
615
614
  * @deprecated Exists for backwards compatibility only and will be removed in the future.
616
615
  */
617
616
  private static fromLegacyConfig;
617
+ private options;
618
618
  constructor(options: {
619
619
  id: string;
620
620
  provider: MicrosoftGraphProviderConfig;
@@ -8,15 +8,6 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
8
8
  var qs__default = /*#__PURE__*/_interopDefaultCompat(qs);
9
9
 
10
10
  class MicrosoftGraphClient {
11
- /**
12
- * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}
13
- * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls
14
- *
15
- */
16
- constructor(baseUrl, tokenCredential) {
17
- this.baseUrl = baseUrl;
18
- this.tokenCredential = tokenCredential;
19
- }
20
11
  /**
21
12
  * Factory method that instantiate `msal` client and return
22
13
  * an instance of `MicrosoftGraphClient`
@@ -38,6 +29,17 @@ class MicrosoftGraphClient {
38
29
  ) : new identity.DefaultAzureCredential(options);
39
30
  return new MicrosoftGraphClient(config.target, credential);
40
31
  }
32
+ /**
33
+ * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}
34
+ * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls
35
+ *
36
+ */
37
+ baseUrl;
38
+ tokenCredential;
39
+ constructor(baseUrl, tokenCredential) {
40
+ this.baseUrl = baseUrl;
41
+ this.tokenCredential = tokenCredential;
42
+ }
41
43
  /**
42
44
  * Get a collection of resource from Graph API and
43
45
  * return an `AsyncIterable` of that resource
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs.js","sources":["../../src/microsoftGraph/client.ts"],"sourcesContent":["/*\n * Copyright 2020 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 TokenCredential,\n DefaultAzureCredential,\n ClientSecretCredential,\n} from '@azure/identity';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport qs from 'qs';\nimport { MicrosoftGraphProviderConfig } from './config';\n\n/**\n * OData (Open Data Protocol) Query\n *\n * {@link https://docs.microsoft.com/en-us/odata/concepts/queryoptions-overview}\n * {@link https://docs.microsoft.com/en-us/graph/query-parameters}\n * @public\n */\nexport type ODataQuery = {\n /**\n * search resources within a collection matching a free-text search expression.\n */\n search?: string;\n /**\n * filter a collection of resources\n */\n filter?: string;\n /**\n * specifies the related resources or media streams to be included in line with retrieved resources\n */\n expand?: string;\n /**\n * request a specific set of properties for each entity or complex type\n */\n select?: string[];\n /**\n * Retrieves the total count of matching resources.\n */\n count?: boolean;\n /**\n * Maximum number of records to receive in one batch.\n */\n top?: number;\n};\n\n/**\n * Extends the base msgraph types to include the odata type.\n *\n * @public\n */\nexport type GroupMember =\n | (MicrosoftGraph.Group & { '@odata.type': '#microsoft.graph.group' })\n | (MicrosoftGraph.User & { '@odata.type': '#microsoft.graph.user' });\n\n/**\n * A HTTP Client that communicates with Microsoft Graph API.\n * Simplify Authentication and API calls to get `User` and `Group` from Microsoft Graph\n *\n * Uses `msal-node` for authentication\n *\n * @public\n */\nexport class MicrosoftGraphClient {\n /**\n * Factory method that instantiate `msal` client and return\n * an instance of `MicrosoftGraphClient`\n *\n * @public\n *\n * @param config - Configuration for Interacting with Graph API\n */\n static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient {\n const options = {\n authorityHost: config.authority,\n tenantId: config.tenantId,\n };\n\n const credential =\n config.clientId && config.clientSecret\n ? new ClientSecretCredential(\n config.tenantId,\n config.clientId,\n config.clientSecret,\n options,\n )\n : new DefaultAzureCredential(options);\n\n return new MicrosoftGraphClient(config.target, credential);\n }\n\n /**\n * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}\n * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls\n *\n */\n constructor(\n private readonly baseUrl: string,\n private readonly tokenCredential: TokenCredential,\n ) {}\n\n /**\n * Get a collection of resource from Graph API and\n * return an `AsyncIterable` of that resource\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *requestCollection<T>(\n path: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<T> {\n // upgrade to advanced query mode transparently when \"search\" is used\n // to stay backwards compatible.\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // not needed for \"search\"\n // as of https://docs.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http\n // even though a few other places say the opposite\n // - https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http#request-headers\n // - https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties\n if (appliedQueryMode === 'advanced' && (query?.filter || query?.select)) {\n query.count = true;\n }\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced'\n ? {\n // Eventual consistency is required for advanced querying capabilities\n // like \"$search\" or parts of \"$filter\".\n // If a new user/group is not found, it'll eventually be imported on a subsequent read\n ConsistencyLevel: 'eventual',\n }\n : {};\n\n let response = await this.requestApi(path, query, headers);\n\n for (;;) {\n if (response.status !== 200) {\n await this.handleError(path, response);\n }\n\n const result = await response.json();\n\n // Graph API return array of collections\n const elements: T[] = result.value;\n\n yield* elements;\n\n // Follow cursor to the next page if one is available\n if (!result['@odata.nextLink']) {\n return;\n }\n\n response = await this.requestRaw(result['@odata.nextLink'], headers);\n }\n }\n\n /**\n * Abstract on top of {@link MicrosoftGraphClient.requestRaw}\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param headers - optional HTTP headers\n */\n async requestApi(\n path: string,\n query?: ODataQuery,\n headers?: Record<string, string>,\n ): Promise<Response> {\n const queryString = qs.stringify(\n {\n $search: query?.search,\n $filter: query?.filter,\n $select: query?.select?.join(','),\n $expand: query?.expand,\n $count: query?.count,\n $top: query?.top,\n },\n {\n addQueryPrefix: true,\n encode: true,\n },\n );\n\n return await this.requestRaw(\n `${this.baseUrl}/${path}${queryString}`,\n headers,\n );\n }\n\n /**\n * Makes a HTTP call to Graph API with token\n *\n * @param url - HTTP Endpoint of Graph API\n * @param headers - optional HTTP headers\n */\n async requestRaw(\n url: string,\n headers?: Record<string, string>,\n retryCount = 2,\n ): Promise<Response> {\n // Make sure that we always have a valid access token (might be cached)\n const urlObj = new URL(url);\n const token = await this.tokenCredential.getToken(\n `${urlObj.protocol}//${urlObj.hostname}/.default`,\n );\n\n if (!token) {\n throw new Error('Failed to obtain token from Azure Identity');\n }\n\n try {\n return await fetch(url, {\n headers: {\n ...headers,\n Authorization: `Bearer ${token.token}`,\n },\n });\n } catch (e: any) {\n if (e?.code === 'ETIMEDOUT' && retryCount > 0) {\n return this.requestRaw(url, headers, retryCount - 1);\n }\n throw e;\n }\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `User` from Graph API with size limit\n *\n * @param userId - The unique identifier for the `User` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getUserPhotoWithSizeLimit(\n userId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('users', userId, maxSize);\n }\n\n async getUserPhoto(\n userId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('users', userId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n * @param path - Resource endpoint in Microsoft Graph\n */\n async *getUsers(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n path: string = 'users',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(path, query, queryMode);\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `Group` from Graph API with size limit\n *\n * @param groupId - The unique identifier for the `Group` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getGroupPhotoWithSizeLimit(\n groupId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('groups', groupId, maxSize);\n }\n\n async getGroupPhoto(\n groupId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('groups', groupId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/group | Group}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n * @param path - Resource endpoint in Microsoft Graph\n */\n async *getGroups(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n path: string = 'groups',\n ): AsyncIterable<MicrosoftGraph.Group> {\n yield* this.requestCollection<MicrosoftGraph.Group>(path, query, queryMode);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n *\n */\n async *getGroupMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<GroupMember> {\n yield* this.requestCollection<GroupMember>(\n `groups/${groupId}/members`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroupUserMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `groups/${groupId}/members/microsoft.graph.user/`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/organization | Organization}\n * from Graph API\n * @public\n * @param tenantId - The unique identifier for the `Organization` resource\n *\n */\n async getOrganization(\n tenantId: string,\n ): Promise<MicrosoftGraph.Organization> {\n const response = await this.requestApi(`organization/${tenantId}`);\n\n if (response.status !== 200) {\n await this.handleError(`organization/${tenantId}`, response);\n }\n\n return await response.json();\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * from Graph API\n *\n * @param entityName - type of parent resource, either `User` or `Group`\n * @param id - The unique identifier for the `entityName` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n private async getPhotoWithSizeLimit(\n entityName: string,\n id: string,\n maxSize: number,\n ): Promise<string | undefined> {\n const response = await this.requestApi(`${entityName}/${id}/photos`);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError(`${entityName} photos`, response);\n }\n\n const result = await response.json();\n const photos = result.value as MicrosoftGraph.ProfilePhoto[];\n let selectedPhoto: MicrosoftGraph.ProfilePhoto | undefined = undefined;\n\n // Find the biggest picture that is smaller than the max size\n for (const p of photos) {\n if (\n !selectedPhoto ||\n (p.height! >= selectedPhoto.height! && p.height! <= maxSize)\n ) {\n selectedPhoto = p;\n }\n }\n\n if (!selectedPhoto) {\n return undefined;\n }\n\n return await this.getPhoto(entityName, id, selectedPhoto.id!);\n }\n\n private async getPhoto(\n entityName: string,\n id: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n const path = sizeId\n ? `${entityName}/${id}/photos/${sizeId}/$value`\n : `${entityName}/${id}/photo/$value`;\n const response = await this.requestApi(path);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError('photo', response);\n }\n\n return `data:image/jpeg;base64,${Buffer.from(\n await response.arrayBuffer(),\n ).toString('base64')}`;\n }\n\n private async handleError(path: string, response: Response): Promise<void> {\n const result = await response.json();\n const error = result.error as MicrosoftGraph.PublicError;\n\n throw new Error(\n `Error while reading ${path} from Microsoft Graph: ${error.code} - ${error.message}`,\n );\n }\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential","qs"],"mappings":"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"}
1
+ {"version":3,"file":"client.cjs.js","sources":["../../src/microsoftGraph/client.ts"],"sourcesContent":["/*\n * Copyright 2020 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 TokenCredential,\n DefaultAzureCredential,\n ClientSecretCredential,\n} from '@azure/identity';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport qs from 'qs';\nimport { MicrosoftGraphProviderConfig } from './config';\n\n/**\n * OData (Open Data Protocol) Query\n *\n * {@link https://docs.microsoft.com/en-us/odata/concepts/queryoptions-overview}\n * {@link https://docs.microsoft.com/en-us/graph/query-parameters}\n * @public\n */\nexport type ODataQuery = {\n /**\n * search resources within a collection matching a free-text search expression.\n */\n search?: string;\n /**\n * filter a collection of resources\n */\n filter?: string;\n /**\n * specifies the related resources or media streams to be included in line with retrieved resources\n */\n expand?: string;\n /**\n * request a specific set of properties for each entity or complex type\n */\n select?: string[];\n /**\n * Retrieves the total count of matching resources.\n */\n count?: boolean;\n /**\n * Maximum number of records to receive in one batch.\n */\n top?: number;\n};\n\n/**\n * Extends the base msgraph types to include the odata type.\n *\n * @public\n */\nexport type GroupMember =\n | (MicrosoftGraph.Group & { '@odata.type': '#microsoft.graph.group' })\n | (MicrosoftGraph.User & { '@odata.type': '#microsoft.graph.user' });\n\n/**\n * A HTTP Client that communicates with Microsoft Graph API.\n * Simplify Authentication and API calls to get `User` and `Group` from Microsoft Graph\n *\n * Uses `msal-node` for authentication\n *\n * @public\n */\nexport class MicrosoftGraphClient {\n /**\n * Factory method that instantiate `msal` client and return\n * an instance of `MicrosoftGraphClient`\n *\n * @public\n *\n * @param config - Configuration for Interacting with Graph API\n */\n static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient {\n const options = {\n authorityHost: config.authority,\n tenantId: config.tenantId,\n };\n\n const credential =\n config.clientId && config.clientSecret\n ? new ClientSecretCredential(\n config.tenantId,\n config.clientId,\n config.clientSecret,\n options,\n )\n : new DefaultAzureCredential(options);\n\n return new MicrosoftGraphClient(config.target, credential);\n }\n\n /**\n * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}\n * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls\n *\n */\n private readonly baseUrl: string;\n private readonly tokenCredential: TokenCredential;\n\n constructor(baseUrl: string, tokenCredential: TokenCredential) {\n this.baseUrl = baseUrl;\n this.tokenCredential = tokenCredential;\n }\n\n /**\n * Get a collection of resource from Graph API and\n * return an `AsyncIterable` of that resource\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *requestCollection<T>(\n path: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<T> {\n // upgrade to advanced query mode transparently when \"search\" is used\n // to stay backwards compatible.\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // not needed for \"search\"\n // as of https://docs.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http\n // even though a few other places say the opposite\n // - https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http#request-headers\n // - https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties\n if (appliedQueryMode === 'advanced' && (query?.filter || query?.select)) {\n query.count = true;\n }\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced'\n ? {\n // Eventual consistency is required for advanced querying capabilities\n // like \"$search\" or parts of \"$filter\".\n // If a new user/group is not found, it'll eventually be imported on a subsequent read\n ConsistencyLevel: 'eventual',\n }\n : {};\n\n let response = await this.requestApi(path, query, headers);\n\n for (;;) {\n if (response.status !== 200) {\n await this.handleError(path, response);\n }\n\n const result = await response.json();\n\n // Graph API return array of collections\n const elements: T[] = result.value;\n\n yield* elements;\n\n // Follow cursor to the next page if one is available\n if (!result['@odata.nextLink']) {\n return;\n }\n\n response = await this.requestRaw(result['@odata.nextLink'], headers);\n }\n }\n\n /**\n * Abstract on top of {@link MicrosoftGraphClient.requestRaw}\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param headers - optional HTTP headers\n */\n async requestApi(\n path: string,\n query?: ODataQuery,\n headers?: Record<string, string>,\n ): Promise<Response> {\n const queryString = qs.stringify(\n {\n $search: query?.search,\n $filter: query?.filter,\n $select: query?.select?.join(','),\n $expand: query?.expand,\n $count: query?.count,\n $top: query?.top,\n },\n {\n addQueryPrefix: true,\n encode: true,\n },\n );\n\n return await this.requestRaw(\n `${this.baseUrl}/${path}${queryString}`,\n headers,\n );\n }\n\n /**\n * Makes a HTTP call to Graph API with token\n *\n * @param url - HTTP Endpoint of Graph API\n * @param headers - optional HTTP headers\n */\n async requestRaw(\n url: string,\n headers?: Record<string, string>,\n retryCount = 2,\n ): Promise<Response> {\n // Make sure that we always have a valid access token (might be cached)\n const urlObj = new URL(url);\n const token = await this.tokenCredential.getToken(\n `${urlObj.protocol}//${urlObj.hostname}/.default`,\n );\n\n if (!token) {\n throw new Error('Failed to obtain token from Azure Identity');\n }\n\n try {\n return await fetch(url, {\n headers: {\n ...headers,\n Authorization: `Bearer ${token.token}`,\n },\n });\n } catch (e: any) {\n if (e?.code === 'ETIMEDOUT' && retryCount > 0) {\n return this.requestRaw(url, headers, retryCount - 1);\n }\n throw e;\n }\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `User` from Graph API with size limit\n *\n * @param userId - The unique identifier for the `User` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getUserPhotoWithSizeLimit(\n userId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('users', userId, maxSize);\n }\n\n async getUserPhoto(\n userId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('users', userId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n * @param path - Resource endpoint in Microsoft Graph\n */\n async *getUsers(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n path: string = 'users',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(path, query, queryMode);\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `Group` from Graph API with size limit\n *\n * @param groupId - The unique identifier for the `Group` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getGroupPhotoWithSizeLimit(\n groupId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('groups', groupId, maxSize);\n }\n\n async getGroupPhoto(\n groupId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('groups', groupId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/group | Group}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n * @param path - Resource endpoint in Microsoft Graph\n */\n async *getGroups(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n path: string = 'groups',\n ): AsyncIterable<MicrosoftGraph.Group> {\n yield* this.requestCollection<MicrosoftGraph.Group>(path, query, queryMode);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n *\n */\n async *getGroupMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<GroupMember> {\n yield* this.requestCollection<GroupMember>(\n `groups/${groupId}/members`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroupUserMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `groups/${groupId}/members/microsoft.graph.user/`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/organization | Organization}\n * from Graph API\n * @public\n * @param tenantId - The unique identifier for the `Organization` resource\n *\n */\n async getOrganization(\n tenantId: string,\n ): Promise<MicrosoftGraph.Organization> {\n const response = await this.requestApi(`organization/${tenantId}`);\n\n if (response.status !== 200) {\n await this.handleError(`organization/${tenantId}`, response);\n }\n\n return await response.json();\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * from Graph API\n *\n * @param entityName - type of parent resource, either `User` or `Group`\n * @param id - The unique identifier for the `entityName` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n private async getPhotoWithSizeLimit(\n entityName: string,\n id: string,\n maxSize: number,\n ): Promise<string | undefined> {\n const response = await this.requestApi(`${entityName}/${id}/photos`);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError(`${entityName} photos`, response);\n }\n\n const result = await response.json();\n const photos = result.value as MicrosoftGraph.ProfilePhoto[];\n let selectedPhoto: MicrosoftGraph.ProfilePhoto | undefined = undefined;\n\n // Find the biggest picture that is smaller than the max size\n for (const p of photos) {\n if (\n !selectedPhoto ||\n (p.height! >= selectedPhoto.height! && p.height! <= maxSize)\n ) {\n selectedPhoto = p;\n }\n }\n\n if (!selectedPhoto) {\n return undefined;\n }\n\n return await this.getPhoto(entityName, id, selectedPhoto.id!);\n }\n\n private async getPhoto(\n entityName: string,\n id: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n const path = sizeId\n ? `${entityName}/${id}/photos/${sizeId}/$value`\n : `${entityName}/${id}/photo/$value`;\n const response = await this.requestApi(path);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError('photo', response);\n }\n\n return `data:image/jpeg;base64,${Buffer.from(\n await response.arrayBuffer(),\n ).toString('base64')}`;\n }\n\n private async handleError(path: string, response: Response): Promise<void> {\n const result = await response.json();\n const error = result.error as MicrosoftGraph.PublicError;\n\n throw new Error(\n `Error while reading ${path} from Microsoft Graph: ${error.code} - ${error.message}`,\n );\n }\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential","qs"],"mappings":";;;;;;;;;AA4EO,MAAM,oBAAA,CAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShC,OAAO,OAAO,MAAA,EAA4D;AACxE,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,eAAe,MAAA,CAAO,SAAA;AAAA,MACtB,UAAU,MAAA,CAAO;AAAA,KACnB;AAEA,IAAA,MAAM,UAAA,GACJ,MAAA,CAAO,QAAA,IAAY,MAAA,CAAO,eACtB,IAAIA,+BAAA;AAAA,MACF,MAAA,CAAO,QAAA;AAAA,MACP,MAAA,CAAO,QAAA;AAAA,MACP,MAAA,CAAO,YAAA;AAAA,MACP;AAAA,KACF,GACA,IAAIC,+BAAA,CAAuB,OAAO,CAAA;AAExC,IAAA,OAAO,IAAI,oBAAA,CAAqB,MAAA,CAAO,MAAA,EAAQ,UAAU,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOiB,OAAA;AAAA,EACA,eAAA;AAAA,EAEjB,WAAA,CAAY,SAAiB,eAAA,EAAkC;AAC7D,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,iBAAA,CACL,IAAA,EACA,KAAA,EACA,SAAA,EACkB;AAGlB,IAAA,MAAM,gBAAA,GAAmB,KAAA,EAAO,MAAA,GAAS,UAAA,GAAa,SAAA,IAAa,OAAA;AAOnE,IAAA,IAAI,gBAAA,KAAqB,UAAA,KAAe,KAAA,EAAO,MAAA,IAAU,OAAO,MAAA,CAAA,EAAS;AACvE,MAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,IAChB;AACA,IAAA,MAAM,OAAA,GACJ,qBAAqB,UAAA,GACjB;AAAA;AAAA;AAAA;AAAA,MAIE,gBAAA,EAAkB;AAAA,QAEpB,EAAC;AAEP,IAAA,IAAI,WAAW,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,OAAO,OAAO,CAAA;AAEzD,IAAA,WAAS;AACP,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,EAAM,QAAQ,CAAA;AAAA,MACvC;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AAGnC,MAAA,MAAM,WAAgB,MAAA,CAAO,KAAA;AAE7B,MAAA,OAAO,QAAA;AAGP,MAAA,IAAI,CAAC,MAAA,CAAO,iBAAiB,CAAA,EAAG;AAC9B,QAAA;AAAA,MACF;AAEA,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,iBAAiB,GAAG,OAAO,CAAA;AAAA,IACrE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UAAA,CACJ,IAAA,EACA,KAAA,EACA,OAAA,EACmB;AACnB,IAAA,MAAM,cAAcC,mBAAA,CAAG,SAAA;AAAA,MACrB;AAAA,QACE,SAAS,KAAA,EAAO,MAAA;AAAA,QAChB,SAAS,KAAA,EAAO,MAAA;AAAA,QAChB,OAAA,EAAS,KAAA,EAAO,MAAA,EAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,QAChC,SAAS,KAAA,EAAO,MAAA;AAAA,QAChB,QAAQ,KAAA,EAAO,KAAA;AAAA,QACf,MAAM,KAAA,EAAO;AAAA,OACf;AAAA,MACA;AAAA,QACE,cAAA,EAAgB,IAAA;AAAA,QAChB,MAAA,EAAQ;AAAA;AACV,KACF;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,UAAA;AAAA,MAChB,GAAG,IAAA,CAAK,OAAO,CAAA,CAAA,EAAI,IAAI,GAAG,WAAW,CAAA,CAAA;AAAA,MACrC;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAA,CACJ,GAAA,EACA,OAAA,EACA,aAAa,CAAA,EACM;AAEnB,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,eAAA,CAAgB,QAAA;AAAA,MACvC,CAAA,EAAG,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK,OAAO,QAAQ,CAAA,SAAA;AAAA,KACxC;AAEA,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,MAAM,GAAA,EAAK;AAAA,QACtB,OAAA,EAAS;AAAA,UACP,GAAG,OAAA;AAAA,UACH,aAAA,EAAe,CAAA,OAAA,EAAU,KAAA,CAAM,KAAK,CAAA;AAAA;AACtC,OACD,CAAA;AAAA,IACH,SAAS,CAAA,EAAQ;AACf,MAAA,IAAI,CAAA,EAAG,IAAA,KAAS,WAAA,IAAe,UAAA,GAAa,CAAA,EAAG;AAC7C,QAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,EAAK,OAAA,EAAS,aAAa,CAAC,CAAA;AAAA,MACrD;AACA,MAAA,MAAM,CAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBAAA,CACJ,MAAA,EACA,OAAA,EAC6B;AAC7B,IAAA,OAAO,MAAM,IAAA,CAAK,qBAAA,CAAsB,OAAA,EAAS,QAAQ,OAAO,CAAA;AAAA,EAClE;AAAA,EAEA,MAAM,YAAA,CACJ,MAAA,EACA,MAAA,EAC6B;AAC7B,IAAA,OAAO,MAAM,IAAA,CAAK,QAAA,CAAS,OAAA,EAAS,QAAQ,MAAM,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,QAAA,CACL,KAAA,EACA,SAAA,EACA,OAAe,OAAA,EACqB;AACpC,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAuC,IAAA,EAAM,KAAA,EAAO,SAAS,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,0BAAA,CACJ,OAAA,EACA,OAAA,EAC6B;AAC7B,IAAA,OAAO,MAAM,IAAA,CAAK,qBAAA,CAAsB,QAAA,EAAU,SAAS,OAAO,CAAA;AAAA,EACpE;AAAA,EAEA,MAAM,aAAA,CACJ,OAAA,EACA,MAAA,EAC6B;AAC7B,IAAA,OAAO,MAAM,IAAA,CAAK,QAAA,CAAS,QAAA,EAAU,SAAS,MAAM,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,SAAA,CACL,KAAA,EACA,SAAA,EACA,OAAe,QAAA,EACsB;AACrC,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAwC,IAAA,EAAM,KAAA,EAAO,SAAS,CAAA;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,eAAA,CACL,OAAA,EACA,KAAA,EACA,SAAA,EAC4B;AAC5B,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,MACV,UAAU,OAAO,CAAA,QAAA,CAAA;AAAA,MACjB,KAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,mBAAA,CACL,OAAA,EACA,KAAA,EACA,SAAA,EACoC;AACpC,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,MACV,UAAU,OAAO,CAAA,8BAAA,CAAA;AAAA,MACjB,KAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBACJ,QAAA,EACsC;AACtC,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,UAAA,CAAW,CAAA,aAAA,EAAgB,QAAQ,CAAA,CAAE,CAAA;AAEjE,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,MAAM,IAAA,CAAK,WAAA,CAAY,CAAA,aAAA,EAAgB,QAAQ,IAAI,QAAQ,CAAA;AAAA,IAC7D;AAEA,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,qBAAA,CACZ,UAAA,EACA,EAAA,EACA,OAAA,EAC6B;AAC7B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,CAAW,GAAG,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,OAAA,CAAS,CAAA;AAEnE,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,OAAO,MAAA;AAAA,IACT,CAAA,MAAA,IAAW,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK;AAClC,MAAA,MAAM,IAAA,CAAK,WAAA,CAAY,CAAA,EAAG,UAAU,WAAW,QAAQ,CAAA;AAAA,IACzD;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,IAAA,MAAM,SAAS,MAAA,CAAO,KAAA;AACtB,IAAA,IAAI,aAAA,GAAyD,MAAA;AAG7D,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,IACE,CAAC,iBACA,CAAA,CAAE,MAAA,IAAW,cAAc,MAAA,IAAW,CAAA,CAAE,UAAW,OAAA,EACpD;AACA,QAAA,aAAA,GAAgB,CAAA;AAAA,MAClB;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,QAAA,CAAS,UAAA,EAAY,EAAA,EAAI,cAAc,EAAG,CAAA;AAAA,EAC9D;AAAA,EAEA,MAAc,QAAA,CACZ,UAAA,EACA,EAAA,EACA,MAAA,EAC6B;AAC7B,IAAA,MAAM,IAAA,GAAO,MAAA,GACT,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,QAAA,EAAW,MAAM,CAAA,OAAA,CAAA,GACpC,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,aAAA,CAAA;AACvB,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA;AAE3C,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,OAAO,MAAA;AAAA,IACT,CAAA,MAAA,IAAW,QAAA,CAAS,MAAA,KAAW,GAAA,EAAK;AAClC,MAAA,MAAM,IAAA,CAAK,WAAA,CAAY,OAAA,EAAS,QAAQ,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,0BAA0B,MAAA,CAAO,IAAA;AAAA,MACtC,MAAM,SAAS,WAAA;AAAY,KAC7B,CAAE,QAAA,CAAS,QAAQ,CAAC,CAAA,CAAA;AAAA,EACtB;AAAA,EAEA,MAAc,WAAA,CAAY,IAAA,EAAc,QAAA,EAAmC;AACzE,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,IAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AAErB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,uBAAuB,IAAI,CAAA,uBAAA,EAA0B,MAAM,IAAI,CAAA,GAAA,EAAM,MAAM,OAAO,CAAA;AAAA,KACpF;AAAA,EACF;AACF;;;;"}
@@ -29,9 +29,6 @@ function _interopNamespaceCompat(e) {
29
29
  var uuid__namespace = /*#__PURE__*/_interopNamespaceCompat(uuid);
30
30
 
31
31
  class MicrosoftGraphOrgEntityProvider {
32
- constructor(options) {
33
- this.options = options;
34
- }
35
32
  connection;
36
33
  scheduleFn;
37
34
  static fromConfig(configRoot, options) {
@@ -117,6 +114,10 @@ class MicrosoftGraphOrgEntityProvider {
117
114
  }
118
115
  return result;
119
116
  }
117
+ options;
118
+ constructor(options) {
119
+ this.options = options;
120
+ }
120
121
  /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */
121
122
  getProviderName() {
122
123
  return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;
@@ -1 +1 @@
1
- {"version":3,"file":"MicrosoftGraphOrgEntityProvider.cjs.js","sources":["../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2021 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 ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\nimport { merge } from 'lodash';\nimport * as uuid from 'uuid';\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 ProviderConfigTransformer,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport {\n LoggerService,\n SchedulerService,\n SchedulerServiceTaskRunner,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link MicrosoftGraphOrgEntityProvider}.\n *\n * @public\n */\nexport type MicrosoftGraphOrgEntityProviderOptions =\n | MicrosoftGraphOrgEntityProviderLegacyOptions\n | {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: SchedulerService;\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.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\n };\n\n/**\n * Legacy options for {@link MicrosoftGraphOrgEntityProvider}\n * based on `catalog.processors.microsoftGraphOrg`.\n *\n * @public\n * @deprecated This interface exists for backwards compatibility only and will be removed in the future.\n */\nexport interface MicrosoftGraphOrgEntityProviderLegacyOptions {\n /**\n * A unique, stable identifier for this provider.\n *\n * @example \"production\"\n */\n id: string;\n\n /**\n * The target that this provider should consume.\n *\n * Should exactly match the \"target\" field of one of the provider\n * configuration entries.\n */\n target: string;\n\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n */\n userTransformer?: UserTransformer;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n */\n groupTransformer?: GroupTransformer;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n */\n organizationTransformer?: OrganizationTransformer;\n\n /**\n * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?: ProviderConfigTransformer;\n}\n\n/**\n * Reads user and group entries out of Microsoft Graph, and provides them as\n * User and Group entities for the catalog.\n *\n * @public\n */\nexport class MicrosoftGraphOrgEntityProvider implements EntityProvider {\n private connection?: EntityProviderConnection;\n private scheduleFn?: () => Promise<void>;\n\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderOptions,\n ): MicrosoftGraphOrgEntityProvider[] {\n if ('id' in options) {\n return [\n MicrosoftGraphOrgEntityProvider.fromLegacyConfig(configRoot, options),\n ];\n }\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\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\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new Error(\n `No schedule provided neither via code nor config for MicrosoftGraphOrgEntityProvider:${providerConfig.id}.`,\n );\n }\n\n const taskRunner =\n options.schedule ??\n options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);\n\n const provider = new MicrosoftGraphOrgEntityProvider({\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 if (taskRunner !== 'manual') {\n provider.schedule(taskRunner);\n }\n\n return provider;\n });\n }\n\n /**\n * @deprecated Exists for backwards compatibility only and will be removed in the future.\n */\n private static fromLegacyConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderLegacyOptions,\n ): MicrosoftGraphOrgEntityProvider {\n options.logger.warn(\n 'Deprecated msgraph config \"catalog.processors.microsoftGraphOrg\" used. Use \"catalog.providers.microsoftGraphOrg\" instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n const config = configRoot.getOptionalConfig(\n 'catalog.processors.microsoftGraphOrg',\n );\n const providers = config ? readMicrosoftGraphConfig(config) : [];\n const provider = providers.find(p => options.target.startsWith(p.target));\n\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches \"${options.target}\". Please add a configuration entry for it under \"catalog.processors.microsoftGraphOrg.providers\".`,\n );\n }\n\n const logger = options.logger.child({\n target: options.target,\n });\n\n const result = new MicrosoftGraphOrgEntityProvider({\n id: options.id,\n userTransformer: options.userTransformer,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n providerConfigTransformer: options.providerConfigTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n constructor(\n private 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\n /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection) {\n this.connection = connection;\n await this.scheduleFn?.();\n }\n\n /**\n * Runs one complete ingestion loop. Call this method regularly at some\n * appropriate cadence.\n */\n async read(options?: { logger?: LoggerService }) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n const logger = options?.logger ?? this.options.logger;\n const provider = this.options.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n userSelect: provider.userSelect,\n userPath: provider.userPath,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n userGroupMemberPath: provider.userGroupMemberPath,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n groupPath: provider.groupPath,\n groupIncludeSubGroups: provider.groupIncludeSubGroups,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n },\n );\n\n const { markCommitComplete } = markReadComplete({ users, groups });\n\n await this.connection.applyMutation({\n type: 'full',\n entities: [...users, ...groups].map(entity => ({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n })),\n });\n\n markCommitComplete();\n }\n\n private schedule(taskRunner: SchedulerServiceTaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async () => {\n const logger = this.options.logger.child({\n class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,\n taskId: id,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.read({ logger });\n } catch (error) {\n logger.error(\n `${this.getProviderName()} refresh failed, ${error}`,\n error,\n );\n }\n },\n });\n };\n }\n}\n\n// Helps wrap the timing and logging behaviors\nfunction trackProgress(logger: LoggerService) {\n let timestamp = Date.now();\n let summary: string;\n\n logger.info('Reading msgraph users and groups');\n\n function markReadComplete(read: { users: unknown[]; groups: unknown[] }) {\n summary = `${read.users.length} msgraph users and ${read.groups.length} msgraph groups`;\n const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n timestamp = Date.now();\n logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`);\n return { markCommitComplete };\n }\n\n function markCommitComplete() {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`);\n }\n\n return { markReadComplete };\n}\n\n// Makes sure that emitted entities have a proper location based on their uuid\nexport function 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 merge(\n {\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n },\n entity,\n ) as Entity;\n}\n"],"names":["readProviderConfigs","config","readMicrosoftGraphConfig","client","MicrosoftGraphClient","readMicrosoftGraphOrg","uuid","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"mappings":"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"}
1
+ {"version":3,"file":"MicrosoftGraphOrgEntityProvider.cjs.js","sources":["../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2021 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 ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\nimport { merge } from 'lodash';\nimport * as uuid from 'uuid';\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 ProviderConfigTransformer,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport {\n LoggerService,\n SchedulerService,\n SchedulerServiceTaskRunner,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link MicrosoftGraphOrgEntityProvider}.\n *\n * @public\n */\nexport type MicrosoftGraphOrgEntityProviderOptions =\n | MicrosoftGraphOrgEntityProviderLegacyOptions\n | {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: SchedulerService;\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.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\n };\n\n/**\n * Legacy options for {@link MicrosoftGraphOrgEntityProvider}\n * based on `catalog.processors.microsoftGraphOrg`.\n *\n * @public\n * @deprecated This interface exists for backwards compatibility only and will be removed in the future.\n */\nexport interface MicrosoftGraphOrgEntityProviderLegacyOptions {\n /**\n * A unique, stable identifier for this provider.\n *\n * @example \"production\"\n */\n id: string;\n\n /**\n * The target that this provider should consume.\n *\n * Should exactly match the \"target\" field of one of the provider\n * configuration entries.\n */\n target: string;\n\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n */\n userTransformer?: UserTransformer;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n */\n groupTransformer?: GroupTransformer;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n */\n organizationTransformer?: OrganizationTransformer;\n\n /**\n * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?: ProviderConfigTransformer;\n}\n\n/**\n * Reads user and group entries out of Microsoft Graph, and provides them as\n * User and Group entities for the catalog.\n *\n * @public\n */\nexport class MicrosoftGraphOrgEntityProvider implements EntityProvider {\n private connection?: EntityProviderConnection;\n private scheduleFn?: () => Promise<void>;\n\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderOptions,\n ): MicrosoftGraphOrgEntityProvider[] {\n if ('id' in options) {\n return [\n MicrosoftGraphOrgEntityProvider.fromLegacyConfig(configRoot, options),\n ];\n }\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\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\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new Error(\n `No schedule provided neither via code nor config for MicrosoftGraphOrgEntityProvider:${providerConfig.id}.`,\n );\n }\n\n const taskRunner =\n options.schedule ??\n options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);\n\n const provider = new MicrosoftGraphOrgEntityProvider({\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 if (taskRunner !== 'manual') {\n provider.schedule(taskRunner);\n }\n\n return provider;\n });\n }\n\n /**\n * @deprecated Exists for backwards compatibility only and will be removed in the future.\n */\n private static fromLegacyConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderLegacyOptions,\n ): MicrosoftGraphOrgEntityProvider {\n options.logger.warn(\n 'Deprecated msgraph config \"catalog.processors.microsoftGraphOrg\" used. Use \"catalog.providers.microsoftGraphOrg\" instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n const config = configRoot.getOptionalConfig(\n 'catalog.processors.microsoftGraphOrg',\n );\n const providers = config ? readMicrosoftGraphConfig(config) : [];\n const provider = providers.find(p => options.target.startsWith(p.target));\n\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches \"${options.target}\". Please add a configuration entry for it under \"catalog.processors.microsoftGraphOrg.providers\".`,\n );\n }\n\n const logger = options.logger.child({\n target: options.target,\n });\n\n const result = new MicrosoftGraphOrgEntityProvider({\n id: options.id,\n userTransformer: options.userTransformer,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n providerConfigTransformer: options.providerConfigTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n private 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-node#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection) {\n this.connection = connection;\n await this.scheduleFn?.();\n }\n\n /**\n * Runs one complete ingestion loop. Call this method regularly at some\n * appropriate cadence.\n */\n async read(options?: { logger?: LoggerService }) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n const logger = options?.logger ?? this.options.logger;\n const provider = this.options.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n userSelect: provider.userSelect,\n userPath: provider.userPath,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n userGroupMemberPath: provider.userGroupMemberPath,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n groupPath: provider.groupPath,\n groupIncludeSubGroups: provider.groupIncludeSubGroups,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n },\n );\n\n const { markCommitComplete } = markReadComplete({ users, groups });\n\n await this.connection.applyMutation({\n type: 'full',\n entities: [...users, ...groups].map(entity => ({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n })),\n });\n\n markCommitComplete();\n }\n\n private schedule(taskRunner: SchedulerServiceTaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async () => {\n const logger = this.options.logger.child({\n class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,\n taskId: id,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.read({ logger });\n } catch (error) {\n logger.error(\n `${this.getProviderName()} refresh failed, ${error}`,\n error,\n );\n }\n },\n });\n };\n }\n}\n\n// Helps wrap the timing and logging behaviors\nfunction trackProgress(logger: LoggerService) {\n let timestamp = Date.now();\n let summary: string;\n\n logger.info('Reading msgraph users and groups');\n\n function markReadComplete(read: { users: unknown[]; groups: unknown[] }) {\n summary = `${read.users.length} msgraph users and ${read.groups.length} msgraph groups`;\n const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n timestamp = Date.now();\n logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`);\n return { markCommitComplete };\n }\n\n function markCommitComplete() {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`);\n }\n\n return { markReadComplete };\n}\n\n// Makes sure that emitted entities have a proper location based on their uuid\nexport function 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 merge(\n {\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n },\n entity,\n ) as Entity;\n}\n"],"names":["readProviderConfigs","config","readMicrosoftGraphConfig","client","MicrosoftGraphClient","readMicrosoftGraphOrg","uuid","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend-module-msgraph",
3
- "version": "0.8.1",
3
+ "version": "0.8.2-next.0",
4
4
  "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph",
5
5
  "backstage": {
6
6
  "role": "backend-plugin-module",
@@ -66,11 +66,11 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@azure/identity": "^4.0.0",
69
- "@backstage/backend-plugin-api": "^1.4.4",
70
- "@backstage/catalog-model": "^1.7.5",
71
- "@backstage/config": "^1.3.5",
72
- "@backstage/plugin-catalog-common": "^1.1.6",
73
- "@backstage/plugin-catalog-node": "^1.19.1",
69
+ "@backstage/backend-plugin-api": "1.4.5-next.0",
70
+ "@backstage/catalog-model": "1.7.6-next.0",
71
+ "@backstage/config": "1.3.6-next.0",
72
+ "@backstage/plugin-catalog-common": "1.1.7-next.0",
73
+ "@backstage/plugin-catalog-node": "1.19.2-next.0",
74
74
  "@microsoft/microsoft-graph-types": "^2.6.0",
75
75
  "lodash": "^4.17.21",
76
76
  "p-limit": "^3.0.2",
@@ -78,8 +78,8 @@
78
78
  "uuid": "^11.0.0"
79
79
  },
80
80
  "devDependencies": {
81
- "@backstage/backend-test-utils": "^1.9.1",
82
- "@backstage/cli": "^0.34.4",
81
+ "@backstage/backend-test-utils": "1.10.0-next.0",
82
+ "@backstage/cli": "0.34.5-next.0",
83
83
  "@types/lodash": "^4.14.151",
84
84
  "msw": "^1.0.0"
85
85
  },