@backstage/catalog-client 0.3.19 → 0.4.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 +13 -0
- package/dist/index.cjs.js +16 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +16 -2
- package/dist/index.esm.js.map +1 -1
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @backstage/catalog-client
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- dbcaa6387a: Extends the `CatalogClient` interface with a `refreshEntity` method.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 9ef2987a83: Update `AddLocationResponse` to optionally return `exists` to signal that the location already exists, this is only returned when calling `addLocation` in dryRun.
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @backstage/catalog-model@0.9.3
|
|
14
|
+
- @backstage/config@0.1.10
|
|
15
|
+
|
|
3
16
|
## 0.3.19
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -64,6 +64,19 @@ class CatalogClient {
|
|
|
64
64
|
const {kind, namespace = "default", name} = compoundName;
|
|
65
65
|
return this.requestOptional("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}`, options);
|
|
66
66
|
}
|
|
67
|
+
async refreshEntity(entityRef, options) {
|
|
68
|
+
const response = await fetch__default['default'](`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
|
|
69
|
+
headers: {
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
|
|
72
|
+
},
|
|
73
|
+
method: "POST",
|
|
74
|
+
body: JSON.stringify({entityRef})
|
|
75
|
+
});
|
|
76
|
+
if (response.status !== 200) {
|
|
77
|
+
throw new Error(await response.text());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
67
80
|
async addLocation({type = "url", target, dryRun, presence}, options) {
|
|
68
81
|
const response = await fetch__default['default'](`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
|
|
69
82
|
headers: {
|
|
@@ -76,13 +89,14 @@ class CatalogClient {
|
|
|
76
89
|
if (response.status !== 201) {
|
|
77
90
|
throw new Error(await response.text());
|
|
78
91
|
}
|
|
79
|
-
const {location, entities} = await response.json();
|
|
92
|
+
const {location, entities, exists} = await response.json();
|
|
80
93
|
if (!location) {
|
|
81
94
|
throw new Error(`Location wasn't added: ${target}`);
|
|
82
95
|
}
|
|
83
96
|
return {
|
|
84
97
|
location,
|
|
85
|
-
entities
|
|
98
|
+
entities,
|
|
99
|
+
exists
|
|
86
100
|
};
|
|
87
101
|
}
|
|
88
102
|
async getOriginLocationByEntity(entity, options) {
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/CatalogClient.ts","../src/types/status.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 { Entity, EntityName, Location } from '@backstage/catalog-model';\n\n/** @public */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/** @public */\nexport type CatalogEntitiesRequest = {\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n fields?: string[] | undefined;\n};\n\n/** @public */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/** @public */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/** @public */\nexport interface CatalogApi {\n // Entities\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/** @public */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/** @public */\nexport type AddLocationResponse = {\n location: Location;\n entities: Entity[];\n};\n","/*\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 Entity,\n EntityName,\n Location,\n LOCATION_ANNOTATION,\n ORIGIN_LOCATION_ANNOTATION,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\n\n/** @public */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: { discoveryApi: DiscoveryApi }) {\n this.discoveryApi = options.discoveryApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n 'GET',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [] } = request ?? {};\n const filterItems = [filter].flat();\n const params: string[] = [];\n\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of filterItems) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(encodeURIComponent(key));\n } else if (typeof v === 'string') {\n filterParts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,\n );\n }\n }\n }\n\n if (filterParts.length) {\n params.push(`filter=${filterParts.join(',')}`);\n }\n }\n\n if (fields.length) {\n params.push(`fields=${fields.map(encodeURIComponent).join(',')}`);\n }\n\n const query = params.length ? `?${params.join('&')}` : '';\n const entities: Entity[] = await this.requestRequired(\n 'GET',\n `/entities${query}`,\n options,\n );\n\n const refCompare = (a: Entity, b: Entity) => {\n // in case field filtering is used, these fields might not be part of the response\n if (\n a.metadata?.name === undefined ||\n a.kind === undefined ||\n b.metadata?.name === undefined ||\n b.kind === undefined\n ) {\n return 0;\n }\n\n const aRef = stringifyEntityRef(a);\n const bRef = stringifyEntityRef(b);\n if (aRef < bRef) {\n return -1;\n }\n if (aRef > bRef) {\n return 1;\n }\n return 0;\n };\n\n return { items: entities.sort(refCompare) };\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}`,\n options,\n );\n }\n\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/locations${\n dryRun ? '?dryRun=true' : ''\n }`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ type, target, presence }),\n },\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n };\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound =\n entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/entities/by-uid/${encodeURIComponent(uid)}`,\n options,\n );\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private async requestOptional(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any | undefined> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\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\n/**\n * The entity `status.items[].type` for the status of the processing engine in\n * regards to an entity.\n *\n * @public\n */\nexport const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =\n 'backstage.io/catalog-processing';\n"],"names":["stringifyEntityRef","fetch","ORIGIN_LOCATION_ANNOTATION","stringifyLocationReference","LOCATION_ANNOTATION","ResponseError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/CatalogClient.ts","../src/types/status.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 { Entity, EntityName, Location } from '@backstage/catalog-model';\n\n/** @public */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/** @public */\nexport type CatalogEntitiesRequest = {\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n fields?: string[] | undefined;\n};\n\n/** @public */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/** @public */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/** @public */\nexport interface CatalogApi {\n // Entities\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/** @public */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/** @public */\nexport type AddLocationResponse = {\n location: Location;\n entities: Entity[];\n // Exists is only set in DryRun mode.\n exists?: boolean;\n};\n","/*\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 Entity,\n EntityName,\n Location,\n LOCATION_ANNOTATION,\n ORIGIN_LOCATION_ANNOTATION,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\n\n/** @public */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: { discoveryApi: DiscoveryApi }) {\n this.discoveryApi = options.discoveryApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n 'GET',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [] } = request ?? {};\n const filterItems = [filter].flat();\n const params: string[] = [];\n\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of filterItems) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(encodeURIComponent(key));\n } else if (typeof v === 'string') {\n filterParts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,\n );\n }\n }\n }\n\n if (filterParts.length) {\n params.push(`filter=${filterParts.join(',')}`);\n }\n }\n\n if (fields.length) {\n params.push(`fields=${fields.map(encodeURIComponent).join(',')}`);\n }\n\n const query = params.length ? `?${params.join('&')}` : '';\n const entities: Entity[] = await this.requestRequired(\n 'GET',\n `/entities${query}`,\n options,\n );\n\n const refCompare = (a: Entity, b: Entity) => {\n // in case field filtering is used, these fields might not be part of the response\n if (\n a.metadata?.name === undefined ||\n a.kind === undefined ||\n b.metadata?.name === undefined ||\n b.kind === undefined\n ) {\n return 0;\n }\n\n const aRef = stringifyEntityRef(a);\n const bRef = stringifyEntityRef(b);\n if (aRef < bRef) {\n return -1;\n }\n if (aRef > bRef) {\n return 1;\n }\n return 0;\n };\n\n return { items: entities.sort(refCompare) };\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}`,\n options,\n );\n }\n\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/refresh`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ entityRef }),\n },\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/locations${\n dryRun ? '?dryRun=true' : ''\n }`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ type, target, presence }),\n },\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound =\n entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/entities/by-uid/${encodeURIComponent(uid)}`,\n options,\n );\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private async requestOptional(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any | undefined> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\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\n/**\n * The entity `status.items[].type` for the status of the processing engine in\n * regards to an entity.\n *\n * @public\n */\nexport const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =\n 'backstage.io/catalog-processing';\n"],"names":["stringifyEntityRef","fetch","ORIGIN_LOCATION_ANNOTATION","stringifyLocationReference","LOCATION_ANNOTATION","ResponseError"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ interface CatalogApi {
|
|
|
20
20
|
getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>;
|
|
21
21
|
getEntityByName(name: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>;
|
|
22
22
|
removeEntityByUid(uid: string, options?: CatalogRequestOptions): Promise<void>;
|
|
23
|
+
refreshEntity(entityRef: string, options?: CatalogRequestOptions): Promise<void>;
|
|
23
24
|
getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
|
24
25
|
getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
|
25
26
|
getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
|
@@ -37,6 +38,7 @@ declare type AddLocationRequest = {
|
|
|
37
38
|
declare type AddLocationResponse = {
|
|
38
39
|
location: Location;
|
|
39
40
|
entities: Entity[];
|
|
41
|
+
exists?: boolean;
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
/**
|
|
@@ -57,6 +59,7 @@ declare class CatalogClient implements CatalogApi {
|
|
|
57
59
|
getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
|
58
60
|
getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>;
|
|
59
61
|
getEntityByName(compoundName: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>;
|
|
62
|
+
refreshEntity(entityRef: string, options?: CatalogRequestOptions): Promise<void>;
|
|
60
63
|
addLocation({ type, target, dryRun, presence }: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>;
|
|
61
64
|
getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
|
62
65
|
getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
|
package/dist/index.esm.js
CHANGED
|
@@ -56,6 +56,19 @@ class CatalogClient {
|
|
|
56
56
|
const {kind, namespace = "default", name} = compoundName;
|
|
57
57
|
return this.requestOptional("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}`, options);
|
|
58
58
|
}
|
|
59
|
+
async refreshEntity(entityRef, options) {
|
|
60
|
+
const response = await fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
|
|
61
|
+
headers: {
|
|
62
|
+
"Content-Type": "application/json",
|
|
63
|
+
...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
|
|
64
|
+
},
|
|
65
|
+
method: "POST",
|
|
66
|
+
body: JSON.stringify({entityRef})
|
|
67
|
+
});
|
|
68
|
+
if (response.status !== 200) {
|
|
69
|
+
throw new Error(await response.text());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
59
72
|
async addLocation({type = "url", target, dryRun, presence}, options) {
|
|
60
73
|
const response = await fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
|
|
61
74
|
headers: {
|
|
@@ -68,13 +81,14 @@ class CatalogClient {
|
|
|
68
81
|
if (response.status !== 201) {
|
|
69
82
|
throw new Error(await response.text());
|
|
70
83
|
}
|
|
71
|
-
const {location, entities} = await response.json();
|
|
84
|
+
const {location, entities, exists} = await response.json();
|
|
72
85
|
if (!location) {
|
|
73
86
|
throw new Error(`Location wasn't added: ${target}`);
|
|
74
87
|
}
|
|
75
88
|
return {
|
|
76
89
|
location,
|
|
77
|
-
entities
|
|
90
|
+
entities,
|
|
91
|
+
exists
|
|
78
92
|
};
|
|
79
93
|
}
|
|
80
94
|
async getOriginLocationByEntity(entity, options) {
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/CatalogClient.ts","../src/types/status.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 { Entity, EntityName, Location } from '@backstage/catalog-model';\n\n/** @public */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/** @public */\nexport type CatalogEntitiesRequest = {\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n fields?: string[] | undefined;\n};\n\n/** @public */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/** @public */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/** @public */\nexport interface CatalogApi {\n // Entities\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/** @public */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/** @public */\nexport type AddLocationResponse = {\n location: Location;\n entities: Entity[];\n};\n","/*\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 Entity,\n EntityName,\n Location,\n LOCATION_ANNOTATION,\n ORIGIN_LOCATION_ANNOTATION,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\n\n/** @public */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: { discoveryApi: DiscoveryApi }) {\n this.discoveryApi = options.discoveryApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n 'GET',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [] } = request ?? {};\n const filterItems = [filter].flat();\n const params: string[] = [];\n\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of filterItems) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(encodeURIComponent(key));\n } else if (typeof v === 'string') {\n filterParts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,\n );\n }\n }\n }\n\n if (filterParts.length) {\n params.push(`filter=${filterParts.join(',')}`);\n }\n }\n\n if (fields.length) {\n params.push(`fields=${fields.map(encodeURIComponent).join(',')}`);\n }\n\n const query = params.length ? `?${params.join('&')}` : '';\n const entities: Entity[] = await this.requestRequired(\n 'GET',\n `/entities${query}`,\n options,\n );\n\n const refCompare = (a: Entity, b: Entity) => {\n // in case field filtering is used, these fields might not be part of the response\n if (\n a.metadata?.name === undefined ||\n a.kind === undefined ||\n b.metadata?.name === undefined ||\n b.kind === undefined\n ) {\n return 0;\n }\n\n const aRef = stringifyEntityRef(a);\n const bRef = stringifyEntityRef(b);\n if (aRef < bRef) {\n return -1;\n }\n if (aRef > bRef) {\n return 1;\n }\n return 0;\n };\n\n return { items: entities.sort(refCompare) };\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}`,\n options,\n );\n }\n\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/locations${\n dryRun ? '?dryRun=true' : ''\n }`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ type, target, presence }),\n },\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n };\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound =\n entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/entities/by-uid/${encodeURIComponent(uid)}`,\n options,\n );\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private async requestOptional(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any | undefined> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\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\n/**\n * The entity `status.items[].type` for the status of the processing engine in\n * regards to an entity.\n *\n * @public\n */\nexport const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =\n 'backstage.io/catalog-processing';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/CatalogClient.ts","../src/types/status.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 { Entity, EntityName, Location } from '@backstage/catalog-model';\n\n/** @public */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/** @public */\nexport type CatalogEntitiesRequest = {\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n fields?: string[] | undefined;\n};\n\n/** @public */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/** @public */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/** @public */\nexport interface CatalogApi {\n // Entities\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/** @public */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/** @public */\nexport type AddLocationResponse = {\n location: Location;\n entities: Entity[];\n // Exists is only set in DryRun mode.\n exists?: boolean;\n};\n","/*\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 Entity,\n EntityName,\n Location,\n LOCATION_ANNOTATION,\n ORIGIN_LOCATION_ANNOTATION,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\n\n/** @public */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: { discoveryApi: DiscoveryApi }) {\n this.discoveryApi = options.discoveryApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n 'GET',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [] } = request ?? {};\n const filterItems = [filter].flat();\n const params: string[] = [];\n\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of filterItems) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(encodeURIComponent(key));\n } else if (typeof v === 'string') {\n filterParts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,\n );\n }\n }\n }\n\n if (filterParts.length) {\n params.push(`filter=${filterParts.join(',')}`);\n }\n }\n\n if (fields.length) {\n params.push(`fields=${fields.map(encodeURIComponent).join(',')}`);\n }\n\n const query = params.length ? `?${params.join('&')}` : '';\n const entities: Entity[] = await this.requestRequired(\n 'GET',\n `/entities${query}`,\n options,\n );\n\n const refCompare = (a: Entity, b: Entity) => {\n // in case field filtering is used, these fields might not be part of the response\n if (\n a.metadata?.name === undefined ||\n a.kind === undefined ||\n b.metadata?.name === undefined ||\n b.kind === undefined\n ) {\n return 0;\n }\n\n const aRef = stringifyEntityRef(a);\n const bRef = stringifyEntityRef(b);\n if (aRef < bRef) {\n return -1;\n }\n if (aRef > bRef) {\n return 1;\n }\n return 0;\n };\n\n return { items: entities.sort(refCompare) };\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}`,\n options,\n );\n }\n\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/refresh`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ entityRef }),\n },\n );\n\n if (response.status !== 200) {\n throw new Error(await response.text());\n }\n }\n\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await fetch(\n `${await this.discoveryApi.getBaseUrl('catalog')}/locations${\n dryRun ? '?dryRun=true' : ''\n }`,\n {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify({ type, target, presence }),\n },\n );\n\n if (response.status !== 201) {\n throw new Error(await response.text());\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound =\n entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const locationCompound = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n if (!locationCompound) {\n return undefined;\n }\n const all: { data: Location }[] = await this.requestRequired(\n 'GET',\n '/locations',\n options,\n );\n return all\n .map(r => r.data)\n .find(l => locationCompound === stringifyLocationReference(l));\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/locations/${encodeURIComponent(id)}`,\n options,\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n 'DELETE',\n `/entities/by-uid/${encodeURIComponent(uid)}`,\n options,\n );\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private async requestOptional(\n method: string,\n path: string,\n options?: CatalogRequestOptions,\n ): Promise<any | undefined> {\n const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`;\n const headers: Record<string, string> = options?.token\n ? { Authorization: `Bearer ${options.token}` }\n : {};\n const response = await fetch(url, { method, headers });\n\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\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\n/**\n * The entity `status.items[].type` for the status of the processing engine in\n * regards to an entity.\n *\n * @public\n */\nexport const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =\n 'backstage.io/catalog-processing';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/catalog-client",
|
|
3
|
-
"
|
|
3
|
+
"description": "An isomorphic client for the catalog backend",
|
|
4
|
+
"version": "0.4.0",
|
|
4
5
|
"main": "dist/index.cjs.js",
|
|
5
6
|
"types": "dist/index.d.ts",
|
|
6
7
|
"license": "Apache-2.0",
|
|
@@ -29,19 +30,19 @@
|
|
|
29
30
|
"clean": "backstage-cli clean"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@backstage/catalog-model": "^0.9.
|
|
33
|
-
"@backstage/config": "^0.1.
|
|
33
|
+
"@backstage/catalog-model": "^0.9.3",
|
|
34
|
+
"@backstage/config": "^0.1.10",
|
|
34
35
|
"@backstage/errors": "^0.1.2",
|
|
35
36
|
"cross-fetch": "^3.0.6"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@backstage/cli": "^0.7.
|
|
39
|
+
"@backstage/cli": "^0.7.13",
|
|
39
40
|
"@types/jest": "^26.0.7",
|
|
40
41
|
"msw": "^0.29.0"
|
|
41
42
|
},
|
|
42
43
|
"files": [
|
|
43
44
|
"dist"
|
|
44
45
|
],
|
|
45
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "2fd2dbc5d2fad9da5f623126920958970aea469b",
|
|
46
47
|
"module": "dist/index.esm.js"
|
|
47
48
|
}
|