@backstage/catalog-client 0.4.0 → 0.5.3

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,43 @@
1
1
  # @backstage/catalog-client
2
2
 
3
+ ## 0.5.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 7927005152: Add the ability to supply a custom `fetchApi`. In the default frontend app setup, this will use the `fetchApiRef` implementation.
8
+ - 5463c03b35: Add support for passing paging parameters to the getEntities call of the catalog client
9
+
10
+ ## 0.5.2
11
+
12
+ ### Patch Changes
13
+
14
+ - 3bf2238187: Update to the right version of @backstage/errors
15
+ - Updated dependencies
16
+ - @backstage/catalog-model@0.9.7
17
+
18
+ ## 0.5.1
19
+
20
+ ### Patch Changes
21
+
22
+ - 39e92897e4: Improved API documentation for catalog-client.
23
+
24
+ ## 0.5.0
25
+
26
+ ### Minor Changes
27
+
28
+ - bb0f6b8a0f: Updates the `<EntitySwitch if={asyncMethod}/>` to accept asynchronous `if` functions.
29
+
30
+ Adds the new `getEntityAncestors` method to `CatalogClient`.
31
+
32
+ Updates the `<EntityProcessingErrorsPanel />` to make use of the ancestry endpoint to display errors for entities further up the ancestry tree. This makes it easier to discover issues where for example the origin location has been removed or malformed.
33
+
34
+ `hasCatalogProcessingErrors()` is now changed to be asynchronous so any calls outside the already established entitySwitch need to be awaited.
35
+
36
+ ### Patch Changes
37
+
38
+ - Updated dependencies
39
+ - @backstage/catalog-model@0.9.4
40
+
3
41
  ## 0.4.0
4
42
 
5
43
  ### Minor Changes
package/dist/index.cjs.js CHANGED
@@ -4,23 +4,28 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var catalogModel = require('@backstage/catalog-model');
6
6
  var errors = require('@backstage/errors');
7
- var fetch = require('cross-fetch');
7
+ var crossFetch = require('cross-fetch');
8
8
 
9
9
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
10
 
11
- var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
11
+ var crossFetch__default = /*#__PURE__*/_interopDefaultLegacy(crossFetch);
12
12
 
13
13
  const CATALOG_FILTER_EXISTS = Symbol("CATALOG_FILTER_EXISTS");
14
14
 
15
15
  class CatalogClient {
16
16
  constructor(options) {
17
17
  this.discoveryApi = options.discoveryApi;
18
+ this.fetchApi = options.fetchApi || { fetch: crossFetch__default["default"] };
19
+ }
20
+ async getEntityAncestors(request, options) {
21
+ const { kind, namespace, name } = catalogModel.parseEntityRef(request.entityRef);
22
+ return await this.requestRequired("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}/ancestry`, options);
18
23
  }
19
24
  async getLocationById(id, options) {
20
25
  return await this.requestOptional("GET", `/locations/${encodeURIComponent(id)}`, options);
21
26
  }
22
27
  async getEntities(request, options) {
23
- const {filter = [], fields = []} = request != null ? request : {};
28
+ const { filter = [], fields = [], offset, limit, after } = request != null ? request : {};
24
29
  const filterItems = [filter].flat();
25
30
  const params = [];
26
31
  for (const filterItem of filterItems) {
@@ -41,6 +46,15 @@ class CatalogClient {
41
46
  if (fields.length) {
42
47
  params.push(`fields=${fields.map(encodeURIComponent).join(",")}`);
43
48
  }
49
+ if (offset !== void 0) {
50
+ params.push(`offset=${offset}`);
51
+ }
52
+ if (limit !== void 0) {
53
+ params.push(`limit=${limit}`);
54
+ }
55
+ if (after !== void 0) {
56
+ params.push(`after=${encodeURIComponent(after)}`);
57
+ }
44
58
  const query = params.length ? `?${params.join("&")}` : "";
45
59
  const entities = await this.requestRequired("GET", `/entities${query}`, options);
46
60
  const refCompare = (a, b) => {
@@ -58,38 +72,38 @@ class CatalogClient {
58
72
  }
59
73
  return 0;
60
74
  };
61
- return {items: entities.sort(refCompare)};
75
+ return { items: entities.sort(refCompare) };
62
76
  }
63
77
  async getEntityByName(compoundName, options) {
64
- const {kind, namespace = "default", name} = compoundName;
78
+ const { kind, namespace = "default", name } = compoundName;
65
79
  return this.requestOptional("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}`, options);
66
80
  }
67
81
  async refreshEntity(entityRef, options) {
68
- const response = await fetch__default['default'](`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
82
+ const response = await this.fetchApi.fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
69
83
  headers: {
70
84
  "Content-Type": "application/json",
71
- ...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
85
+ ...(options == null ? void 0 : options.token) && { Authorization: `Bearer ${options == null ? void 0 : options.token}` }
72
86
  },
73
87
  method: "POST",
74
- body: JSON.stringify({entityRef})
88
+ body: JSON.stringify({ entityRef })
75
89
  });
76
90
  if (response.status !== 200) {
77
91
  throw new Error(await response.text());
78
92
  }
79
93
  }
80
- async addLocation({type = "url", target, dryRun, presence}, options) {
81
- const response = await fetch__default['default'](`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
94
+ async addLocation({ type = "url", target, dryRun, presence }, options) {
95
+ const response = await this.fetchApi.fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
82
96
  headers: {
83
97
  "Content-Type": "application/json",
84
- ...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
98
+ ...(options == null ? void 0 : options.token) && { Authorization: `Bearer ${options == null ? void 0 : options.token}` }
85
99
  },
86
100
  method: "POST",
87
- body: JSON.stringify({type, target, presence})
101
+ body: JSON.stringify({ type, target, presence })
88
102
  });
89
103
  if (response.status !== 201) {
90
104
  throw new Error(await response.text());
91
105
  }
92
- const {location, entities, exists} = await response.json();
106
+ const { location, entities, exists } = await response.json();
93
107
  if (!location) {
94
108
  throw new Error(`Location wasn't added: ${target}`);
95
109
  }
@@ -125,16 +139,16 @@ class CatalogClient {
125
139
  }
126
140
  async requestIgnored(method, path, options) {
127
141
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
128
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
129
- const response = await fetch__default['default'](url, {method, headers});
142
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
143
+ const response = await this.fetchApi.fetch(url, { method, headers });
130
144
  if (!response.ok) {
131
145
  throw await errors.ResponseError.fromResponse(response);
132
146
  }
133
147
  }
134
148
  async requestRequired(method, path, options) {
135
149
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
136
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
137
- const response = await fetch__default['default'](url, {method, headers});
150
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
151
+ const response = await this.fetchApi.fetch(url, { method, headers });
138
152
  if (!response.ok) {
139
153
  throw await errors.ResponseError.fromResponse(response);
140
154
  }
@@ -142,8 +156,8 @@ class CatalogClient {
142
156
  }
143
157
  async requestOptional(method, path, options) {
144
158
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
145
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
146
- const response = await fetch__default['default'](url, {method, headers});
159
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
160
+ const response = await this.fetchApi.fetch(url, { method, headers });
147
161
  if (!response.ok) {
148
162
  if (response.status === 404) {
149
163
  return void 0;
@@ -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 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":";;;;;;;;;;;;MAmBa,wBAAwB,OAAO;;oBCoBK;AAAA,EAG/C,YAAY,SAAyC;AACnD,SAAK,eAAe,QAAQ;AAAA;AAAA,QAGxB,gBACJ,IACA,SAC+B;AAC/B,WAAO,MAAM,KAAK,gBAChB,OACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAIE,YACJ,SACA,SACsC;AACtC,UAAM,CAAE,SAAS,IAAI,SAAS,MAAO,4BAAW;AAChD,UAAM,cAAc,CAAC,QAAQ;AAC7B,UAAM,SAAmB;AAMzB,eAAW,cAAc,aAAa;AACpC,YAAM,cAAwB;AAC9B,iBAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa;AACrD,mBAAW,KAAK,CAAC,OAAO,QAAQ;AAC9B,cAAI,MAAM,uBAAuB;AAC/B,wBAAY,KAAK,mBAAmB;AAAA,qBAC3B,OAAO,MAAM,UAAU;AAChC,wBAAY,KACV,GAAG,mBAAmB,QAAQ,mBAAmB;AAAA;AAAA;AAAA;AAMzD,UAAI,YAAY,QAAQ;AACtB,eAAO,KAAK,UAAU,YAAY,KAAK;AAAA;AAAA;AAI3C,QAAI,OAAO,QAAQ;AACjB,aAAO,KAAK,UAAU,OAAO,IAAI,oBAAoB,KAAK;AAAA;AAG5D,UAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,KAAK,SAAS;AACvD,UAAM,WAAqB,MAAM,KAAK,gBACpC,OACA,YAAY,SACZ;AAGF,UAAM,aAAa,CAAC,GAAW,MAAc;AAnGjD;AAqGM,UACE,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,UACX,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,QACX;AACA,eAAO;AAAA;AAGT,YAAM,OAAOA,gCAAmB;AAChC,YAAM,OAAOA,gCAAmB;AAChC,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,aAAO;AAAA;AAGT,WAAO,CAAE,OAAO,SAAS,KAAK;AAAA;AAAA,QAG1B,gBACJ,cACA,SAC6B;AAC7B,UAAM,CAAE,MAAM,YAAY,WAAW,QAAS;AAC9C,WAAO,KAAK,gBACV,OACA,qBAAqB,mBAAmB,SAAS,mBAC/C,cACG,mBAAmB,SACxB;AAAA;AAAA,QAIE,cAAc,WAAmB,SAAiC;AACtE,UAAM,WAAW,MAAMC,0BACrB,GAAG,MAAM,KAAK,aAAa,WAAW,sBACtC;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,CAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,CAAE;AAAA;AAI3B,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAAA;AAAA,QAI7B,YACJ,CAAE,OAAO,OAAO,QAAQ,QAAQ,WAChC,SAC8B;AAC9B,UAAM,WAAW,MAAMA,0BACrB,GAAG,MAAM,KAAK,aAAa,WAAW,uBACpC,SAAS,iBAAiB,MAE5B;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,CAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,CAAE,MAAM,QAAQ;AAAA;AAIzC,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAGjC,UAAM,CAAE,UAAU,UAAU,UAAW,MAAM,SAAS;AAEtD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,0BAA0B;AAAA;AAG5C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA,QAIE,0BACJ,QACA,SAC+B;AAlMnC;AAmMI,UAAM,mBACJ,aAAO,SAAS,gBAAhB,mBAA8BC;AAChC,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqBC,wCAA2B;AAAA;AAAA,QAGzD,oBACJ,QACA,SAC+B;AArNnC;AAsNI,UAAM,mBAAmB,aAAO,SAAS,gBAAhB,mBAA8BC;AACvD,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqBD,wCAA2B;AAAA;AAAA,QAGzD,mBACJ,IACA,SACe;AACf,UAAM,KAAK,eACT,UACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAIE,kBACJ,KACA,SACe;AACf,UAAM,KAAK,eACT,UACA,oBAAoB,mBAAmB,QACvC;AAAA;AAAA,QAQU,eACZ,QACA,MACA,SACe;AACf,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAMF,0BAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAMI,qBAAc,aAAa;AAAA;AAAA;AAAA,QAI7B,gBACZ,QACA,MACA,SACc;AACd,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAMJ,0BAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAMI,qBAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA,QAGV,gBACZ,QACA,MACA,SAC0B;AAC1B,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAMJ,0BAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA;AAET,YAAM,MAAMI,qBAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA;;MC5Rb,wCACX;;;;;;"}
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/**\n * A Symbol to define if a catalog filter exists or not.\n *\n * @public\n */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/**\n * A request type for retrieving catalog Entities.\n *\n * @public\n */\nexport type CatalogEntitiesRequest = {\n /**\n * If given, return only entities that match the given patterns.\n *\n * @remarks\n *\n * If multiple filter sets are given as an array, then there is effectively an\n * OR between each filter set.\n *\n * Within one filter set, there is effectively an AND between the various\n * keys.\n *\n * Within one key, if there are more than one value, then there is effectively\n * an OR between them.\n *\n * Example: For an input of\n *\n * ```\n * [\n * { kind: ['API', 'Component'] },\n * { 'metadata.name': 'a', 'metadata.namespace': 'b' }\n * ]\n * ```\n *\n * This effectively means\n *\n * ```\n * (kind = EITHER 'API' OR 'Component')\n * OR\n * (metadata.name = 'a' AND metadata.namespace = 'b' )\n * ```\n *\n * Each key is a dot separated path in each object.\n *\n * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`\n * (exported from this package), which means that you assert on the existence\n * of that key, no matter what its value is.\n */\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n /**\n * If given, return only the parts of each entity that match those dot\n * separated paths in each object.\n *\n * @remarks\n *\n * Example: For an input of `['kind', 'metadata.annotations']`, then response\n * objects will be shaped like\n *\n * ```\n * {\n * \"kind\": \"Component\",\n * \"metadata\": {\n * \"annotations\": {\n * \"foo\": \"bar\"\n * }\n * }\n * }\n * ```\n */\n fields?: string[] | undefined;\n /**\n * If given, skips over the first N items in the result set.\n */\n offset?: number;\n /**\n * If given, returns at most N items from the result set.\n */\n limit?: number;\n /**\n * If given, skips over all items before that cursor as returned by a previous\n * request.\n */\n after?: string;\n};\n\n/**\n * A request type for Catalog Entity Ancestor information.\n *\n * @public\n */\nexport type CatalogEntityAncestorsRequest = {\n entityRef: string;\n};\n\n/**\n * A response type for Catalog Entity Ancestor information.\n *\n * @public\n */\nexport type CatalogEntityAncestorsResponse = {\n root: EntityName;\n items: { entity: Entity; parents: EntityName[] }[];\n};\n\n/**\n * A response type for the result of a catalog operation in list form.\n *\n * @public\n */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/**\n * Options you can pass into a catalog request for additional information.\n *\n * @public\n */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/**\n * Public functions for interacting with the Catalog API.\n *\n * @public\n */\nexport interface CatalogApi {\n /**\n * Gets the Entities from the catalog based on your request and options.\n *\n * @param request - An object with your filters and fields.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogListResponse with items typed Catalog Model Entity.\n *\n */\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n /**\n * Gets the Entity ancestor information from the catalog based on your request and options.\n *\n * @param request - An object with your filters and fields.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogEntityAncestorsResponse.\n */\n getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse>;\n /**\n * Gets a single Entity from the catalog by Entity name.\n *\n * @param name - A complete Entity name, with the full kind-namespace-name triplet.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Entity}.\n */\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n /**\n * Removes a single Entity from the catalog by Entity UID.\n *\n * @param uid - A string of the Entity UID.\n * @param options - An object with your preferred options.\n *\n */\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n /**\n * Refreshes an Entity in the catalog.\n *\n * @param entityRef - A string in the form of 'Kind/default:foo'.\n * @param options - An object with your preferred options.\n *\n */\n refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n /**\n * Gets a Location object by ID from the catalog.\n *\n * @param id - A string in of the Location Id.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Gets origin location by Entity.\n *\n * @param entity - An {@link catalog-model#Entity}.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Gets Location by Entity.\n *\n * @param entity - An {@link catalog-model#Entity}.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Adds a Location.\n *\n * @param location - A request type for adding a Location to the catalog.\n * @param options - An object with your preferred options.\n *\n * @returns A AddLocationResponse.\n */\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n /**\n * Removes a Location by Id.\n *\n * @param id - A string in of the Location Id.\n * @param options - An object with your preferred options.\n *\n */\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/**\n * A request type for adding a Location to the catalog.\n *\n * @public\n */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/**\n * A response type for adding a Location to the catalog.\n *\n * @public\n */\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 parseEntityRef,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport crossFetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n CatalogEntityAncestorsRequest,\n CatalogEntityAncestorsResponse,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport { FetchApi } from './types/fetch';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage Catalog.\n *\n * @public\n * */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi || { fetch: crossFetch };\n }\n\n /**\n * Gets the Ancestors of an Entity.\n *\n * @param request - A request type for retrieving Entity ancestors.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogEntityAncestorsResponse.\n *\n * @public\n */\n async getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse> {\n const { kind, namespace, name } = parseEntityRef(request.entityRef);\n return await this.requestRequired(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}/ancestry`,\n options,\n );\n }\n\n /**\n * Gets a Location by Id.\n *\n * @param id - A string containing the Id.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Gets a set of Entities.\n *\n * @param request - A request type for retrieving an Entity.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogListResponse.\n *\n * @public\n */\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [], offset, limit, after } = 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 if (offset !== undefined) {\n params.push(`offset=${offset}`);\n }\n if (limit !== undefined) {\n params.push(`limit=${limit}`);\n }\n if (after !== undefined) {\n params.push(`after=${encodeURIComponent(after)}`);\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 /**\n * Gets a given Entity based on a provided name.\n *\n * @param compoundName - A string containing the name.\n * @param options - An object with your preferred options.\n *\n * @returns An {@link catalog-model#Entity}.\n *\n * @public\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 /**\n * Refreshes an Entity.\n *\n * @param entityRef - A string containing the entityREf\n * @param options - An object with your preferred options.\n *\n * @public\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.fetchApi.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 /**\n * Adds a location.\n *\n * @param options - An object with your preferred options.\n * @param AddLocationRequest - A request object for adding locations.\n *\n * @returns An AddLocationResponse\n *\n * @public\n */\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await this.fetchApi.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 /**\n * Gets an origin Location By Entity.\n *\n * @param entity - An Entity\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Gets a Location by Entity.\n *\n * @param entity - An Entity\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Removes a location as identified by Id.\n *\n * @param id - A string containing the Id\n * @param options - An object with your preferred options.\n *\n * @public\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 /**\n * Removes an Entity as identified by Uid.\n *\n * @param uid - A string containing the Uid\n * @param options - An object with your preferred options.\n *\n * @public\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 this.fetchApi.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 this.fetchApi.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 this.fetchApi.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":["crossFetch","parseEntityRef","stringifyEntityRef","ORIGIN_LOCATION_ANNOTATION","stringifyLocationReference","LOCATION_ANNOTATION","ResponseError"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,40 +1,237 @@
1
- import { Entity, EntityName, Location } from '@backstage/catalog-model';
1
+ import { EntityName, Entity, Location } from '@backstage/catalog-model';
2
2
 
3
- /** @public */
3
+ /**
4
+ * A Symbol to define if a catalog filter exists or not.
5
+ *
6
+ * @public
7
+ */
4
8
  declare const CATALOG_FILTER_EXISTS: unique symbol;
5
- /** @public */
9
+ /**
10
+ * A request type for retrieving catalog Entities.
11
+ *
12
+ * @public
13
+ */
6
14
  declare type CatalogEntitiesRequest = {
15
+ /**
16
+ * If given, return only entities that match the given patterns.
17
+ *
18
+ * @remarks
19
+ *
20
+ * If multiple filter sets are given as an array, then there is effectively an
21
+ * OR between each filter set.
22
+ *
23
+ * Within one filter set, there is effectively an AND between the various
24
+ * keys.
25
+ *
26
+ * Within one key, if there are more than one value, then there is effectively
27
+ * an OR between them.
28
+ *
29
+ * Example: For an input of
30
+ *
31
+ * ```
32
+ * [
33
+ * { kind: ['API', 'Component'] },
34
+ * { 'metadata.name': 'a', 'metadata.namespace': 'b' }
35
+ * ]
36
+ * ```
37
+ *
38
+ * This effectively means
39
+ *
40
+ * ```
41
+ * (kind = EITHER 'API' OR 'Component')
42
+ * OR
43
+ * (metadata.name = 'a' AND metadata.namespace = 'b' )
44
+ * ```
45
+ *
46
+ * Each key is a dot separated path in each object.
47
+ *
48
+ * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`
49
+ * (exported from this package), which means that you assert on the existence
50
+ * of that key, no matter what its value is.
51
+ */
7
52
  filter?: Record<string, string | symbol | (string | symbol)[]>[] | Record<string, string | symbol | (string | symbol)[]> | undefined;
53
+ /**
54
+ * If given, return only the parts of each entity that match those dot
55
+ * separated paths in each object.
56
+ *
57
+ * @remarks
58
+ *
59
+ * Example: For an input of `['kind', 'metadata.annotations']`, then response
60
+ * objects will be shaped like
61
+ *
62
+ * ```
63
+ * {
64
+ * "kind": "Component",
65
+ * "metadata": {
66
+ * "annotations": {
67
+ * "foo": "bar"
68
+ * }
69
+ * }
70
+ * }
71
+ * ```
72
+ */
8
73
  fields?: string[] | undefined;
74
+ /**
75
+ * If given, skips over the first N items in the result set.
76
+ */
77
+ offset?: number;
78
+ /**
79
+ * If given, returns at most N items from the result set.
80
+ */
81
+ limit?: number;
82
+ /**
83
+ * If given, skips over all items before that cursor as returned by a previous
84
+ * request.
85
+ */
86
+ after?: string;
87
+ };
88
+ /**
89
+ * A request type for Catalog Entity Ancestor information.
90
+ *
91
+ * @public
92
+ */
93
+ declare type CatalogEntityAncestorsRequest = {
94
+ entityRef: string;
95
+ };
96
+ /**
97
+ * A response type for Catalog Entity Ancestor information.
98
+ *
99
+ * @public
100
+ */
101
+ declare type CatalogEntityAncestorsResponse = {
102
+ root: EntityName;
103
+ items: {
104
+ entity: Entity;
105
+ parents: EntityName[];
106
+ }[];
9
107
  };
10
- /** @public */
108
+ /**
109
+ * A response type for the result of a catalog operation in list form.
110
+ *
111
+ * @public
112
+ */
11
113
  declare type CatalogListResponse<T> = {
12
114
  items: T[];
13
115
  };
14
- /** @public */
116
+ /**
117
+ * Options you can pass into a catalog request for additional information.
118
+ *
119
+ * @public
120
+ */
15
121
  declare type CatalogRequestOptions = {
16
122
  token?: string;
17
123
  };
18
- /** @public */
124
+ /**
125
+ * Public functions for interacting with the Catalog API.
126
+ *
127
+ * @public
128
+ */
19
129
  interface CatalogApi {
130
+ /**
131
+ * Gets the Entities from the catalog based on your request and options.
132
+ *
133
+ * @param request - An object with your filters and fields.
134
+ * @param options - An object with your preferred options.
135
+ *
136
+ * @returns A CatalogListResponse with items typed Catalog Model Entity.
137
+ *
138
+ */
20
139
  getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>;
140
+ /**
141
+ * Gets the Entity ancestor information from the catalog based on your request and options.
142
+ *
143
+ * @param request - An object with your filters and fields.
144
+ * @param options - An object with your preferred options.
145
+ *
146
+ * @returns A CatalogEntityAncestorsResponse.
147
+ */
148
+ getEntityAncestors(request: CatalogEntityAncestorsRequest, options?: CatalogRequestOptions): Promise<CatalogEntityAncestorsResponse>;
149
+ /**
150
+ * Gets a single Entity from the catalog by Entity name.
151
+ *
152
+ * @param name - A complete Entity name, with the full kind-namespace-name triplet.
153
+ * @param options - An object with your preferred options.
154
+ *
155
+ * @returns A {@link catalog-model#Entity}.
156
+ */
21
157
  getEntityByName(name: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>;
158
+ /**
159
+ * Removes a single Entity from the catalog by Entity UID.
160
+ *
161
+ * @param uid - A string of the Entity UID.
162
+ * @param options - An object with your preferred options.
163
+ *
164
+ */
22
165
  removeEntityByUid(uid: string, options?: CatalogRequestOptions): Promise<void>;
166
+ /**
167
+ * Refreshes an Entity in the catalog.
168
+ *
169
+ * @param entityRef - A string in the form of 'Kind/default:foo'.
170
+ * @param options - An object with your preferred options.
171
+ *
172
+ */
23
173
  refreshEntity(entityRef: string, options?: CatalogRequestOptions): Promise<void>;
174
+ /**
175
+ * Gets a Location object by ID from the catalog.
176
+ *
177
+ * @param id - A string in of the Location Id.
178
+ * @param options - An object with your preferred options.
179
+ *
180
+ * @returns A {@link catalog-model#Location_2}.
181
+ */
24
182
  getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location | undefined>;
183
+ /**
184
+ * Gets origin location by Entity.
185
+ *
186
+ * @param entity - An {@link catalog-model#Entity}.
187
+ * @param options - An object with your preferred options.
188
+ *
189
+ * @returns A {@link catalog-model#Location_2}.
190
+ */
25
191
  getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
192
+ /**
193
+ * Gets Location by Entity.
194
+ *
195
+ * @param entity - An {@link catalog-model#Entity}.
196
+ * @param options - An object with your preferred options.
197
+ *
198
+ * @returns A {@link catalog-model#Location_2}.
199
+ */
26
200
  getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
201
+ /**
202
+ * Adds a Location.
203
+ *
204
+ * @param location - A request type for adding a Location to the catalog.
205
+ * @param options - An object with your preferred options.
206
+ *
207
+ * @returns A AddLocationResponse.
208
+ */
27
209
  addLocation(location: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>;
210
+ /**
211
+ * Removes a Location by Id.
212
+ *
213
+ * @param id - A string in of the Location Id.
214
+ * @param options - An object with your preferred options.
215
+ *
216
+ */
28
217
  removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>;
29
218
  }
30
- /** @public */
219
+ /**
220
+ * A request type for adding a Location to the catalog.
221
+ *
222
+ * @public
223
+ */
31
224
  declare type AddLocationRequest = {
32
225
  type?: string;
33
226
  target: string;
34
227
  dryRun?: boolean;
35
228
  presence?: 'optional' | 'required';
36
229
  };
37
- /** @public */
230
+ /**
231
+ * A response type for adding a Location to the catalog.
232
+ *
233
+ * @public
234
+ */
38
235
  declare type AddLocationResponse = {
39
236
  location: Location;
40
237
  entities: Entity[];
@@ -42,7 +239,7 @@ declare type AddLocationResponse = {
42
239
  };
43
240
 
44
241
  /**
45
- * This is a copy of the core DiscoveryApi, to avoid importing core.
242
+ * This is a copy of the DiscoveryApi, to avoid importing core-plugin-api.
46
243
  *
47
244
  * @public
48
245
  */
@@ -50,20 +247,130 @@ declare type DiscoveryApi = {
50
247
  getBaseUrl(pluginId: string): Promise<string>;
51
248
  };
52
249
 
53
- /** @public */
250
+ /**
251
+ * This is a copy of FetchApi, to avoid importing core-plugin-api.
252
+ *
253
+ * @public
254
+ */
255
+ declare type FetchApi = {
256
+ fetch: typeof fetch;
257
+ };
258
+
259
+ /**
260
+ * A frontend and backend compatible client for communicating with the Backstage Catalog.
261
+ *
262
+ * @public
263
+ * */
54
264
  declare class CatalogClient implements CatalogApi {
55
265
  private readonly discoveryApi;
266
+ private readonly fetchApi;
56
267
  constructor(options: {
57
268
  discoveryApi: DiscoveryApi;
269
+ fetchApi?: FetchApi;
58
270
  });
271
+ /**
272
+ * Gets the Ancestors of an Entity.
273
+ *
274
+ * @param request - A request type for retrieving Entity ancestors.
275
+ * @param options - An object with your preferred options.
276
+ *
277
+ * @returns A CatalogEntityAncestorsResponse.
278
+ *
279
+ * @public
280
+ */
281
+ getEntityAncestors(request: CatalogEntityAncestorsRequest, options?: CatalogRequestOptions): Promise<CatalogEntityAncestorsResponse>;
282
+ /**
283
+ * Gets a Location by Id.
284
+ *
285
+ * @param id - A string containing the Id.
286
+ * @param options - An object with your preferred options.
287
+ *
288
+ * @returns A {@link catalog-model#Location_2}.
289
+ *
290
+ * @public
291
+ */
59
292
  getLocationById(id: string, options?: CatalogRequestOptions): Promise<Location | undefined>;
293
+ /**
294
+ * Gets a set of Entities.
295
+ *
296
+ * @param request - A request type for retrieving an Entity.
297
+ * @param options - An object with your preferred options.
298
+ *
299
+ * @returns A CatalogListResponse.
300
+ *
301
+ * @public
302
+ */
60
303
  getEntities(request?: CatalogEntitiesRequest, options?: CatalogRequestOptions): Promise<CatalogListResponse<Entity>>;
304
+ /**
305
+ * Gets a given Entity based on a provided name.
306
+ *
307
+ * @param compoundName - A string containing the name.
308
+ * @param options - An object with your preferred options.
309
+ *
310
+ * @returns An {@link catalog-model#Entity}.
311
+ *
312
+ * @public
313
+ */
61
314
  getEntityByName(compoundName: EntityName, options?: CatalogRequestOptions): Promise<Entity | undefined>;
315
+ /**
316
+ * Refreshes an Entity.
317
+ *
318
+ * @param entityRef - A string containing the entityREf
319
+ * @param options - An object with your preferred options.
320
+ *
321
+ * @public
322
+ */
62
323
  refreshEntity(entityRef: string, options?: CatalogRequestOptions): Promise<void>;
324
+ /**
325
+ * Adds a location.
326
+ *
327
+ * @param options - An object with your preferred options.
328
+ * @param AddLocationRequest - A request object for adding locations.
329
+ *
330
+ * @returns An AddLocationResponse
331
+ *
332
+ * @public
333
+ */
63
334
  addLocation({ type, target, dryRun, presence }: AddLocationRequest, options?: CatalogRequestOptions): Promise<AddLocationResponse>;
335
+ /**
336
+ * Gets an origin Location By Entity.
337
+ *
338
+ * @param entity - An Entity
339
+ * @param options - An object with your preferred options.
340
+ *
341
+ * @returns A {@link catalog-model#Location_2}.
342
+ *
343
+ * @public
344
+ */
64
345
  getOriginLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
346
+ /**
347
+ * Gets a Location by Entity.
348
+ *
349
+ * @param entity - An Entity
350
+ * @param options - An object with your preferred options.
351
+ *
352
+ * @returns A {@link catalog-model#Location_2}.
353
+ *
354
+ * @public
355
+ */
65
356
  getLocationByEntity(entity: Entity, options?: CatalogRequestOptions): Promise<Location | undefined>;
357
+ /**
358
+ * Removes a location as identified by Id.
359
+ *
360
+ * @param id - A string containing the Id
361
+ * @param options - An object with your preferred options.
362
+ *
363
+ * @public
364
+ */
66
365
  removeLocationById(id: string, options?: CatalogRequestOptions): Promise<void>;
366
+ /**
367
+ * Removes an Entity as identified by Uid.
368
+ *
369
+ * @param uid - A string containing the Uid
370
+ * @param options - An object with your preferred options.
371
+ *
372
+ * @public
373
+ */
67
374
  removeEntityByUid(uid: string, options?: CatalogRequestOptions): Promise<void>;
68
375
  private requestIgnored;
69
376
  private requestRequired;
@@ -78,4 +385,4 @@ declare class CatalogClient implements CatalogApi {
78
385
  */
79
386
  declare const ENTITY_STATUS_CATALOG_PROCESSING_TYPE = "backstage.io/catalog-processing";
80
387
 
81
- export { AddLocationRequest, AddLocationResponse, CATALOG_FILTER_EXISTS, CatalogApi, CatalogClient, CatalogEntitiesRequest, CatalogListResponse, CatalogRequestOptions, DiscoveryApi, ENTITY_STATUS_CATALOG_PROCESSING_TYPE };
388
+ export { AddLocationRequest, AddLocationResponse, CATALOG_FILTER_EXISTS, CatalogApi, CatalogClient, CatalogEntitiesRequest, CatalogEntityAncestorsRequest, CatalogEntityAncestorsResponse, CatalogListResponse, CatalogRequestOptions, DiscoveryApi, ENTITY_STATUS_CATALOG_PROCESSING_TYPE, FetchApi };
package/dist/index.esm.js CHANGED
@@ -1,18 +1,23 @@
1
- import { ORIGIN_LOCATION_ANNOTATION, stringifyLocationReference, LOCATION_ANNOTATION, stringifyEntityRef } from '@backstage/catalog-model';
1
+ import { parseEntityRef, ORIGIN_LOCATION_ANNOTATION, stringifyLocationReference, LOCATION_ANNOTATION, stringifyEntityRef } from '@backstage/catalog-model';
2
2
  import { ResponseError } from '@backstage/errors';
3
- import fetch from 'cross-fetch';
3
+ import crossFetch from 'cross-fetch';
4
4
 
5
5
  const CATALOG_FILTER_EXISTS = Symbol("CATALOG_FILTER_EXISTS");
6
6
 
7
7
  class CatalogClient {
8
8
  constructor(options) {
9
9
  this.discoveryApi = options.discoveryApi;
10
+ this.fetchApi = options.fetchApi || { fetch: crossFetch };
11
+ }
12
+ async getEntityAncestors(request, options) {
13
+ const { kind, namespace, name } = parseEntityRef(request.entityRef);
14
+ return await this.requestRequired("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}/ancestry`, options);
10
15
  }
11
16
  async getLocationById(id, options) {
12
17
  return await this.requestOptional("GET", `/locations/${encodeURIComponent(id)}`, options);
13
18
  }
14
19
  async getEntities(request, options) {
15
- const {filter = [], fields = []} = request != null ? request : {};
20
+ const { filter = [], fields = [], offset, limit, after } = request != null ? request : {};
16
21
  const filterItems = [filter].flat();
17
22
  const params = [];
18
23
  for (const filterItem of filterItems) {
@@ -33,6 +38,15 @@ class CatalogClient {
33
38
  if (fields.length) {
34
39
  params.push(`fields=${fields.map(encodeURIComponent).join(",")}`);
35
40
  }
41
+ if (offset !== void 0) {
42
+ params.push(`offset=${offset}`);
43
+ }
44
+ if (limit !== void 0) {
45
+ params.push(`limit=${limit}`);
46
+ }
47
+ if (after !== void 0) {
48
+ params.push(`after=${encodeURIComponent(after)}`);
49
+ }
36
50
  const query = params.length ? `?${params.join("&")}` : "";
37
51
  const entities = await this.requestRequired("GET", `/entities${query}`, options);
38
52
  const refCompare = (a, b) => {
@@ -50,38 +64,38 @@ class CatalogClient {
50
64
  }
51
65
  return 0;
52
66
  };
53
- return {items: entities.sort(refCompare)};
67
+ return { items: entities.sort(refCompare) };
54
68
  }
55
69
  async getEntityByName(compoundName, options) {
56
- const {kind, namespace = "default", name} = compoundName;
70
+ const { kind, namespace = "default", name } = compoundName;
57
71
  return this.requestOptional("GET", `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}`, options);
58
72
  }
59
73
  async refreshEntity(entityRef, options) {
60
- const response = await fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
74
+ const response = await this.fetchApi.fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/refresh`, {
61
75
  headers: {
62
76
  "Content-Type": "application/json",
63
- ...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
77
+ ...(options == null ? void 0 : options.token) && { Authorization: `Bearer ${options == null ? void 0 : options.token}` }
64
78
  },
65
79
  method: "POST",
66
- body: JSON.stringify({entityRef})
80
+ body: JSON.stringify({ entityRef })
67
81
  });
68
82
  if (response.status !== 200) {
69
83
  throw new Error(await response.text());
70
84
  }
71
85
  }
72
- async addLocation({type = "url", target, dryRun, presence}, options) {
73
- const response = await fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
86
+ async addLocation({ type = "url", target, dryRun, presence }, options) {
87
+ const response = await this.fetchApi.fetch(`${await this.discoveryApi.getBaseUrl("catalog")}/locations${dryRun ? "?dryRun=true" : ""}`, {
74
88
  headers: {
75
89
  "Content-Type": "application/json",
76
- ...(options == null ? void 0 : options.token) && {Authorization: `Bearer ${options == null ? void 0 : options.token}`}
90
+ ...(options == null ? void 0 : options.token) && { Authorization: `Bearer ${options == null ? void 0 : options.token}` }
77
91
  },
78
92
  method: "POST",
79
- body: JSON.stringify({type, target, presence})
93
+ body: JSON.stringify({ type, target, presence })
80
94
  });
81
95
  if (response.status !== 201) {
82
96
  throw new Error(await response.text());
83
97
  }
84
- const {location, entities, exists} = await response.json();
98
+ const { location, entities, exists } = await response.json();
85
99
  if (!location) {
86
100
  throw new Error(`Location wasn't added: ${target}`);
87
101
  }
@@ -117,16 +131,16 @@ class CatalogClient {
117
131
  }
118
132
  async requestIgnored(method, path, options) {
119
133
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
120
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
121
- const response = await fetch(url, {method, headers});
134
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
135
+ const response = await this.fetchApi.fetch(url, { method, headers });
122
136
  if (!response.ok) {
123
137
  throw await ResponseError.fromResponse(response);
124
138
  }
125
139
  }
126
140
  async requestRequired(method, path, options) {
127
141
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
128
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
129
- const response = await fetch(url, {method, headers});
142
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
143
+ const response = await this.fetchApi.fetch(url, { method, headers });
130
144
  if (!response.ok) {
131
145
  throw await ResponseError.fromResponse(response);
132
146
  }
@@ -134,8 +148,8 @@ class CatalogClient {
134
148
  }
135
149
  async requestOptional(method, path, options) {
136
150
  const url = `${await this.discoveryApi.getBaseUrl("catalog")}${path}`;
137
- const headers = (options == null ? void 0 : options.token) ? {Authorization: `Bearer ${options.token}`} : {};
138
- const response = await fetch(url, {method, headers});
151
+ const headers = (options == null ? void 0 : options.token) ? { Authorization: `Bearer ${options.token}` } : {};
152
+ const response = await this.fetchApi.fetch(url, { method, headers });
139
153
  if (!response.ok) {
140
154
  if (response.status === 404) {
141
155
  return void 0;
@@ -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 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":";;;;MAmBa,wBAAwB,OAAO;;oBCoBK;AAAA,EAG/C,YAAY,SAAyC;AACnD,SAAK,eAAe,QAAQ;AAAA;AAAA,QAGxB,gBACJ,IACA,SAC+B;AAC/B,WAAO,MAAM,KAAK,gBAChB,OACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAIE,YACJ,SACA,SACsC;AACtC,UAAM,CAAE,SAAS,IAAI,SAAS,MAAO,4BAAW;AAChD,UAAM,cAAc,CAAC,QAAQ;AAC7B,UAAM,SAAmB;AAMzB,eAAW,cAAc,aAAa;AACpC,YAAM,cAAwB;AAC9B,iBAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa;AACrD,mBAAW,KAAK,CAAC,OAAO,QAAQ;AAC9B,cAAI,MAAM,uBAAuB;AAC/B,wBAAY,KAAK,mBAAmB;AAAA,qBAC3B,OAAO,MAAM,UAAU;AAChC,wBAAY,KACV,GAAG,mBAAmB,QAAQ,mBAAmB;AAAA;AAAA;AAAA;AAMzD,UAAI,YAAY,QAAQ;AACtB,eAAO,KAAK,UAAU,YAAY,KAAK;AAAA;AAAA;AAI3C,QAAI,OAAO,QAAQ;AACjB,aAAO,KAAK,UAAU,OAAO,IAAI,oBAAoB,KAAK;AAAA;AAG5D,UAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,KAAK,SAAS;AACvD,UAAM,WAAqB,MAAM,KAAK,gBACpC,OACA,YAAY,SACZ;AAGF,UAAM,aAAa,CAAC,GAAW,MAAc;AAnGjD;AAqGM,UACE,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,UACX,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,QACX;AACA,eAAO;AAAA;AAGT,YAAM,OAAO,mBAAmB;AAChC,YAAM,OAAO,mBAAmB;AAChC,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,aAAO;AAAA;AAGT,WAAO,CAAE,OAAO,SAAS,KAAK;AAAA;AAAA,QAG1B,gBACJ,cACA,SAC6B;AAC7B,UAAM,CAAE,MAAM,YAAY,WAAW,QAAS;AAC9C,WAAO,KAAK,gBACV,OACA,qBAAqB,mBAAmB,SAAS,mBAC/C,cACG,mBAAmB,SACxB;AAAA;AAAA,QAIE,cAAc,WAAmB,SAAiC;AACtE,UAAM,WAAW,MAAM,MACrB,GAAG,MAAM,KAAK,aAAa,WAAW,sBACtC;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,CAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,CAAE;AAAA;AAI3B,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAAA;AAAA,QAI7B,YACJ,CAAE,OAAO,OAAO,QAAQ,QAAQ,WAChC,SAC8B;AAC9B,UAAM,WAAW,MAAM,MACrB,GAAG,MAAM,KAAK,aAAa,WAAW,uBACpC,SAAS,iBAAiB,MAE5B;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,CAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,CAAE,MAAM,QAAQ;AAAA;AAIzC,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAGjC,UAAM,CAAE,UAAU,UAAU,UAAW,MAAM,SAAS;AAEtD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,0BAA0B;AAAA;AAG5C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA,QAIE,0BACJ,QACA,SAC+B;AAlMnC;AAmMI,UAAM,mBACJ,aAAO,SAAS,gBAAhB,mBAA8B;AAChC,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqB,2BAA2B;AAAA;AAAA,QAGzD,oBACJ,QACA,SAC+B;AArNnC;AAsNI,UAAM,mBAAmB,aAAO,SAAS,gBAAhB,mBAA8B;AACvD,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqB,2BAA2B;AAAA;AAAA,QAGzD,mBACJ,IACA,SACe;AACf,UAAM,KAAK,eACT,UACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAIE,kBACJ,KACA,SACe;AACf,UAAM,KAAK,eACT,UACA,oBAAoB,mBAAmB,QACvC;AAAA;AAAA,QAQU,eACZ,QACA,MACA,SACe;AACf,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAM,MAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAAA;AAAA,QAI7B,gBACZ,QACA,MACA,SACc;AACd,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAM,MAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA,QAGV,gBACZ,QACA,MACA,SAC0B;AAC1B,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,CAAE,eAAe,UAAU,QAAQ,WACnC;AACJ,UAAM,WAAW,MAAM,MAAM,KAAK,CAAE,QAAQ;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA;AAET,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA;;MC5Rb,wCACX;;;;"}
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/**\n * A Symbol to define if a catalog filter exists or not.\n *\n * @public\n */\nexport const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');\n\n/**\n * A request type for retrieving catalog Entities.\n *\n * @public\n */\nexport type CatalogEntitiesRequest = {\n /**\n * If given, return only entities that match the given patterns.\n *\n * @remarks\n *\n * If multiple filter sets are given as an array, then there is effectively an\n * OR between each filter set.\n *\n * Within one filter set, there is effectively an AND between the various\n * keys.\n *\n * Within one key, if there are more than one value, then there is effectively\n * an OR between them.\n *\n * Example: For an input of\n *\n * ```\n * [\n * { kind: ['API', 'Component'] },\n * { 'metadata.name': 'a', 'metadata.namespace': 'b' }\n * ]\n * ```\n *\n * This effectively means\n *\n * ```\n * (kind = EITHER 'API' OR 'Component')\n * OR\n * (metadata.name = 'a' AND metadata.namespace = 'b' )\n * ```\n *\n * Each key is a dot separated path in each object.\n *\n * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`\n * (exported from this package), which means that you assert on the existence\n * of that key, no matter what its value is.\n */\n filter?:\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>\n | undefined;\n /**\n * If given, return only the parts of each entity that match those dot\n * separated paths in each object.\n *\n * @remarks\n *\n * Example: For an input of `['kind', 'metadata.annotations']`, then response\n * objects will be shaped like\n *\n * ```\n * {\n * \"kind\": \"Component\",\n * \"metadata\": {\n * \"annotations\": {\n * \"foo\": \"bar\"\n * }\n * }\n * }\n * ```\n */\n fields?: string[] | undefined;\n /**\n * If given, skips over the first N items in the result set.\n */\n offset?: number;\n /**\n * If given, returns at most N items from the result set.\n */\n limit?: number;\n /**\n * If given, skips over all items before that cursor as returned by a previous\n * request.\n */\n after?: string;\n};\n\n/**\n * A request type for Catalog Entity Ancestor information.\n *\n * @public\n */\nexport type CatalogEntityAncestorsRequest = {\n entityRef: string;\n};\n\n/**\n * A response type for Catalog Entity Ancestor information.\n *\n * @public\n */\nexport type CatalogEntityAncestorsResponse = {\n root: EntityName;\n items: { entity: Entity; parents: EntityName[] }[];\n};\n\n/**\n * A response type for the result of a catalog operation in list form.\n *\n * @public\n */\nexport type CatalogListResponse<T> = {\n items: T[];\n};\n\n/**\n * Options you can pass into a catalog request for additional information.\n *\n * @public\n */\nexport type CatalogRequestOptions = {\n token?: string;\n};\n\n/**\n * Public functions for interacting with the Catalog API.\n *\n * @public\n */\nexport interface CatalogApi {\n /**\n * Gets the Entities from the catalog based on your request and options.\n *\n * @param request - An object with your filters and fields.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogListResponse with items typed Catalog Model Entity.\n *\n */\n getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>>;\n /**\n * Gets the Entity ancestor information from the catalog based on your request and options.\n *\n * @param request - An object with your filters and fields.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogEntityAncestorsResponse.\n */\n getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse>;\n /**\n * Gets a single Entity from the catalog by Entity name.\n *\n * @param name - A complete Entity name, with the full kind-namespace-name triplet.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Entity}.\n */\n getEntityByName(\n name: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n /**\n * Removes a single Entity from the catalog by Entity UID.\n *\n * @param uid - A string of the Entity UID.\n * @param options - An object with your preferred options.\n *\n */\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n /**\n * Refreshes an Entity in the catalog.\n *\n * @param entityRef - A string in the form of 'Kind/default:foo'.\n * @param options - An object with your preferred options.\n *\n */\n refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n // Locations\n /**\n * Gets a Location object by ID from the catalog.\n *\n * @param id - A string in of the Location Id.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Gets origin location by Entity.\n *\n * @param entity - An {@link catalog-model#Entity}.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Gets Location by Entity.\n *\n * @param entity - An {@link catalog-model#Entity}.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n */\n getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n /**\n * Adds a Location.\n *\n * @param location - A request type for adding a Location to the catalog.\n * @param options - An object with your preferred options.\n *\n * @returns A AddLocationResponse.\n */\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n /**\n * Removes a Location by Id.\n *\n * @param id - A string in of the Location Id.\n * @param options - An object with your preferred options.\n *\n */\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n}\n\n/**\n * A request type for adding a Location to the catalog.\n *\n * @public\n */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n dryRun?: boolean;\n presence?: 'optional' | 'required';\n};\n\n/**\n * A response type for adding a Location to the catalog.\n *\n * @public\n */\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 parseEntityRef,\n stringifyEntityRef,\n stringifyLocationReference,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport crossFetch from 'cross-fetch';\nimport {\n CATALOG_FILTER_EXISTS,\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n CatalogEntityAncestorsRequest,\n CatalogEntityAncestorsResponse,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport { FetchApi } from './types/fetch';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage Catalog.\n *\n * @public\n * */\nexport class CatalogClient implements CatalogApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi || { fetch: crossFetch };\n }\n\n /**\n * Gets the Ancestors of an Entity.\n *\n * @param request - A request type for retrieving Entity ancestors.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogEntityAncestorsResponse.\n *\n * @public\n */\n async getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse> {\n const { kind, namespace, name } = parseEntityRef(request.entityRef);\n return await this.requestRequired(\n 'GET',\n `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(\n namespace,\n )}/${encodeURIComponent(name)}/ancestry`,\n options,\n );\n }\n\n /**\n * Gets a Location by Id.\n *\n * @param id - A string containing the Id.\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Gets a set of Entities.\n *\n * @param request - A request type for retrieving an Entity.\n * @param options - An object with your preferred options.\n *\n * @returns A CatalogListResponse.\n *\n * @public\n */\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n const { filter = [], fields = [], offset, limit, after } = 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 if (offset !== undefined) {\n params.push(`offset=${offset}`);\n }\n if (limit !== undefined) {\n params.push(`limit=${limit}`);\n }\n if (after !== undefined) {\n params.push(`after=${encodeURIComponent(after)}`);\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 /**\n * Gets a given Entity based on a provided name.\n *\n * @param compoundName - A string containing the name.\n * @param options - An object with your preferred options.\n *\n * @returns An {@link catalog-model#Entity}.\n *\n * @public\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 /**\n * Refreshes an Entity.\n *\n * @param entityRef - A string containing the entityREf\n * @param options - An object with your preferred options.\n *\n * @public\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.fetchApi.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 /**\n * Adds a location.\n *\n * @param options - An object with your preferred options.\n * @param AddLocationRequest - A request object for adding locations.\n *\n * @returns An AddLocationResponse\n *\n * @public\n */\n async addLocation(\n { type = 'url', target, dryRun, presence }: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const response = await this.fetchApi.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 /**\n * Gets an origin Location By Entity.\n *\n * @param entity - An Entity\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Gets a Location by Entity.\n *\n * @param entity - An Entity\n * @param options - An object with your preferred options.\n *\n * @returns A {@link catalog-model#Location_2}.\n *\n * @public\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 /**\n * Removes a location as identified by Id.\n *\n * @param id - A string containing the Id\n * @param options - An object with your preferred options.\n *\n * @public\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 /**\n * Removes an Entity as identified by Uid.\n *\n * @param uid - A string containing the Uid\n * @param options - An object with your preferred options.\n *\n * @public\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 this.fetchApi.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 this.fetchApi.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 this.fetchApi.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":";;;;MAuBa,wBAAwB,OAAO;;oBCwBK;AAAA,EAI/C,YAAY,SAA8D;AACxE,SAAK,eAAe,QAAQ;AAC5B,SAAK,WAAW,QAAQ,YAAY,EAAE,OAAO;AAAA;AAAA,QAazC,mBACJ,SACA,SACyC;AACzC,UAAM,EAAE,MAAM,WAAW,SAAS,eAAe,QAAQ;AACzD,WAAO,MAAM,KAAK,gBAChB,OACA,qBAAqB,mBAAmB,SAAS,mBAC/C,cACG,mBAAmB,kBACxB;AAAA;AAAA,QAcE,gBACJ,IACA,SAC+B;AAC/B,WAAO,MAAM,KAAK,gBAChB,OACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAcE,YACJ,SACA,SACsC;AACtC,UAAM,EAAE,SAAS,IAAI,SAAS,IAAI,QAAQ,OAAO,UAAU,4BAAW;AACtE,UAAM,cAAc,CAAC,QAAQ;AAC7B,UAAM,SAAmB;AAMzB,eAAW,cAAc,aAAa;AACpC,YAAM,cAAwB;AAC9B,iBAAW,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa;AACrD,mBAAW,KAAK,CAAC,OAAO,QAAQ;AAC9B,cAAI,MAAM,uBAAuB;AAC/B,wBAAY,KAAK,mBAAmB;AAAA,qBAC3B,OAAO,MAAM,UAAU;AAChC,wBAAY,KACV,GAAG,mBAAmB,QAAQ,mBAAmB;AAAA;AAAA;AAAA;AAMzD,UAAI,YAAY,QAAQ;AACtB,eAAO,KAAK,UAAU,YAAY,KAAK;AAAA;AAAA;AAI3C,QAAI,OAAO,QAAQ;AACjB,aAAO,KAAK,UAAU,OAAO,IAAI,oBAAoB,KAAK;AAAA;AAG5D,QAAI,WAAW,QAAW;AACxB,aAAO,KAAK,UAAU;AAAA;AAExB,QAAI,UAAU,QAAW;AACvB,aAAO,KAAK,SAAS;AAAA;AAEvB,QAAI,UAAU,QAAW;AACvB,aAAO,KAAK,SAAS,mBAAmB;AAAA;AAG1C,UAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,KAAK,SAAS;AACvD,UAAM,WAAqB,MAAM,KAAK,gBACpC,OACA,YAAY,SACZ;AAGF,UAAM,aAAa,CAAC,GAAW,MAAc;AAnKjD;AAqKM,UACE,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,UACX,SAAE,aAAF,mBAAY,UAAS,UACrB,EAAE,SAAS,QACX;AACA,eAAO;AAAA;AAGT,YAAM,OAAO,mBAAmB;AAChC,YAAM,OAAO,mBAAmB;AAChC,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,UAAI,OAAO,MAAM;AACf,eAAO;AAAA;AAET,aAAO;AAAA;AAGT,WAAO,EAAE,OAAO,SAAS,KAAK;AAAA;AAAA,QAa1B,gBACJ,cACA,SAC6B;AAC7B,UAAM,EAAE,MAAM,YAAY,WAAW,SAAS;AAC9C,WAAO,KAAK,gBACV,OACA,qBAAqB,mBAAmB,SAAS,mBAC/C,cACG,mBAAmB,SACxB;AAAA;AAAA,QAYE,cAAc,WAAmB,SAAiC;AACtE,UAAM,WAAW,MAAM,KAAK,SAAS,MACnC,GAAG,MAAM,KAAK,aAAa,WAAW,sBACtC;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,EAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE;AAAA;AAI3B,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAAA;AAAA,QAc7B,YACJ,EAAE,OAAO,OAAO,QAAQ,QAAQ,YAChC,SAC8B;AAC9B,UAAM,WAAW,MAAM,KAAK,SAAS,MACnC,GAAG,MAAM,KAAK,aAAa,WAAW,uBACpC,SAAS,iBAAiB,MAE5B;AAAA,MACE,SAAS;AAAA,QACP,gBAAgB;AAAA,WACZ,oCAAS,UAAS,EAAE,eAAe,UAAU,mCAAS;AAAA;AAAA,MAE5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,MAAM,QAAQ;AAAA;AAIzC,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,MAAM,MAAM,SAAS;AAAA;AAGjC,UAAM,EAAE,UAAU,UAAU,WAAW,MAAM,SAAS;AAEtD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,0BAA0B;AAAA;AAG5C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA,QAcE,0BACJ,QACA,SAC+B;AAxSnC;AAySI,UAAM,mBACJ,aAAO,SAAS,gBAAhB,mBAA8B;AAChC,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqB,2BAA2B;AAAA;AAAA,QAazD,oBACJ,QACA,SAC+B;AArUnC;AAsUI,UAAM,mBAAmB,aAAO,SAAS,gBAAhB,mBAA8B;AACvD,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA;AAET,UAAM,MAA4B,MAAM,KAAK,gBAC3C,OACA,cACA;AAEF,WAAO,IACJ,IAAI,OAAK,EAAE,MACX,KAAK,OAAK,qBAAqB,2BAA2B;AAAA;AAAA,QAWzD,mBACJ,IACA,SACe;AACf,UAAM,KAAK,eACT,UACA,cAAc,mBAAmB,OACjC;AAAA;AAAA,QAYE,kBACJ,KACA,SACe;AACf,UAAM,KAAK,eACT,UACA,oBAAoB,mBAAmB,QACvC;AAAA;AAAA,QAQU,eACZ,QACA,MACA,SACe;AACf,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,EAAE,eAAe,UAAU,QAAQ,YACnC;AACJ,UAAM,WAAW,MAAM,KAAK,SAAS,MAAM,KAAK,EAAE,QAAQ;AAE1D,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAAA;AAAA,QAI7B,gBACZ,QACA,MACA,SACc;AACd,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,EAAE,eAAe,UAAU,QAAQ,YACnC;AACJ,UAAM,WAAW,MAAM,KAAK,SAAS,MAAM,KAAK,EAAE,QAAQ;AAE1D,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA,QAGV,gBACZ,QACA,MACA,SAC0B;AAC1B,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WAAW,aAAa;AAC/D,UAAM,UAAkC,oCAAS,SAC7C,EAAE,eAAe,UAAU,QAAQ,YACnC;AACJ,UAAM,WAAW,MAAM,KAAK,SAAS,MAAM,KAAK,EAAE,QAAQ;AAE1D,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA;AAET,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,WAAO,MAAM,SAAS;AAAA;AAAA;;MC5Zb,wCACX;;;;"}
package/package.json CHANGED
@@ -1,7 +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
+ "version": "0.5.3",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -30,19 +30,18 @@
30
30
  "clean": "backstage-cli clean"
31
31
  },
32
32
  "dependencies": {
33
- "@backstage/catalog-model": "^0.9.3",
34
- "@backstage/config": "^0.1.10",
35
- "@backstage/errors": "^0.1.2",
33
+ "@backstage/catalog-model": "^0.9.7",
34
+ "@backstage/errors": "^0.1.4",
36
35
  "cross-fetch": "^3.0.6"
37
36
  },
38
37
  "devDependencies": {
39
- "@backstage/cli": "^0.7.13",
38
+ "@backstage/cli": "^0.10.3",
40
39
  "@types/jest": "^26.0.7",
41
- "msw": "^0.29.0"
40
+ "msw": "^0.35.0"
42
41
  },
43
42
  "files": [
44
43
  "dist"
45
44
  ],
46
- "gitHead": "2fd2dbc5d2fad9da5f623126920958970aea469b",
45
+ "gitHead": "b315430f9dfcfa19ab0dd90f5b4ac6904938fba7",
47
46
  "module": "dist/index.esm.js"
48
47
  }