@backstage/backend-defaults 0.14.0 → 0.14.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.14.1-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3afeab4: Implementing `readTree` for `GoogleGcsReader`
8
+ - Updated dependencies
9
+ - @backstage/integration@1.19.2-next.0
10
+
11
+ ## 0.14.1-next.0
12
+
13
+ ### Patch Changes
14
+
15
+ - 7126bf2: Fixed a spelling mistake in root health service shutdown response.
16
+ - Updated dependencies
17
+ - @backstage/backend-app-api@1.4.0
18
+ - @backstage/backend-dev-utils@0.1.6
19
+ - @backstage/backend-plugin-api@1.6.0
20
+ - @backstage/cli-node@0.2.16
21
+ - @backstage/config@1.3.6
22
+ - @backstage/config-loader@1.10.7
23
+ - @backstage/errors@1.2.7
24
+ - @backstage/integration@1.19.0
25
+ - @backstage/integration-aws-node@0.1.19
26
+ - @backstage/types@1.2.2
27
+ - @backstage/plugin-auth-node@0.6.10
28
+ - @backstage/plugin-events-node@0.4.18
29
+ - @backstage/plugin-permission-node@0.10.7
30
+
3
31
  ## 0.14.0
4
32
 
5
33
  ### Minor Changes
@@ -27,7 +27,7 @@ class DefaultRootHealthService {
27
27
  if (this.#state === "down") {
28
28
  return {
29
29
  status: 503,
30
- payload: { message: "Backend is shuttting down", status: "error" }
30
+ payload: { message: "Backend is shutting down", status: "error" }
31
31
  };
32
32
  }
33
33
  return { status: 200, payload: { status: "ok" } };
@@ -1 +1 @@
1
- {"version":3,"file":"rootHealthServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHealth/rootHealthServiceFactory.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 */\n\nimport {\n RootHealthService,\n RootLifecycleService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class DefaultRootHealthService implements RootHealthService {\n #state: 'init' | 'up' | 'down' = 'init';\n readonly options: { lifecycle: RootLifecycleService };\n\n constructor(options: { lifecycle: RootLifecycleService }) {\n this.options = options;\n options.lifecycle.addStartupHook(() => {\n this.#state = 'up';\n });\n options.lifecycle.addBeforeShutdownHook(() => {\n this.#state = 'down';\n });\n }\n\n async getLiveness(): Promise<{ status: number; payload?: any }> {\n return { status: 200, payload: { status: 'ok' } };\n }\n\n async getReadiness(): Promise<{ status: number; payload?: any }> {\n if (this.#state === 'init') {\n return {\n status: 503,\n payload: { message: 'Backend has not started yet', status: 'error' },\n };\n }\n if (this.#state === 'down') {\n return {\n status: 503,\n payload: { message: 'Backend is shuttting down', status: 'error' },\n };\n }\n\n return { status: 200, payload: { status: 'ok' } };\n }\n}\n\n/**\n * @public\n */\nexport const rootHealthServiceFactory = createServiceFactory({\n service: coreServices.rootHealth,\n deps: {\n lifecycle: coreServices.rootLifecycle,\n },\n async factory({ lifecycle }) {\n return new DefaultRootHealthService({ lifecycle });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AAwBO,MAAM,wBAAA,CAAsD;AAAA,EACjE,MAAA,GAAiC,MAAA;AAAA,EACxB,OAAA;AAAA,EAET,YAAY,OAAA,EAA8C;AACxD,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,OAAA,CAAQ,SAAA,CAAU,eAAe,MAAM;AACrC,MAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,IAChB,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,SAAA,CAAU,sBAAsB,MAAM;AAC5C,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,WAAA,GAA0D;AAC9D,IAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAK,EAAE;AAAA,EAClD;AAAA,EAEA,MAAM,YAAA,GAA2D;AAC/D,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,EAAE,OAAA,EAAS,6BAAA,EAA+B,QAAQ,OAAA;AAAQ,OACrE;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,EAAE,OAAA,EAAS,2BAAA,EAA6B,QAAQ,OAAA;AAAQ,OACnE;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAK,EAAE;AAAA,EAClD;AACF;AAKO,MAAM,2BAA2BA,qCAAA,CAAqB;AAAA,EAC3D,SAASC,6BAAA,CAAa,UAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,WAAWA,6BAAA,CAAa;AAAA,GAC1B;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,SAAA,EAAU,EAAG;AAC3B,IAAA,OAAO,IAAI,wBAAA,CAAyB,EAAE,SAAA,EAAW,CAAA;AAAA,EACnD;AACF,CAAC;;;;;"}
1
+ {"version":3,"file":"rootHealthServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHealth/rootHealthServiceFactory.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 */\n\nimport {\n RootHealthService,\n RootLifecycleService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class DefaultRootHealthService implements RootHealthService {\n #state: 'init' | 'up' | 'down' = 'init';\n readonly options: { lifecycle: RootLifecycleService };\n\n constructor(options: { lifecycle: RootLifecycleService }) {\n this.options = options;\n options.lifecycle.addStartupHook(() => {\n this.#state = 'up';\n });\n options.lifecycle.addBeforeShutdownHook(() => {\n this.#state = 'down';\n });\n }\n\n async getLiveness(): Promise<{ status: number; payload?: any }> {\n return { status: 200, payload: { status: 'ok' } };\n }\n\n async getReadiness(): Promise<{ status: number; payload?: any }> {\n if (this.#state === 'init') {\n return {\n status: 503,\n payload: { message: 'Backend has not started yet', status: 'error' },\n };\n }\n if (this.#state === 'down') {\n return {\n status: 503,\n payload: { message: 'Backend is shutting down', status: 'error' },\n };\n }\n\n return { status: 200, payload: { status: 'ok' } };\n }\n}\n\n/**\n * @public\n */\nexport const rootHealthServiceFactory = createServiceFactory({\n service: coreServices.rootHealth,\n deps: {\n lifecycle: coreServices.rootLifecycle,\n },\n async factory({ lifecycle }) {\n return new DefaultRootHealthService({ lifecycle });\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":";;;;AAwBO,MAAM,wBAAA,CAAsD;AAAA,EACjE,MAAA,GAAiC,MAAA;AAAA,EACxB,OAAA;AAAA,EAET,YAAY,OAAA,EAA8C;AACxD,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,OAAA,CAAQ,SAAA,CAAU,eAAe,MAAM;AACrC,MAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,IAChB,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,SAAA,CAAU,sBAAsB,MAAM;AAC5C,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,WAAA,GAA0D;AAC9D,IAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAK,EAAE;AAAA,EAClD;AAAA,EAEA,MAAM,YAAA,GAA2D;AAC/D,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,EAAE,OAAA,EAAS,6BAAA,EAA+B,QAAQ,OAAA;AAAQ,OACrE;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,EAAE,OAAA,EAAS,0BAAA,EAA4B,QAAQ,OAAA;AAAQ,OAClE;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,MAAA,EAAQ,MAAK,EAAE;AAAA,EAClD;AACF;AAKO,MAAM,2BAA2BA,qCAAA,CAAqB;AAAA,EAC3D,SAASC,6BAAA,CAAa,UAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,WAAWA,6BAAA,CAAa;AAAA,GAC1B;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,SAAA,EAAU,EAAG;AAC3B,IAAA,OAAO,IAAI,wBAAA,CAAyB,EAAE,SAAA,EAAW,CAAA;AAAA,EACnD;AACF,CAAC;;;;;"}
@@ -6,6 +6,7 @@ var integration = require('@backstage/integration');
6
6
  var ReadUrlResponseFactory = require('./ReadUrlResponseFactory.cjs.js');
7
7
  var _package = require('../../../package.json.cjs.js');
8
8
  var errors = require('@backstage/errors');
9
+ var posix = require('path/posix');
9
10
 
10
11
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
12
 
@@ -44,7 +45,7 @@ const parseURL = (url) => {
44
45
  };
45
46
  };
46
47
  class GoogleGcsUrlReader {
47
- static factory = ({ config, logger }) => {
48
+ static factory = ({ config, logger, treeResponseFactory }) => {
48
49
  if (!config.has("integrations.googleGcs")) {
49
50
  return [];
50
51
  }
@@ -68,15 +69,19 @@ class GoogleGcsUrlReader {
68
69
  userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${_package.default.version}`
69
70
  });
70
71
  }
71
- const reader = new GoogleGcsUrlReader(gcsConfig, storage);
72
+ const reader = new GoogleGcsUrlReader(gcsConfig, storage, {
73
+ treeResponseFactory
74
+ });
72
75
  const predicate = (url) => url.host === GOOGLE_GCS_HOST;
73
76
  return [{ reader, predicate }];
74
77
  };
75
78
  integration;
76
79
  storage;
77
- constructor(integration, storage) {
80
+ deps;
81
+ constructor(integration, storage, deps) {
78
82
  this.integration = integration;
79
83
  this.storage = storage;
84
+ this.deps = deps;
80
85
  }
81
86
  readStreamFromUrl(url) {
82
87
  const { bucket, key } = parseURL(url);
@@ -93,8 +98,23 @@ class GoogleGcsUrlReader {
93
98
  const stream = this.readStreamFromUrl(url);
94
99
  return ReadUrlResponseFactory.ReadUrlResponseFactory.fromReadable(stream);
95
100
  }
96
- async readTree() {
97
- throw new Error("GcsUrlReader does not implement readTree");
101
+ async readTree(url, _options) {
102
+ const { bucket, key } = parseURL(url);
103
+ if (key.match(/[*?]/)) {
104
+ throw new Error(
105
+ "GcsUrlReader readTree does not support glob patterns, use search instead"
106
+ );
107
+ }
108
+ const [files] = await this.storage.bucket(bucket).getFiles({
109
+ autoPaginate: true,
110
+ prefix: key
111
+ });
112
+ const responses = files.map((file) => ({
113
+ data: file.createReadStream(),
114
+ path: posix.relative(key, file.name),
115
+ lastModifiedAt: file.metadata.updated ? new Date(file.metadata.updated) : void 0
116
+ }));
117
+ return this.deps.treeResponseFactory.fromReadableArray(responses);
98
118
  }
99
119
  async search(url, options) {
100
120
  const { bucket, key: pattern } = parseURL(url);
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleGcsUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as GoogleCloud from '@google-cloud/storage';\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory } from './types';\nimport getRawBody from 'raw-body';\nimport {\n GoogleGcsIntegrationConfig,\n readGoogleGcsIntegrationConfig,\n} from '@backstage/integration';\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport packageinfo from '../../../../package.json';\nimport { assertError } from '@backstage/errors';\n\nconst GOOGLE_GCS_HOST = 'storage.cloud.google.com';\n\nconst parseURL = (\n url: string,\n): { host: string; bucket: string; key: string } => {\n const { host, pathname } = new URL(url);\n\n if (host !== GOOGLE_GCS_HOST) {\n throw new Error(`not a valid GCS URL: ${url}`);\n }\n\n const [, bucket, ...key] = pathname.split('/');\n return {\n host: host,\n bucket,\n key: key.join('/'),\n };\n};\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files on Google GCS.\n *\n * @public\n */\nexport class GoogleGcsUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, logger }) => {\n if (!config.has('integrations.googleGcs')) {\n return [];\n }\n const gcsConfig = readGoogleGcsIntegrationConfig(\n config.getConfig('integrations.googleGcs'),\n );\n let storage: GoogleCloud.Storage;\n if (!gcsConfig.clientEmail || !gcsConfig.privateKey) {\n logger.info(\n 'googleGcs credentials not found in config. Using default credentials provider.',\n );\n storage = new GoogleCloud.Storage({\n userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`,\n });\n } else {\n storage = new GoogleCloud.Storage({\n credentials: {\n client_email: gcsConfig.clientEmail || undefined,\n private_key: gcsConfig.privateKey || undefined,\n },\n userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`,\n });\n }\n const reader = new GoogleGcsUrlReader(gcsConfig, storage);\n const predicate = (url: URL) => url.host === GOOGLE_GCS_HOST;\n return [{ reader, predicate }];\n };\n\n private readonly integration: GoogleGcsIntegrationConfig;\n private readonly storage: GoogleCloud.Storage;\n\n constructor(\n integration: GoogleGcsIntegrationConfig,\n storage: GoogleCloud.Storage,\n ) {\n this.integration = integration;\n this.storage = storage;\n }\n\n private readStreamFromUrl(url: string): Readable {\n const { bucket, key } = parseURL(url);\n return this.storage.bucket(bucket).file(key).createReadStream();\n }\n\n async read(url: string): Promise<Buffer> {\n try {\n return await getRawBody(this.readStreamFromUrl(url));\n } catch (error) {\n throw new Error(`unable to read gcs file from ${url}, ${error}`);\n }\n }\n\n async readUrl(\n url: string,\n _options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // TODO etag is not implemented yet.\n const stream = this.readStreamFromUrl(url);\n return ReadUrlResponseFactory.fromReadable(stream);\n }\n\n async readTree(): Promise<UrlReaderServiceReadTreeResponse> {\n throw new Error('GcsUrlReader does not implement readTree');\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { bucket, key: pattern } = parseURL(url);\n\n // If it's a direct URL we use readUrl instead\n if (!pattern?.match(/[*?]/)) {\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n if (!pattern.endsWith('*') || pattern.indexOf('*') !== pattern.length - 1) {\n throw new Error('GcsUrlReader only supports prefix-based searches');\n }\n\n const [files] = await this.storage.bucket(bucket).getFiles({\n autoPaginate: true,\n prefix: pattern.split('*').join(''),\n });\n\n return {\n files: files.map(file => {\n const fullUrl = ['https:/', GOOGLE_GCS_HOST, bucket, file.name].join(\n '/',\n );\n return {\n url: fullUrl,\n content: async () => {\n const readResponse = await this.readUrl(fullUrl);\n return readResponse.buffer();\n },\n };\n }),\n // TODO etag is not implemented yet.\n etag: 'NOT/IMPLEMENTED',\n };\n }\n\n toString() {\n const key = this.integration.privateKey;\n return `googleGcs{host=${GOOGLE_GCS_HOST},authed=${Boolean(key)}}`;\n }\n}\n"],"names":["readGoogleGcsIntegrationConfig","GoogleCloud","packageinfo","getRawBody","ReadUrlResponseFactory","assertError"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAM,eAAA,GAAkB,0BAAA;AAExB,MAAM,QAAA,GAAW,CACf,GAAA,KACkD;AAClD,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,IAAI,IAAI,GAAG,CAAA;AAEtC,EAAA,IAAI,SAAS,eAAA,EAAiB;AAC5B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,GAAG,CAAA,CAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,GAAG,MAAA,EAAQ,GAAG,GAAG,CAAA,GAAI,QAAA,CAAS,MAAM,GAAG,CAAA;AAC7C,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAA,EAAK,GAAA,CAAI,IAAA,CAAK,GAAG;AAAA,GACnB;AACF,CAAA;AAOO,MAAM,kBAAA,CAA+C;AAAA,EAC1D,OAAO,OAAA,GAAyB,CAAC,EAAE,MAAA,EAAQ,QAAO,KAAM;AACtD,IAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,wBAAwB,CAAA,EAAG;AACzC,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,SAAA,GAAYA,0CAAA;AAAA,MAChB,MAAA,CAAO,UAAU,wBAAwB;AAAA,KAC3C;AACA,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,CAAC,SAAA,CAAU,WAAA,IAAe,CAAC,UAAU,UAAA,EAAY;AACnD,MAAA,MAAA,CAAO,IAAA;AAAA,QACL;AAAA,OACF;AACA,MAAA,OAAA,GAAU,IAAIC,uBAAY,OAAA,CAAQ;AAAA,QAChC,SAAA,EAAW,CAAA,8CAAA,EAAiDC,gBAAA,CAAY,OAAO,CAAA;AAAA,OAChF,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,OAAA,GAAU,IAAID,uBAAY,OAAA,CAAQ;AAAA,QAChC,WAAA,EAAa;AAAA,UACX,YAAA,EAAc,UAAU,WAAA,IAAe,MAAA;AAAA,UACvC,WAAA,EAAa,UAAU,UAAA,IAAc;AAAA,SACvC;AAAA,QACA,SAAA,EAAW,CAAA,8CAAA,EAAiDC,gBAAA,CAAY,OAAO,CAAA;AAAA,OAChF,CAAA;AAAA,IACH;AACA,IAAA,MAAM,MAAA,GAAS,IAAI,kBAAA,CAAmB,SAAA,EAAW,OAAO,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,CAAC,GAAA,KAAa,GAAA,CAAI,IAAA,KAAS,eAAA;AAC7C,IAAA,OAAO,CAAC,EAAE,MAAA,EAAQ,SAAA,EAAW,CAAA;AAAA,EAC/B,CAAA;AAAA,EAEiB,WAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CACE,aACA,OAAA,EACA;AACA,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AACnB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEQ,kBAAkB,GAAA,EAAuB;AAC/C,IAAA,MAAM,EAAE,MAAA,EAAQ,GAAA,EAAI,GAAI,SAAS,GAAG,CAAA;AACpC,IAAA,OAAO,IAAA,CAAK,QAAQ,MAAA,CAAO,MAAM,EAAE,IAAA,CAAK,GAAG,EAAE,gBAAA,EAAiB;AAAA,EAChE;AAAA,EAEA,MAAM,KAAK,GAAA,EAA8B;AACvC,IAAA,IAAI;AACF,MAAA,OAAO,MAAMC,2BAAA,CAAW,IAAA,CAAK,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,IACrD,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6BAAA,EAAgC,GAAG,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAM,OAAA,CACJ,GAAA,EACA,QAAA,EAC0C;AAE1C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,iBAAA,CAAkB,GAAG,CAAA;AACzC,IAAA,OAAOC,6CAAA,CAAuB,aAAa,MAAM,CAAA;AAAA,EACnD;AAAA,EAEA,MAAM,QAAA,GAAsD;AAC1D,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAAA,EAEA,MAAM,MAAA,CACJ,GAAA,EACA,OAAA,EACyC;AACzC,IAAA,MAAM,EAAE,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAQ,GAAI,SAAS,GAAG,CAAA;AAG7C,IAAA,IAAI,CAAC,OAAA,EAAS,KAAA,CAAM,MAAM,CAAA,EAAG;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAE5C,QAAA,OAAO;AAAA,UACL,KAAA,EAAO;AAAA,YACL;AAAA,cACE,GAAA;AAAA,cACA,SAAS,IAAA,CAAK,MAAA;AAAA,cACd,gBAAgB,IAAA,CAAK;AAAA;AACvB,WACF;AAAA,UACA,IAAA,EAAM,KAAK,IAAA,IAAQ;AAAA,SACrB;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAAC,kBAAA,CAAY,KAAK,CAAA;AACjB,QAAA,IAAI,KAAA,CAAM,SAAS,eAAA,EAAiB;AAClC,UAAA,OAAO;AAAA,YACL,OAAO,EAAC;AAAA,YACR,IAAA,EAAM;AAAA,WACR;AAAA,QACF;AACA,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,IAAK,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA,KAAM,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACzE,MAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,IACpE;AAEA,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,KAAK,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,CAAE,QAAA,CAAS;AAAA,MACzD,YAAA,EAAc,IAAA;AAAA,MACd,QAAQ,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,KAAK,EAAE;AAAA,KACnC,CAAA;AAED,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,KAAQ;AACvB,QAAA,MAAM,UAAU,CAAC,SAAA,EAAW,iBAAiB,MAAA,EAAQ,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA;AAAA,UAC9D;AAAA,SACF;AACA,QAAA,OAAO;AAAA,UACL,GAAA,EAAK,OAAA;AAAA,UACL,SAAS,YAAY;AACnB,YAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AAC/C,YAAA,OAAO,aAAa,MAAA,EAAO;AAAA,UAC7B;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAAA;AAAA,MAED,IAAA,EAAM;AAAA,KACR;AAAA,EACF;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,MAAM,GAAA,GAAM,KAAK,WAAA,CAAY,UAAA;AAC7B,IAAA,OAAO,CAAA,eAAA,EAAkB,eAAe,CAAA,QAAA,EAAW,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAA,CAAA;AAAA,EACjE;AACF;;;;"}
1
+ {"version":3,"file":"GoogleGcsUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as GoogleCloud from '@google-cloud/storage';\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport getRawBody from 'raw-body';\nimport {\n GoogleGcsIntegrationConfig,\n readGoogleGcsIntegrationConfig,\n} from '@backstage/integration';\n\nimport { Readable } from 'stream';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport packageinfo from '../../../../package.json';\nimport { assertError } from '@backstage/errors';\nimport { relative } from 'path/posix';\n\nconst GOOGLE_GCS_HOST = 'storage.cloud.google.com';\n\nconst parseURL = (\n url: string,\n): { host: string; bucket: string; key: string } => {\n const { host, pathname } = new URL(url);\n\n if (host !== GOOGLE_GCS_HOST) {\n throw new Error(`not a valid GCS URL: ${url}`);\n }\n\n const [, bucket, ...key] = pathname.split('/');\n return {\n host: host,\n bucket,\n key: key.join('/'),\n };\n};\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files on Google GCS.\n *\n * @public\n */\nexport class GoogleGcsUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, logger, treeResponseFactory }) => {\n if (!config.has('integrations.googleGcs')) {\n return [];\n }\n const gcsConfig = readGoogleGcsIntegrationConfig(\n config.getConfig('integrations.googleGcs'),\n );\n let storage: GoogleCloud.Storage;\n if (!gcsConfig.clientEmail || !gcsConfig.privateKey) {\n logger.info(\n 'googleGcs credentials not found in config. Using default credentials provider.',\n );\n storage = new GoogleCloud.Storage({\n userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`,\n });\n } else {\n storage = new GoogleCloud.Storage({\n credentials: {\n client_email: gcsConfig.clientEmail || undefined,\n private_key: gcsConfig.privateKey || undefined,\n },\n userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`,\n });\n }\n const reader = new GoogleGcsUrlReader(gcsConfig, storage, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => url.host === GOOGLE_GCS_HOST;\n return [{ reader, predicate }];\n };\n\n private readonly integration: GoogleGcsIntegrationConfig;\n private readonly storage: GoogleCloud.Storage;\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n };\n\n constructor(\n integration: GoogleGcsIntegrationConfig,\n storage: GoogleCloud.Storage,\n deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {\n this.integration = integration;\n this.storage = storage;\n this.deps = deps;\n }\n\n private readStreamFromUrl(url: string): Readable {\n const { bucket, key } = parseURL(url);\n return this.storage.bucket(bucket).file(key).createReadStream();\n }\n\n async read(url: string): Promise<Buffer> {\n try {\n return await getRawBody(this.readStreamFromUrl(url));\n } catch (error) {\n throw new Error(`unable to read gcs file from ${url}, ${error}`);\n }\n }\n\n async readUrl(\n url: string,\n _options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // TODO etag is not implemented yet.\n const stream = this.readStreamFromUrl(url);\n return ReadUrlResponseFactory.fromReadable(stream);\n }\n\n async readTree(\n url: string,\n _options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const { bucket, key } = parseURL(url);\n\n if (key.match(/[*?]/)) {\n throw new Error(\n 'GcsUrlReader readTree does not support glob patterns, use search instead',\n );\n }\n\n const [files] = await this.storage.bucket(bucket).getFiles({\n autoPaginate: true,\n prefix: key,\n });\n\n const responses = files.map(file => ({\n data: file.createReadStream(),\n path: relative(key, file.name),\n lastModifiedAt: file.metadata.updated\n ? new Date(file.metadata.updated as string)\n : undefined,\n }));\n\n return this.deps.treeResponseFactory.fromReadableArray(responses);\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { bucket, key: pattern } = parseURL(url);\n\n // If it's a direct URL we use readUrl instead\n if (!pattern?.match(/[*?]/)) {\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n if (!pattern.endsWith('*') || pattern.indexOf('*') !== pattern.length - 1) {\n throw new Error('GcsUrlReader only supports prefix-based searches');\n }\n\n const [files] = await this.storage.bucket(bucket).getFiles({\n autoPaginate: true,\n prefix: pattern.split('*').join(''),\n });\n\n return {\n files: files.map(file => {\n const fullUrl = ['https:/', GOOGLE_GCS_HOST, bucket, file.name].join(\n '/',\n );\n return {\n url: fullUrl,\n content: async () => {\n const readResponse = await this.readUrl(fullUrl);\n return readResponse.buffer();\n },\n };\n }),\n // TODO etag is not implemented yet.\n etag: 'NOT/IMPLEMENTED',\n };\n }\n\n toString() {\n const key = this.integration.privateKey;\n return `googleGcs{host=${GOOGLE_GCS_HOST},authed=${Boolean(key)}}`;\n }\n}\n"],"names":["readGoogleGcsIntegrationConfig","GoogleCloud","packageinfo","getRawBody","ReadUrlResponseFactory","relative","assertError"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "0.14.0";
5
+ var version = "0.14.1-next.1";
6
6
  var packageinfo = {
7
7
  version: version};
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-defaults",
3
- "version": "0.14.0",
3
+ "version": "0.14.1-next.1",
4
4
  "description": "Backend defaults used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -216,19 +216,19 @@
216
216
  "@aws-sdk/credential-providers": "^3.350.0",
217
217
  "@aws-sdk/types": "^3.347.0",
218
218
  "@azure/storage-blob": "^12.5.0",
219
- "@backstage/backend-app-api": "^1.4.0",
220
- "@backstage/backend-dev-utils": "^0.1.6",
221
- "@backstage/backend-plugin-api": "^1.6.0",
222
- "@backstage/cli-node": "^0.2.16",
223
- "@backstage/config": "^1.3.6",
224
- "@backstage/config-loader": "^1.10.7",
225
- "@backstage/errors": "^1.2.7",
226
- "@backstage/integration": "^1.19.0",
227
- "@backstage/integration-aws-node": "^0.1.19",
228
- "@backstage/plugin-auth-node": "^0.6.10",
229
- "@backstage/plugin-events-node": "^0.4.18",
230
- "@backstage/plugin-permission-node": "^0.10.7",
231
- "@backstage/types": "^1.2.2",
219
+ "@backstage/backend-app-api": "1.4.0",
220
+ "@backstage/backend-dev-utils": "0.1.6",
221
+ "@backstage/backend-plugin-api": "1.6.0",
222
+ "@backstage/cli-node": "0.2.16",
223
+ "@backstage/config": "1.3.6",
224
+ "@backstage/config-loader": "1.10.7",
225
+ "@backstage/errors": "1.2.7",
226
+ "@backstage/integration": "1.19.2-next.0",
227
+ "@backstage/integration-aws-node": "0.1.19",
228
+ "@backstage/plugin-auth-node": "0.6.10",
229
+ "@backstage/plugin-events-node": "0.4.18",
230
+ "@backstage/plugin-permission-node": "0.10.7",
231
+ "@backstage/types": "1.2.2",
232
232
  "@google-cloud/storage": "^7.0.0",
233
233
  "@keyv/memcache": "^2.0.1",
234
234
  "@keyv/redis": "^4.0.1",
@@ -283,9 +283,9 @@
283
283
  },
284
284
  "devDependencies": {
285
285
  "@aws-sdk/util-stream-node": "^3.350.0",
286
- "@backstage/backend-plugin-api": "^1.6.0",
287
- "@backstage/backend-test-utils": "^1.10.2",
288
- "@backstage/cli": "^0.35.0",
286
+ "@backstage/backend-plugin-api": "1.6.0",
287
+ "@backstage/backend-test-utils": "1.10.3-next.0",
288
+ "@backstage/cli": "0.35.2-next.1",
289
289
  "@google-cloud/cloud-sql-connector": "^1.4.0",
290
290
  "@types/archiver": "^7.0.0",
291
291
  "@types/base64-stream": "^1.0.2",