@backstage-community/plugin-3scale-backend 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## @janus-idp/backstage-plugin-3scale-backend [1.8.0](https://github.com/janus-idp/backstage-plugins/compare/@janus-idp/backstage-plugin-3scale-backend@1.7.1...@janus-idp/backstage-plugin-3scale-backend@1.8.0) (2024-07-25)
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - d8c8238: Merge API docs for the same service.
8
+
3
9
  ## 2.0.0
4
10
 
5
11
  ### Major Changes
package/dist/index.cjs.js CHANGED
@@ -6,6 +6,14 @@ var backendPluginApi = require('@backstage/backend-plugin-api');
6
6
  var alpha = require('@backstage/plugin-catalog-node/alpha');
7
7
  var catalogModel = require('@backstage/catalog-model');
8
8
  var errors = require('@backstage/errors');
9
+ var openapiMerge = require('openapi-merge');
10
+ var Swagger2OpenAPI = require('swagger2openapi');
11
+ var SwaggerConverter = require('swagger-converter');
12
+
13
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
+
15
+ var Swagger2OpenAPI__default = /*#__PURE__*/_interopDefaultCompat(Swagger2OpenAPI);
16
+ var SwaggerConverter__default = /*#__PURE__*/_interopDefaultCompat(SwaggerConverter);
9
17
 
10
18
  function listServices(baseUrl, access_token, page, size) {
11
19
  return fetch(
@@ -69,6 +77,75 @@ function readThreeScaleApiEntityConfig(id, config) {
69
77
  };
70
78
  }
71
79
 
80
+ function isNonEmptyArray(arr) {
81
+ return arr.length > 0;
82
+ }
83
+
84
+ function isSwagger1_2(apiDoc) {
85
+ return apiDoc.swaggerVersion && apiDoc.swaggerVersion === "1.2";
86
+ }
87
+ function isSwagger2_0(apiDoc) {
88
+ return apiDoc.swagger && apiDoc.swagger === "2.0";
89
+ }
90
+ function isOpenAPI3_0(apiDoc) {
91
+ return apiDoc.openapi;
92
+ }
93
+ class OpenAPIMergerAndConverter {
94
+ async mergeOpenAPI3Docs(docs) {
95
+ const mergeInput = docs.map((doc) => {
96
+ return { oas: doc };
97
+ });
98
+ const result = await openapiMerge.merge(mergeInput);
99
+ if (openapiMerge.isErrorResult(result)) {
100
+ throw new Error(result.message);
101
+ }
102
+ return result.output;
103
+ }
104
+ // Convert api doc to format openAPI 3. Do nothing with doc if it has format openAPI 3.0.
105
+ // 3scale supports API docs in formats:
106
+ // - swagger 1.2
107
+ // - swagger 2.0
108
+ // - openAPI 3.0
109
+ async convertAPIDocToOpenAPI3(apiDoc) {
110
+ if (isOpenAPI3_0(apiDoc)) {
111
+ return apiDoc;
112
+ }
113
+ if (isSwagger1_2(apiDoc)) {
114
+ const swagger2_0Doc = await this.convertSwagger1_2To2_0(apiDoc);
115
+ return await this.convertSwagger2_0ToOpenAPI3_0(swagger2_0Doc);
116
+ }
117
+ if (isSwagger2_0(apiDoc)) {
118
+ return await this.convertSwagger2_0ToOpenAPI3_0(apiDoc);
119
+ }
120
+ throw new Error(
121
+ `Unsupported API document. Plugin supports Swagger 1.2, 2.0, 3.0(Open API 3.0)`
122
+ );
123
+ }
124
+ async convertSwagger1_2To2_0(swaggerDoc) {
125
+ try {
126
+ const result = SwaggerConverter__default.default.convert(swaggerDoc, {});
127
+ return result;
128
+ } catch (error) {
129
+ console.error("Error converting Swagger 1.2 to Swagger 2.0:", error);
130
+ throw error;
131
+ }
132
+ }
133
+ async convertSwagger2_0ToOpenAPI3_0(swaggerDoc) {
134
+ try {
135
+ const result = await Swagger2OpenAPI__default.default.convertObj(swaggerDoc, {
136
+ patch: true,
137
+ // patch: true helps to fix minor issues
138
+ warnOnly: true
139
+ // Do not throw on non-patchable errors
140
+ });
141
+ return result.openapi;
142
+ } catch (error) {
143
+ console.error("Error converting Swagger 2.0 to OpenAPI 3.0:", error);
144
+ throw error;
145
+ }
146
+ }
147
+ }
148
+
72
149
  class ThreeScaleApiEntityProvider {
73
150
  static SERVICES_FETCH_SIZE = 500;
74
151
  env;
@@ -76,6 +153,7 @@ class ThreeScaleApiEntityProvider {
76
153
  accessToken;
77
154
  logger;
78
155
  scheduleFn;
156
+ openApiMerger;
79
157
  connection;
80
158
  static fromConfig(deps, options) {
81
159
  const providerConfigs = readThreeScaleApiEntityConfigs(deps.config);
@@ -113,6 +191,7 @@ class ThreeScaleApiEntityProvider {
113
191
  target: this.getProviderName()
114
192
  });
115
193
  this.scheduleFn = this.createScheduleFn(taskRunner);
194
+ this.openApiMerger = new OpenAPIMergerAndConverter();
116
195
  }
117
196
  createScheduleFn(taskRunner) {
118
197
  return async () => {
@@ -169,22 +248,19 @@ class ThreeScaleApiEntityProvider {
169
248
  for (const element of services.services) {
170
249
  const service = element;
171
250
  this.logger.debug(`Find service ${service.service.name}`);
172
- const apiDoc = apiDocs.api_docs.find((obj) => {
173
- if (obj.api_doc.service_id !== void 0) {
174
- return obj.api_doc.service_id === service.service.id;
175
- }
176
- return false;
177
- });
251
+ const docs = apiDocs.api_docs.filter(
252
+ (obj) => obj.api_doc.service_id === service.service.id
253
+ );
178
254
  const proxy = await getProxyConfig(
179
255
  this.baseUrl,
180
256
  this.accessToken,
181
257
  service.service.id
182
258
  );
183
- if (apiDoc !== void 0) {
184
- this.logger.info(JSON.stringify(apiDoc));
185
- const apiEntity = this.buildApiEntityFromService(
259
+ if (isNonEmptyArray(docs)) {
260
+ this.logger.info(JSON.stringify(docs));
261
+ const apiEntity = await this.buildApiEntityFromService(
186
262
  service,
187
- apiDoc,
263
+ docs,
188
264
  proxy
189
265
  );
190
266
  entities.push(apiEntity);
@@ -205,9 +281,41 @@ class ThreeScaleApiEntityProvider {
205
281
  }))
206
282
  });
207
283
  }
208
- buildApiEntityFromService(service, apiDoc, proxy) {
284
+ async buildApiEntityFromService(service, apiDocs, proxy) {
209
285
  const location = `url:${this.baseUrl}/apiconfig/services/${service.service.id}`;
210
- const spec = JSON.parse(apiDoc.api_doc.body);
286
+ const serviceDescription = service.service.description || "";
287
+ let entityDescription;
288
+ const docs = apiDocs.map((doc) => JSON.parse(doc.api_doc.body));
289
+ let swaggerDocJSON;
290
+ if (docs.length > 1) {
291
+ let mergedDescription = `[Merged ${docs.length} API docs]`;
292
+ let mergedTitle = mergedDescription;
293
+ const convertedDocs = [];
294
+ for (const doc of docs) {
295
+ const convertedDoc = await this.openApiMerger.convertAPIDocToOpenAPI3(
296
+ doc
297
+ );
298
+ convertedDocs.push(convertedDoc);
299
+ mergedDescription = getDocInfo(convertedDoc)?.description ? `${mergedDescription} ${getDocInfo(convertedDoc)?.description}` : mergedDescription;
300
+ mergedTitle = getDocInfo(convertedDoc)?.title ? `${mergedTitle} ${getDocInfo(convertedDoc)?.title}` : mergedTitle;
301
+ }
302
+ if (isNonEmptyArray(convertedDocs)) {
303
+ swaggerDocJSON = await this.openApiMerger.mergeOpenAPI3Docs(
304
+ convertedDocs
305
+ );
306
+ swaggerDocJSON.info.description = mergedDescription;
307
+ swaggerDocJSON.info.title = mergedTitle;
308
+ entityDescription = mergedDescription;
309
+ }
310
+ }
311
+ if (docs.length === 1) {
312
+ swaggerDocJSON = docs[0];
313
+ const spec = JSON.parse(apiDocs[0].api_doc.body);
314
+ if (isSwagger1_2(spec)) {
315
+ swaggerDocJSON = await this.openApiMerger.convertSwagger1_2To2_0(spec);
316
+ }
317
+ entityDescription = getDocInfo(spec)?.description;
318
+ }
211
319
  return {
212
320
  kind: "API",
213
321
  apiVersion: "backstage.io/v1alpha1",
@@ -218,7 +326,7 @@ class ThreeScaleApiEntityProvider {
218
326
  },
219
327
  // TODO: add tenant name
220
328
  name: `${service.service.system_name}`,
221
- description: spec.info.description || `Version: ${service.service.description}`,
329
+ description: entityDescription || serviceDescription,
222
330
  // TODO: add labels
223
331
  // labels: this.getApiEntityLabels(service),
224
332
  links: [
@@ -241,11 +349,17 @@ class ThreeScaleApiEntityProvider {
241
349
  lifecycle: this.env,
242
350
  system: "3scale",
243
351
  owner: "3scale",
244
- definition: apiDoc.api_doc.body
352
+ definition: JSON.stringify(swaggerDocJSON, null, 2)
245
353
  }
246
354
  };
247
355
  }
248
356
  }
357
+ function getDocInfo(spec) {
358
+ if (isSwagger2_0(spec) || isOpenAPI3_0(spec)) {
359
+ return spec.info;
360
+ }
361
+ return void 0;
362
+ }
249
363
 
250
364
  const catalogModule3ScaleEntityProvider = backendPluginApi.createBackendModule({
251
365
  moduleId: "catalog-backend-module-3scale",
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/clients/ThreeScaleAPIConnector.ts","../src/providers/config.ts","../src/providers/ThreeScaleApiEntityProvider.ts","../src/module.ts"],"sourcesContent":["/*\n * Copyright 2024 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 */\nimport type { APIDocs, Proxy, Services } from './types';\n\nexport function listServices(\n baseUrl: string,\n access_token: string,\n page: number,\n size: number,\n): Promise<Services> {\n return fetch(\n `${baseUrl}/admin/api/services.json?access_token=${access_token}&page=${page}&size=${size}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<Services>;\n });\n}\n\nexport function listApiDocs(\n baseUrl: string,\n access_token: string,\n): Promise<APIDocs> {\n return fetch(\n `${baseUrl}/admin/api/active_docs.json?access_token=${access_token}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<APIDocs>;\n });\n}\n\nexport function getProxyConfig(\n baseUrl: string,\n access_token: string,\n service_id: number,\n): Promise<Proxy> {\n return fetch(\n `${baseUrl}/admin/api/services/${service_id}/proxy.json?access_token=${access_token}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<Proxy>;\n });\n}\n","/*\n * Copyright 2024 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 */\nimport { readSchedulerServiceTaskScheduleDefinitionFromConfig } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport { ThreeScaleConfig } from './types';\n\nexport function readThreeScaleApiEntityConfigs(\n config: Config,\n): ThreeScaleConfig[] {\n const providerConfigs = config.getOptionalConfig(\n 'catalog.providers.threeScaleApiEntity',\n );\n if (!providerConfigs) {\n return [];\n }\n return providerConfigs\n .keys()\n .map(id =>\n readThreeScaleApiEntityConfig(id, providerConfigs.getConfig(id)),\n );\n}\n\nfunction readThreeScaleApiEntityConfig(\n id: string,\n config: Config,\n): ThreeScaleConfig {\n const baseUrl = config.getString('baseUrl');\n const accessToken = config.getString('accessToken');\n const systemLabel = config.getOptionalString('systemLabel');\n const ownerLabel = config.getOptionalString('ownerLabel');\n const addLabels = config.getOptionalBoolean('addLabels') || true;\n\n const schedule = config.has('schedule')\n ? readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config.getConfig('schedule'),\n )\n : undefined;\n\n return {\n id,\n baseUrl,\n accessToken,\n systemLabel,\n ownerLabel,\n addLabels,\n schedule,\n };\n}\n","/*\n * Copyright 2024 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 type {\n SchedulerServiceTaskRunner,\n SchedulerService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n ApiEntity,\n Entity,\n} from '@backstage/catalog-model';\n\nimport type { Config } from '@backstage/config';\nimport { InputError, isError, NotFoundError } from '@backstage/errors';\n\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\n\nimport {\n getProxyConfig,\n listApiDocs,\n listServices,\n} from '../clients/ThreeScaleAPIConnector';\nimport type {\n APIDocElement,\n APIDocs,\n Proxy,\n ServiceElement,\n Services,\n} from '../clients/types';\nimport { readThreeScaleApiEntityConfigs } from './config';\nimport type { ThreeScaleConfig } from './types';\n\nexport class ThreeScaleApiEntityProvider implements EntityProvider {\n private static SERVICES_FETCH_SIZE: number = 500;\n private readonly env: string;\n private readonly baseUrl: string;\n private readonly accessToken: string;\n private readonly logger: LoggerService;\n private readonly scheduleFn: () => Promise<void>;\n private connection?: EntityProviderConnection;\n\n static fromConfig(\n deps: {\n config: Config;\n logger: LoggerService;\n },\n\n options: {\n schedule: SchedulerServiceTaskRunner;\n scheduler: SchedulerService;\n },\n ): ThreeScaleApiEntityProvider[] {\n const providerConfigs = readThreeScaleApiEntityConfigs(deps.config);\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\n return providerConfigs.map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new InputError(\n `No schedule provided via config for ThreeScaleApiEntityProvider:${providerConfig.id}.`,\n );\n }\n\n let taskRunner;\n\n if (options.scheduler && providerConfig.schedule) {\n // Create a scheduled task runner using the provided scheduler and schedule configuration\n taskRunner = options.scheduler.createScheduledTaskRunner(\n providerConfig.schedule,\n );\n } else if (options.schedule) {\n // Use the provided schedule directly\n taskRunner = options.schedule;\n } else {\n // Handle the case where both options.schedule and options.scheduler are missing\n throw new Error('Neither schedule nor scheduler is provided.');\n }\n\n return new ThreeScaleApiEntityProvider(\n providerConfig,\n deps.logger,\n taskRunner,\n );\n });\n }\n\n private constructor(\n config: ThreeScaleConfig,\n logger: LoggerService,\n taskRunner: SchedulerServiceTaskRunner,\n ) {\n this.env = config.id;\n this.baseUrl = config.baseUrl;\n this.accessToken = config.accessToken;\n this.logger = logger.child({\n target: this.getProviderName(),\n });\n\n this.scheduleFn = this.createScheduleFn(taskRunner);\n }\n\n private createScheduleFn(\n taskRunner: SchedulerServiceTaskRunner,\n ): () => Promise<void> {\n return async () => {\n const taskId = `${this.getProviderName()}:run`;\n return taskRunner.run({\n id: taskId,\n fn: async () => {\n try {\n await this.run();\n } catch (error: any) {\n if (isError(error)) {\n // Ensure that we don't log any sensitive internal data:\n this.logger.error(\n `Error while syncing 3scale API from ${this.baseUrl}`,\n {\n // Default Error properties:\n name: error.name,\n message: error.message,\n stack: error.stack,\n // Additional status code if available:\n status: (error.response as { status?: string })?.status,\n },\n );\n }\n }\n },\n });\n };\n }\n\n getProviderName(): string {\n return `ThreeScaleApiEntityProvider:${this.env}`;\n }\n\n async connect(connection: EntityProviderConnection): Promise<void> {\n this.connection = connection;\n await this.scheduleFn();\n }\n\n async run(): Promise<void> {\n if (!this.connection) {\n throw new NotFoundError('Not initialized');\n }\n\n this.logger.info(`Discovering ApiEntities from 3scale ${this.baseUrl}`);\n\n const entities: Entity[] = [];\n\n let page: number = 0;\n let services: Services;\n let apiDocs: APIDocs;\n let fetchServices: boolean = true;\n while (fetchServices) {\n services = await listServices(\n this.baseUrl,\n this.accessToken,\n page,\n ThreeScaleApiEntityProvider.SERVICES_FETCH_SIZE,\n );\n apiDocs = await listApiDocs(this.baseUrl, this.accessToken);\n for (const element of services.services) {\n const service = element;\n this.logger.debug(`Find service ${service.service.name}`);\n\n // Trying to find the API Doc for the service and validate if api doc was assigned to an API.\n const apiDoc = apiDocs.api_docs.find(obj => {\n if (obj.api_doc.service_id !== undefined) {\n return obj.api_doc.service_id === service.service.id;\n }\n return false;\n });\n\n const proxy = await getProxyConfig(\n this.baseUrl,\n this.accessToken,\n service.service.id,\n );\n if (apiDoc !== undefined) {\n this.logger.info(JSON.stringify(apiDoc));\n const apiEntity: ApiEntity = this.buildApiEntityFromService(\n service,\n apiDoc,\n proxy,\n );\n entities.push(apiEntity);\n this.logger.debug(`Discovered ApiEntity ${service.service.name}`);\n }\n }\n\n if (\n services.services.length <\n ThreeScaleApiEntityProvider.SERVICES_FETCH_SIZE\n ) {\n fetchServices = false;\n }\n page++;\n }\n\n this.logger.info(`Applying the mutation with ${entities.length} entities`);\n\n await this.connection.applyMutation({\n type: 'full',\n entities: entities.map(entity => ({\n entity,\n locationKey: this.getProviderName(),\n })),\n });\n }\n\n private buildApiEntityFromService(\n service: ServiceElement,\n apiDoc: APIDocElement,\n proxy: Proxy,\n ): ApiEntity {\n const location = `url:${this.baseUrl}/apiconfig/services/${service.service.id}`;\n\n const spec = JSON.parse(apiDoc.api_doc.body);\n\n return {\n kind: 'API',\n apiVersion: 'backstage.io/v1alpha1',\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n // TODO: add tenant name\n name: `${service.service.system_name}`,\n description:\n spec.info.description || `Version: ${service.service.description}`,\n // TODO: add labels\n // labels: this.getApiEntityLabels(service),\n links: [\n {\n url: `${this.baseUrl}/apiconfig/services/${service.service.id}`,\n title: '3scale Overview',\n },\n {\n url: `${proxy.proxy.sandbox_endpoint}`,\n title: 'Staging Apicast Endpoint',\n },\n {\n url: `${proxy.proxy.endpoint}`,\n title: 'Production Apicast Endpoint',\n },\n ],\n },\n spec: {\n type: 'openapi',\n lifecycle: this.env,\n system: '3scale',\n owner: '3scale',\n definition: apiDoc.api_doc.body,\n },\n };\n }\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\n\nimport { ThreeScaleApiEntityProvider } from './providers';\n\nexport const catalogModule3ScaleEntityProvider = createBackendModule({\n moduleId: 'catalog-backend-module-3scale',\n pluginId: 'catalog',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\n },\n async init({ catalog, config, logger, scheduler }) {\n catalog.addEntityProvider(\n ThreeScaleApiEntityProvider.fromConfig(\n { config, logger },\n {\n scheduler: scheduler,\n schedule: scheduler.createScheduledTaskRunner({\n frequency: { minutes: 30 },\n timeout: { minutes: 3 },\n }),\n },\n ),\n );\n },\n });\n },\n});\n"],"names":["readSchedulerServiceTaskScheduleDefinitionFromConfig","InputError","isError","NotFoundError","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION","createBackendModule","catalogProcessingExtensionPoint","coreServices"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/clients/ThreeScaleAPIConnector.ts","../src/providers/config.ts","../src/providers/types.ts","../src/providers/open-api-merger-converter.ts","../src/providers/ThreeScaleApiEntityProvider.ts","../src/module.ts"],"sourcesContent":["/*\n * Copyright 2024 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 */\nimport type { APIDocs, Proxy, Services } from './types';\n\nexport function listServices(\n baseUrl: string,\n access_token: string,\n page: number,\n size: number,\n): Promise<Services> {\n return fetch(\n `${baseUrl}/admin/api/services.json?access_token=${access_token}&page=${page}&size=${size}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<Services>;\n });\n}\n\nexport function listApiDocs(\n baseUrl: string,\n access_token: string,\n): Promise<APIDocs> {\n return fetch(\n `${baseUrl}/admin/api/active_docs.json?access_token=${access_token}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<APIDocs>;\n });\n}\n\nexport function getProxyConfig(\n baseUrl: string,\n access_token: string,\n service_id: number,\n): Promise<Proxy> {\n return fetch(\n `${baseUrl}/admin/api/services/${service_id}/proxy.json?access_token=${access_token}`,\n ).then(response => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json() as Promise<Proxy>;\n });\n}\n","/*\n * Copyright 2024 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 */\nimport { readSchedulerServiceTaskScheduleDefinitionFromConfig } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport { ThreeScaleConfig } from './types';\n\nexport function readThreeScaleApiEntityConfigs(\n config: Config,\n): ThreeScaleConfig[] {\n const providerConfigs = config.getOptionalConfig(\n 'catalog.providers.threeScaleApiEntity',\n );\n if (!providerConfigs) {\n return [];\n }\n return providerConfigs\n .keys()\n .map(id =>\n readThreeScaleApiEntityConfig(id, providerConfigs.getConfig(id)),\n );\n}\n\nfunction readThreeScaleApiEntityConfig(\n id: string,\n config: Config,\n): ThreeScaleConfig {\n const baseUrl = config.getString('baseUrl');\n const accessToken = config.getString('accessToken');\n const systemLabel = config.getOptionalString('systemLabel');\n const ownerLabel = config.getOptionalString('ownerLabel');\n const addLabels = config.getOptionalBoolean('addLabels') || true;\n\n const schedule = config.has('schedule')\n ? readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config.getConfig('schedule'),\n )\n : undefined;\n\n return {\n id,\n baseUrl,\n accessToken,\n systemLabel,\n ownerLabel,\n addLabels,\n schedule,\n };\n}\n","/*\n * Copyright 2024 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 type { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api';\n\nexport type ThreeScaleConfig = {\n id: string;\n baseUrl: string;\n accessToken: string;\n systemLabel?: string;\n ownerLabel?: string;\n addLabels?: boolean;\n schedule?: SchedulerServiceTaskScheduleDefinition;\n};\n\nexport type NonEmptyArray<T> = [T, ...T[]];\n\nexport function isNonEmptyArray<T>(arr: T[]): arr is NonEmptyArray<T> {\n return arr.length > 0;\n}\n","/*\n * Copyright 2024 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 { merge, isErrorResult, MergeInput } from 'openapi-merge';\nimport { Swagger } from 'atlassian-openapi';\nimport Swagger2OpenAPI from 'swagger2openapi';\n// @ts-ignore\nimport SwaggerConverter from 'swagger-converter';\nimport { NonEmptyArray } from './types';\n\nexport function isSwagger1_2(apiDoc: any): boolean {\n return apiDoc.swaggerVersion && apiDoc.swaggerVersion === '1.2';\n}\n\nexport function isSwagger2_0(apiDoc: any): boolean {\n return apiDoc.swagger && apiDoc.swagger === '2.0';\n}\n\nexport function isOpenAPI3_0(apiDoc: any): boolean {\n return apiDoc.openapi;\n}\n\nexport class OpenAPIMergerAndConverter {\n async mergeOpenAPI3Docs(\n docs: NonEmptyArray<Swagger.SwaggerV3>,\n ): Promise<Swagger.SwaggerV3> {\n const mergeInput: MergeInput = docs.map(doc => {\n return { oas: doc };\n });\n\n const result = await merge(mergeInput);\n if (isErrorResult(result)) {\n throw new Error(result.message);\n }\n return result.output;\n }\n\n // Convert api doc to format openAPI 3. Do nothing with doc if it has format openAPI 3.0.\n // 3scale supports API docs in formats:\n // - swagger 1.2\n // - swagger 2.0\n // - openAPI 3.0\n async convertAPIDocToOpenAPI3(apiDoc: any): Promise<Swagger.SwaggerV3> {\n if (isOpenAPI3_0(apiDoc)) {\n return apiDoc;\n }\n if (isSwagger1_2(apiDoc)) {\n // Unfortunately there is no library in the JavaScript world, which can convert both swagger 1.2 and 2.0 to openAPI 3.0.\n // That's why, for swagger 1.2 we are using convertation to swagger 2.0. And then swagger 2.0 will be converted to openAPI 3.0.\n const swagger2_0Doc = await this.convertSwagger1_2To2_0(apiDoc);\n return await this.convertSwagger2_0ToOpenAPI3_0(swagger2_0Doc);\n }\n if (isSwagger2_0(apiDoc)) {\n return await this.convertSwagger2_0ToOpenAPI3_0(apiDoc);\n }\n\n throw new Error(\n `Unsupported API document. Plugin supports Swagger 1.2, 2.0, 3.0(Open API 3.0)`,\n );\n }\n\n async convertSwagger1_2To2_0(swaggerDoc: any): Promise<any> {\n try {\n const result = SwaggerConverter.convert(swaggerDoc, {});\n return result;\n } catch (error) {\n console.error('Error converting Swagger 1.2 to Swagger 2.0:', error);\n throw error;\n }\n }\n\n private async convertSwagger2_0ToOpenAPI3_0(swaggerDoc: any): Promise<any> {\n try {\n const result = await Swagger2OpenAPI.convertObj(swaggerDoc, {\n patch: true, // patch: true helps to fix minor issues\n warnOnly: true, // Do not throw on non-patchable errors\n });\n return result.openapi;\n } catch (error) {\n console.error('Error converting Swagger 2.0 to OpenAPI 3.0:', error);\n throw error;\n }\n }\n}\n","/*\n * Copyright 2024 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 type {\n SchedulerServiceTaskRunner,\n SchedulerService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n ApiEntity,\n Entity,\n} from '@backstage/catalog-model';\n\nimport type { Config } from '@backstage/config';\nimport { InputError, isError, NotFoundError } from '@backstage/errors';\n\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\n\nimport {\n getProxyConfig,\n listApiDocs,\n listServices,\n} from '../clients/ThreeScaleAPIConnector';\nimport type {\n APIDocElement,\n APIDocs,\n Proxy,\n ServiceElement,\n Services,\n} from '../clients/types';\nimport { readThreeScaleApiEntityConfigs } from './config';\nimport { isNonEmptyArray, NonEmptyArray, ThreeScaleConfig } from './types';\nimport {\n isOpenAPI3_0,\n isSwagger1_2,\n isSwagger2_0,\n OpenAPIMergerAndConverter,\n} from './open-api-merger-converter';\nimport { Swagger } from 'atlassian-openapi';\n\nexport class ThreeScaleApiEntityProvider implements EntityProvider {\n private static SERVICES_FETCH_SIZE: number = 500;\n private readonly env: string;\n private readonly baseUrl: string;\n private readonly accessToken: string;\n private readonly logger: LoggerService;\n private readonly scheduleFn: () => Promise<void>;\n private readonly openApiMerger: OpenAPIMergerAndConverter;\n private connection?: EntityProviderConnection;\n\n static fromConfig(\n deps: {\n config: Config;\n logger: LoggerService;\n },\n\n options: {\n schedule: SchedulerServiceTaskRunner;\n scheduler: SchedulerService;\n },\n ): ThreeScaleApiEntityProvider[] {\n const providerConfigs = readThreeScaleApiEntityConfigs(deps.config);\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\n return providerConfigs.map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new InputError(\n `No schedule provided via config for ThreeScaleApiEntityProvider:${providerConfig.id}.`,\n );\n }\n\n let taskRunner;\n\n if (options.scheduler && providerConfig.schedule) {\n // Create a scheduled task runner using the provided scheduler and schedule configuration\n taskRunner = options.scheduler.createScheduledTaskRunner(\n providerConfig.schedule,\n );\n } else if (options.schedule) {\n // Use the provided schedule directly\n taskRunner = options.schedule;\n } else {\n // Handle the case where both options.schedule and options.scheduler are missing\n throw new Error('Neither schedule nor scheduler is provided.');\n }\n\n return new ThreeScaleApiEntityProvider(\n providerConfig,\n deps.logger,\n taskRunner,\n );\n });\n }\n\n private constructor(\n config: ThreeScaleConfig,\n logger: LoggerService,\n taskRunner: SchedulerServiceTaskRunner,\n ) {\n this.env = config.id;\n this.baseUrl = config.baseUrl;\n this.accessToken = config.accessToken;\n this.logger = logger.child({\n target: this.getProviderName(),\n });\n\n this.scheduleFn = this.createScheduleFn(taskRunner);\n this.openApiMerger = new OpenAPIMergerAndConverter();\n }\n\n private createScheduleFn(\n taskRunner: SchedulerServiceTaskRunner,\n ): () => Promise<void> {\n return async () => {\n const taskId = `${this.getProviderName()}:run`;\n return taskRunner.run({\n id: taskId,\n fn: async () => {\n try {\n await this.run();\n } catch (error: any) {\n if (isError(error)) {\n // Ensure that we don't log any sensitive internal data:\n this.logger.error(\n `Error while syncing 3scale API from ${this.baseUrl}`,\n {\n // Default Error properties:\n name: error.name,\n message: error.message,\n stack: error.stack,\n // Additional status code if available:\n status: (error.response as { status?: string })?.status,\n },\n );\n }\n }\n },\n });\n };\n }\n\n getProviderName(): string {\n return `ThreeScaleApiEntityProvider:${this.env}`;\n }\n\n async connect(connection: EntityProviderConnection): Promise<void> {\n this.connection = connection;\n await this.scheduleFn();\n }\n\n async run(): Promise<void> {\n if (!this.connection) {\n throw new NotFoundError('Not initialized');\n }\n\n this.logger.info(`Discovering ApiEntities from 3scale ${this.baseUrl}`);\n\n const entities: Entity[] = [];\n\n let page: number = 0;\n let services: Services;\n let apiDocs: APIDocs;\n let fetchServices: boolean = true;\n while (fetchServices) {\n services = await listServices(\n this.baseUrl,\n this.accessToken,\n page,\n ThreeScaleApiEntityProvider.SERVICES_FETCH_SIZE,\n );\n apiDocs = await listApiDocs(this.baseUrl, this.accessToken);\n for (const element of services.services) {\n const service = element;\n this.logger.debug(`Find service ${service.service.name}`);\n\n const docs = apiDocs.api_docs.filter(\n obj => obj.api_doc.service_id === service.service.id,\n );\n const proxy = await getProxyConfig(\n this.baseUrl,\n this.accessToken,\n service.service.id,\n );\n if (isNonEmptyArray(docs)) {\n this.logger.info(JSON.stringify(docs));\n const apiEntity: ApiEntity = await this.buildApiEntityFromService(\n service,\n docs,\n proxy,\n );\n entities.push(apiEntity);\n this.logger.debug(`Discovered ApiEntity ${service.service.name}`);\n }\n }\n\n if (\n services.services.length <\n ThreeScaleApiEntityProvider.SERVICES_FETCH_SIZE\n ) {\n fetchServices = false;\n }\n page++;\n }\n\n this.logger.info(`Applying the mutation with ${entities.length} entities`);\n\n await this.connection.applyMutation({\n type: 'full',\n entities: entities.map(entity => ({\n entity,\n locationKey: this.getProviderName(),\n })),\n });\n }\n\n private async buildApiEntityFromService(\n service: ServiceElement,\n apiDocs: NonEmptyArray<APIDocElement>,\n proxy: Proxy,\n ): Promise<ApiEntity> {\n const location = `url:${this.baseUrl}/apiconfig/services/${service.service.id}`;\n const serviceDescription = service.service.description || '';\n let entityDescription: string | undefined;\n\n const docs = apiDocs.map(doc => JSON.parse(doc.api_doc.body));\n\n let swaggerDocJSON;\n if (docs.length > 1) {\n // convert all docs to openapi 3.0 and merge them\n let mergedDescription = `[Merged ${docs.length} API docs]`;\n let mergedTitle = mergedDescription;\n const convertedDocs: Swagger.SwaggerV3[] = [];\n for (const doc of docs) {\n const convertedDoc = await this.openApiMerger.convertAPIDocToOpenAPI3(\n doc,\n );\n convertedDocs.push(convertedDoc);\n mergedDescription = getDocInfo(convertedDoc)?.description\n ? `${mergedDescription} ${getDocInfo(convertedDoc)?.description}`\n : mergedDescription;\n mergedTitle = getDocInfo(convertedDoc)?.title\n ? `${mergedTitle} ${getDocInfo(convertedDoc)?.title}`\n : mergedTitle;\n }\n if (isNonEmptyArray(convertedDocs)) {\n swaggerDocJSON = await this.openApiMerger.mergeOpenAPI3Docs(\n convertedDocs,\n );\n swaggerDocJSON.info.description = mergedDescription;\n swaggerDocJSON.info.title = mergedTitle;\n entityDescription = mergedDescription;\n }\n }\n\n if (docs.length === 1) {\n swaggerDocJSON = docs[0];\n\n const spec = JSON.parse(apiDocs[0].api_doc.body);\n if (isSwagger1_2(spec)) {\n // Backstage UI can render only openapi 3.0 or swagger 2.0. That's why we need to convert swagger 1.2 to swagger 2.0.\n swaggerDocJSON = await this.openApiMerger.convertSwagger1_2To2_0(spec);\n }\n entityDescription = getDocInfo(spec)?.description;\n }\n\n return {\n kind: 'API',\n apiVersion: 'backstage.io/v1alpha1',\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n // TODO: add tenant name\n name: `${service.service.system_name}`,\n description: entityDescription || serviceDescription,\n // TODO: add labels\n // labels: this.getApiEntityLabels(service),\n links: [\n {\n url: `${this.baseUrl}/apiconfig/services/${service.service.id}`,\n title: '3scale Overview',\n },\n {\n url: `${proxy.proxy.sandbox_endpoint}`,\n title: 'Staging Apicast Endpoint',\n },\n {\n url: `${proxy.proxy.endpoint}`,\n title: 'Production Apicast Endpoint',\n },\n ],\n },\n spec: {\n type: 'openapi',\n lifecycle: this.env,\n system: '3scale',\n owner: '3scale',\n definition: JSON.stringify(swaggerDocJSON, null, 2),\n },\n };\n }\n}\n\nfunction getDocInfo(\n spec: any,\n): { description: string; title: string } | undefined {\n if (isSwagger2_0(spec) || isOpenAPI3_0(spec)) {\n return spec.info;\n }\n\n // swagger 1.2 spec doc defined by single file doesn't have description field\n return undefined;\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';\n\nimport { ThreeScaleApiEntityProvider } from './providers';\n\nexport const catalogModule3ScaleEntityProvider = createBackendModule({\n moduleId: 'catalog-backend-module-3scale',\n pluginId: 'catalog',\n register(env) {\n env.registerInit({\n deps: {\n catalog: catalogProcessingExtensionPoint,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n scheduler: coreServices.scheduler,\n },\n async init({ catalog, config, logger, scheduler }) {\n catalog.addEntityProvider(\n ThreeScaleApiEntityProvider.fromConfig(\n { config, logger },\n {\n scheduler: scheduler,\n schedule: scheduler.createScheduledTaskRunner({\n frequency: { minutes: 30 },\n timeout: { minutes: 3 },\n }),\n },\n ),\n );\n },\n });\n },\n});\n"],"names":["readSchedulerServiceTaskScheduleDefinitionFromConfig","merge","isErrorResult","SwaggerConverter","Swagger2OpenAPI","InputError","isError","NotFoundError","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION","createBackendModule","catalogProcessingExtensionPoint","coreServices"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -114,6 +114,7 @@ declare class ThreeScaleApiEntityProvider implements EntityProvider {
114
114
  private readonly accessToken;
115
115
  private readonly logger;
116
116
  private readonly scheduleFn;
117
+ private readonly openApiMerger;
117
118
  private connection?;
118
119
  static fromConfig(deps: {
119
120
  config: Config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-3scale-backend",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
@@ -30,22 +30,27 @@
30
30
  "postversion": "yarn run export-dynamic",
31
31
  "prepack": "backstage-cli package prepack",
32
32
  "start": "backstage-cli package start",
33
- "test": "backstage-cli package test --passWithNoTests --coverage",
34
- "tsc": "tsc"
33
+ "test": "backstage-cli package test --passWithNoTests --coverage"
35
34
  },
36
35
  "dependencies": {
37
36
  "@backstage/backend-plugin-api": "^1.0.0",
38
37
  "@backstage/catalog-model": "^1.7.0",
39
38
  "@backstage/errors": "^1.2.4",
40
- "@backstage/plugin-catalog-node": "^1.13.0"
39
+ "@backstage/plugin-catalog-node": "^1.13.0",
40
+ "atlassian-openapi": "^1.0.19",
41
+ "openapi-merge": "^1.3.3",
42
+ "swagger-converter": "2.1.0",
43
+ "swagger2openapi": "^7.0.4"
41
44
  },
42
45
  "devDependencies": {
43
46
  "@backstage/backend-defaults": "^0.5.0",
47
+ "@backstage/backend-test-utils": "0.4.4",
44
48
  "@backstage/cli": "^0.27.1",
45
49
  "@backstage/config": "^1.2.0",
46
50
  "@backstage/plugin-catalog-backend": "^1.26.0",
47
51
  "@janus-idp/cli": "1.13.1",
48
52
  "@types/supertest": "6.0.2",
53
+ "@types/swagger2openapi": "^7.0.4",
49
54
  "msw": "1.3.3",
50
55
  "supertest": "7.0.0"
51
56
  },