diff --git a/.changeset/tasty-rabbits-wave.md b/.changeset/tasty-rabbits-wave.md new file mode 100644 index 00000000..9072ee46 --- /dev/null +++ b/.changeset/tasty-rabbits-wave.md @@ -0,0 +1,5 @@ +--- +"@reflag/node-sdk": patch +--- + +Replace the built-in GCS fallback provider's default client dependency with `@googleapis/storage`, removing the deprecated `@google-cloud/storage` dependency and its vulnerable transitive request stack. diff --git a/packages/node-sdk/package.json b/packages/node-sdk/package.json index 45ae5246..b28c9265 100644 --- a/packages/node-sdk/package.json +++ b/packages/node-sdk/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@aws-sdk/client-s3": "^3.888.0", - "@google-cloud/storage": "^7.19.0", + "@googleapis/storage": "21.2.0", "@redis/client": "^5.11.0", "@reflag/flag-evaluation": "1.0.0" }, diff --git a/packages/node-sdk/src/flagsFallbackProvider.ts b/packages/node-sdk/src/flagsFallbackProvider.ts index 0bb72876..d373d1f1 100644 --- a/packages/node-sdk/src/flagsFallbackProvider.ts +++ b/packages/node-sdk/src/flagsFallbackProvider.ts @@ -39,6 +39,44 @@ export type S3FallbackProviderOptions = { keyPrefix?: string; }; +export type GCSLegacyClient = { + bucket(name: string): { + file(path: string): { + exists(): Promise<[boolean]>; + download(): Promise<[Uint8Array]>; + save(body: string, options: { contentType: string }): Promise; + }; + }; +}; + +export type GCSGoogleApisClient = { + objects: { + get( + params: { + bucket: string; + object: string; + alt?: string; + }, + options?: { + responseType?: "arraybuffer"; + }, + ): Promise<{ + data: unknown; + }>; + insert(params: { + bucket: string; + name: string; + uploadType: "media"; + media: { + mimeType: string; + body: string; + }; + }): Promise; + }; +}; + +export type GCSFallbackProviderClient = GCSLegacyClient | GCSGoogleApisClient; + export type GCSFallbackProviderOptions = { /** * Bucket where snapshots are stored. @@ -47,16 +85,13 @@ export type GCSFallbackProviderOptions = { /** * Optional GCS client. A default client is created when omitted. + * + * Accepts either a legacy `bucket().file()` client or a generated + * `@googleapis/storage` client. + * + * TODO(next major): Replace this with a simpler object-store interface. */ - client?: { - bucket(name: string): { - file(path: string): { - exists(): Promise<[boolean]>; - download(): Promise<[Uint8Array]>; - save(body: string, options: { contentType: string }): Promise; - }; - }; - }; + client?: GCSFallbackProviderClient; /** * Prefix for generated per-environment keys. @@ -66,6 +101,17 @@ export type GCSFallbackProviderOptions = { keyPrefix?: string; }; +type GCSObjectStore = { + exists(bucket: string, objectPath: string): Promise; + download(bucket: string, objectPath: string): Promise; + save( + bucket: string, + objectPath: string, + body: string, + options: { contentType: string }, + ): Promise; +}; + export type RedisFallbackProviderOptions = { /** * Optional Redis client. When omitted, a client is created using `REDIS_URL`. @@ -153,6 +199,12 @@ function isFlagApiResponse(value: unknown): value is FlagAPIResponse { async function readBodyAsString(body: unknown) { if (typeof body === "string") return body; if (body instanceof Uint8Array) return Buffer.from(body).toString("utf-8"); + if (body instanceof ArrayBuffer) return Buffer.from(body).toString("utf-8"); + if (ArrayBuffer.isView(body)) { + return Buffer.from(body.buffer, body.byteOffset, body.byteLength).toString( + "utf-8", + ); + } if (body && typeof body === "object") { if ( "transformToString" in body && @@ -169,6 +221,15 @@ function parseSnapshot(raw: string) { return isFlagsFallbackSnapshot(parsed) ? parsed : undefined; } +function isNotFoundError(error: any) { + return ( + error?.code === 404 || + error?.status === 404 || + error?.response?.status === 404 || + error?.$metadata?.httpStatusCode === 404 + ); +} + function staticFlagApiResponse( key: string, isEnabled: boolean, @@ -195,9 +256,113 @@ async function createDefaultS3Client() { return new S3Client({}); } -async function createDefaultGCSClient() { - const { Storage } = await import("@google-cloud/storage"); - return new Storage(); +function createLegacyGCSObjectStore(client: GCSLegacyClient): GCSObjectStore { + return { + async exists(bucket, objectPath) { + const [exists] = await client.bucket(bucket).file(objectPath).exists(); + return exists; + }, + + async download(bucket, objectPath) { + const [contents] = await client + .bucket(bucket) + .file(objectPath) + .download(); + return contents; + }, + + async save(bucket, objectPath, body, options) { + return client.bucket(bucket).file(objectPath).save(body, options); + }, + }; +} + +function createGoogleApisGCSObjectStore( + client: GCSGoogleApisClient, +): GCSObjectStore { + return { + async exists(bucket, objectPath) { + try { + await client.objects.get({ + bucket, + object: objectPath, + }); + return true; + } catch (error) { + if (isNotFoundError(error)) { + return false; + } + throw error; + } + }, + + async download(bucket, objectPath) { + const response = await client.objects.get( + { + bucket, + object: objectPath, + alt: "media", + }, + { + responseType: "arraybuffer", + }, + ); + + if (response.data instanceof Uint8Array) { + return response.data; + } + if (response.data instanceof ArrayBuffer) { + return new Uint8Array(response.data); + } + + throw new TypeError("Unexpected GCS download response body format"); + }, + + async save(bucket, objectPath, body, options) { + await client.objects.insert({ + bucket, + name: objectPath, + uploadType: "media", + media: { + mimeType: options.contentType, + body, + }, + }); + }, + }; +} + +function isGoogleApisGCSClient( + client: GCSFallbackProviderClient, +): client is GCSGoogleApisClient { + return ( + "objects" in client && + isObject(client.objects) && + typeof client.objects.get === "function" && + typeof client.objects.insert === "function" + ); +} + +function createGCSObjectStore( + client: GCSFallbackProviderClient, +): GCSObjectStore { + if (isGoogleApisGCSClient(client)) { + return createGoogleApisGCSObjectStore(client); + } + + return createLegacyGCSObjectStore(client); +} + +async function createDefaultGCSObjectStore(): Promise { + const { auth, storage } = await import("@googleapis/storage"); + return createGoogleApisGCSObjectStore( + storage({ + version: "v1", + auth: new auth.GoogleAuth({ + scopes: ["https://www.googleapis.com/auth/devstorage.read_write"], + }), + }), + ); } export function createStaticFallbackProvider({ @@ -281,10 +446,7 @@ export function createS3FallbackProvider({ return parseSnapshot(body); } catch (error: any) { - if ( - error?.name === "NoSuchKey" || - error?.$metadata?.httpStatusCode === 404 - ) { + if (error?.name === "NoSuchKey" || isNotFoundError(error)) { return undefined; } throw error; @@ -312,36 +474,38 @@ export function createGCSFallbackProvider({ client, keyPrefix, }: GCSFallbackProviderOptions): FlagsFallbackProvider { - let defaultClient: GCSFallbackProviderOptions["client"] | undefined; + let defaultClient: GCSObjectStore | undefined; const getClient = async () => { - defaultClient ??= client ?? (await createDefaultGCSClient()); + defaultClient ??= client + ? createGCSObjectStore(client) + : await createDefaultGCSObjectStore(); return defaultClient; }; return { async load(context) { const storage = await getClient(); - const file = storage - .bucket(bucket) - .file(snapshotObjectKey(context, keyPrefix)); - const [exists] = await file.exists(); + const objectKey = snapshotObjectKey(context, keyPrefix); + const exists = await storage.exists(bucket, objectKey); if (!exists) { return undefined; } - const [contents] = await file.download(); + const contents = await storage.download(bucket, objectKey); return parseSnapshot(Buffer.from(contents).toString("utf-8")); }, async save(context, snapshot) { const storage = await getClient(); - await storage - .bucket(bucket) - .file(snapshotObjectKey(context, keyPrefix)) - .save(JSON.stringify(snapshot), { + await storage.save( + bucket, + snapshotObjectKey(context, keyPrefix), + JSON.stringify(snapshot), + { contentType: "application/json", - }); + }, + ); }, }; } diff --git a/packages/node-sdk/src/index.ts b/packages/node-sdk/src/index.ts index 1d78d058..e6bcd752 100644 --- a/packages/node-sdk/src/index.ts +++ b/packages/node-sdk/src/index.ts @@ -10,7 +10,10 @@ export { BoundReflagClient, ReflagClient } from "./client"; export { EdgeClient, EdgeClientOptions } from "./edgeClient"; export type { FileFallbackProviderOptions, + GCSFallbackProviderClient, GCSFallbackProviderOptions, + GCSGoogleApisClient, + GCSLegacyClient, RedisFallbackProviderOptions, S3FallbackProviderOptions, StaticFallbackProviderOptions, diff --git a/packages/node-sdk/test/flagsFallbackProvider.test.ts b/packages/node-sdk/test/flagsFallbackProvider.test.ts index 4c42af7f..f94429ff 100644 --- a/packages/node-sdk/test/flagsFallbackProvider.test.ts +++ b/packages/node-sdk/test/flagsFallbackProvider.test.ts @@ -242,6 +242,127 @@ describe("flagsFallbackProvider", () => { }); }); + it("accepts a provided @googleapis/storage client", async () => { + const get = vi + .fn() + .mockResolvedValueOnce({ data: { kind: "storage#object" } }) + .mockResolvedValueOnce({ + data: Buffer.from(JSON.stringify(snapshot), "utf-8"), + }); + const insert = vi.fn().mockResolvedValue({}); + + const provider = fallbackProviders.gcs({ + bucket: "bucket-name", + client: { + objects: { + get, + insert, + }, + }, + keyPrefix: "reflag/flags-fallback///", + }); + + await expect(provider.load(context)).resolves.toEqual(snapshot); + await provider.save(context, snapshot); + + expect(get).toHaveBeenNthCalledWith(1, { + bucket: "bucket-name", + object: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + }); + expect(get).toHaveBeenNthCalledWith( + 2, + { + bucket: "bucket-name", + object: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + alt: "media", + }, + { + responseType: "arraybuffer", + }, + ); + expect(insert).toHaveBeenCalledWith({ + bucket: "bucket-name", + name: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + uploadType: "media", + media: { + mimeType: "application/json", + body: JSON.stringify(snapshot), + }, + }); + }); + + it("creates the default GCS client from @googleapis/storage", async () => { + vi.resetModules(); + + const get = vi + .fn() + .mockResolvedValueOnce({ data: { kind: "storage#object" } }) + .mockResolvedValueOnce({ + data: Buffer.from(JSON.stringify(snapshot), "utf-8"), + }); + const insert = vi.fn().mockResolvedValue({}); + const storage = vi.fn().mockReturnValue({ + objects: { + get, + insert, + }, + }); + const GoogleAuth = vi.fn(); + + vi.doMock("@googleapis/storage", () => ({ + auth: { GoogleAuth }, + storage, + })); + + try { + const { createGCSFallbackProvider } = + await import("../src/flagsFallbackProvider"); + const provider = createGCSFallbackProvider({ + bucket: "bucket-name", + keyPrefix: "reflag/flags-fallback///", + }); + + await expect(provider.load(context)).resolves.toEqual(snapshot); + await provider.save(context, snapshot); + + expect(GoogleAuth).toHaveBeenCalledWith({ + scopes: ["https://www.googleapis.com/auth/devstorage.read_write"], + }); + expect(storage).toHaveBeenCalledWith( + expect.objectContaining({ + version: "v1", + }), + ); + expect(get).toHaveBeenNthCalledWith(1, { + bucket: "bucket-name", + object: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + }); + expect(get).toHaveBeenNthCalledWith( + 2, + { + bucket: "bucket-name", + object: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + alt: "media", + }, + { + responseType: "arraybuffer", + }, + ); + expect(insert).toHaveBeenCalledWith({ + bucket: "bucket-name", + name: `reflag/flags-fallback/flags-fallback-${context.secretKeyHash.slice(0, 16)}.json`, + uploadType: "media", + media: { + mimeType: "application/json", + body: JSON.stringify(snapshot), + }, + }); + } finally { + vi.doUnmock("@googleapis/storage"); + vi.resetModules(); + } + }); + it("loads Redis snapshots", async () => { const get = vi.fn().mockResolvedValue(JSON.stringify(snapshot)); const set = vi.fn(); diff --git a/yarn.lock b/yarn.lock index 7b407588..dd1379df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4158,50 +4158,12 @@ __metadata: languageName: node linkType: hard -"@google-cloud/paginator@npm:^5.0.0": - version: 5.0.2 - resolution: "@google-cloud/paginator@npm:5.0.2" - dependencies: - arrify: "npm:^2.0.0" - extend: "npm:^3.0.2" - checksum: 10c0/aac4ed986c2b274ac9fdca3f68d5ba6ee95f4c35370b11db25c288bf485352e2ec5df16bf9c3cff554a2e73a07e62f10044d273788df61897b81fe47bb18106d - languageName: node - linkType: hard - -"@google-cloud/projectify@npm:^4.0.0": - version: 4.0.0 - resolution: "@google-cloud/projectify@npm:4.0.0" - checksum: 10c0/0d0a6ceca76a138973fcb3ad577f209acdbd9d9aed1c645b09f98d5e5a258053dbbe6c1f13e6f85310cc0d9308f5f3a84f8fa4f1a132549a68d86174fb21067f - languageName: node - linkType: hard - -"@google-cloud/promisify@npm:<4.1.0": - version: 4.0.0 - resolution: "@google-cloud/promisify@npm:4.0.0" - checksum: 10c0/4332cbd923d7c6943ecdf46f187f1417c84bb9c801525cd74d719c766bfaad650f7964fb74576345f6537b6d6273a4f2992c8d79ebec6c8b8401b23d626b8dd3 - languageName: node - linkType: hard - -"@google-cloud/storage@npm:^7.19.0": - version: 7.19.0 - resolution: "@google-cloud/storage@npm:7.19.0" +"@googleapis/storage@npm:21.2.0": + version: 21.2.0 + resolution: "@googleapis/storage@npm:21.2.0" dependencies: - "@google-cloud/paginator": "npm:^5.0.0" - "@google-cloud/projectify": "npm:^4.0.0" - "@google-cloud/promisify": "npm:<4.1.0" - abort-controller: "npm:^3.0.0" - async-retry: "npm:^1.3.3" - duplexify: "npm:^4.1.3" - fast-xml-parser: "npm:^5.3.4" - gaxios: "npm:^6.0.2" - google-auth-library: "npm:^9.6.3" - html-entities: "npm:^2.5.2" - mime: "npm:^3.0.0" - p-limit: "npm:^3.0.1" - retry-request: "npm:^7.0.0" - teeny-request: "npm:^9.0.0" - uuid: "npm:^8.0.0" - checksum: 10c0/2951e4a0b3c2f90c28917a9b313a981722a9e5648ca2b6d04f384f816e9107e1637b00c32c5e71ed8d25c7e1840898b616f015b29c2cc1d8d8a22c8630778d8c + googleapis-common: "npm:^8.0.0" + checksum: 10c0/ff7e758d4a14e19ae05343d80994e91a09ad82be3ab42cc903b123b30e7e57a78e7c54c7eb21398f015216d82968a60f674f5f5db0776433b31912ecd5beb023 languageName: node linkType: hard @@ -6993,7 +6955,7 @@ __metadata: dependencies: "@aws-sdk/client-s3": "npm:^3.888.0" "@babel/core": "npm:~7.24.7" - "@google-cloud/storage": "npm:^7.19.0" + "@googleapis/storage": "npm:21.2.0" "@redis/client": "npm:^5.11.0" "@reflag/flag-evaluation": "npm:1.0.0" "@reflag/tsconfig": "npm:~0.0.2" @@ -8517,13 +8479,6 @@ __metadata: languageName: node linkType: hard -"@types/caseless@npm:*": - version: 0.12.5 - resolution: "@types/caseless@npm:0.12.5" - checksum: 10c0/b1f8b8a38ce747b643115d37a40ea824c658bd7050e4b69427a10e9d12d1606ed17a0f6018241c08291cd59f70aeb3c1f3754ad61e45f8dbba708ec72dde7ec8 - languageName: node - linkType: hard - "@types/connect@npm:*": version: 3.4.38 resolution: "@types/connect@npm:3.4.38" @@ -8859,18 +8814,6 @@ __metadata: languageName: node linkType: hard -"@types/request@npm:^2.48.8": - version: 2.48.13 - resolution: "@types/request@npm:2.48.13" - dependencies: - "@types/caseless": "npm:*" - "@types/node": "npm:*" - "@types/tough-cookie": "npm:*" - form-data: "npm:^2.5.5" - checksum: 10c0/1c6798d926a6577f213dbc04aa09945590f260ea367537c20824ff337b0a49d56e5199a6a6029e625568d97c3bbb98908bdb8d9158eb421f70a0d03ae230ff72 - languageName: node - linkType: hard - "@types/semver@npm:^7.7.0": version: 7.7.0 resolution: "@types/semver@npm:7.7.0" @@ -10406,7 +10349,7 @@ __metadata: languageName: node linkType: hard -"arrify@npm:^2.0.0, arrify@npm:^2.0.1": +"arrify@npm:^2.0.1": version: 2.0.1 resolution: "arrify@npm:2.0.1" checksum: 10c0/3fb30b5e7c37abea1907a60b28a554d2f0fc088757ca9bf5b684786e583fdf14360721eb12575c1ce6f995282eab936712d3c4389122682eafab0e0b57f78dbb @@ -10457,15 +10400,6 @@ __metadata: languageName: node linkType: hard -"async-retry@npm:^1.3.3": - version: 1.3.3 - resolution: "async-retry@npm:1.3.3" - dependencies: - retry: "npm:0.13.1" - checksum: 10c0/cabced4fb46f8737b95cc88dc9c0ff42656c62dc83ce0650864e891b6c155a063af08d62c446269b51256f6fbcb69a6563b80e76d0ea4a5117b0c0377b6b19d8 - languageName: node - linkType: hard - "async@npm:^2.6.4": version: 2.6.4 resolution: "async@npm:2.6.4" @@ -12274,6 +12208,13 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^4.0.0": + version: 4.0.1 + resolution: "data-uri-to-buffer@npm:4.0.1" + checksum: 10c0/20a6b93107597530d71d4cb285acee17f66bcdfc03fd81040921a81252f19db27588d87fc8fc69e1950c55cfb0bf8ae40d0e5e21d907230813eb5d5a7f9eb45b + languageName: node + linkType: hard + "data-uri-to-buffer@npm:^6.0.2": version: 6.0.2 resolution: "data-uri-to-buffer@npm:6.0.2" @@ -12694,18 +12635,6 @@ __metadata: languageName: node linkType: hard -"duplexify@npm:^4.1.3": - version: 4.1.3 - resolution: "duplexify@npm:4.1.3" - dependencies: - end-of-stream: "npm:^1.4.1" - inherits: "npm:^2.0.3" - readable-stream: "npm:^3.1.1" - stream-shift: "npm:^1.0.2" - checksum: 10c0/8a7621ae95c89f3937f982fe36d72ea997836a708471a75bb2a0eecde3330311b1e128a6dad510e0fd64ace0c56bff3484ed2e82af0e465600c82117eadfbda5 - languageName: node - linkType: hard - "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -13932,15 +13861,6 @@ __metadata: languageName: node linkType: hard -"fast-xml-builder@npm:^1.1.3": - version: 1.1.3 - resolution: "fast-xml-builder@npm:1.1.3" - dependencies: - path-expression-matcher: "npm:^1.1.3" - checksum: 10c0/353a2b3695f66f2b0717fcb1a59d2c4108a3b29e7e4f125a51accaccade509dc6fb7e2777da62fb3b339487753ece01eaa270542b10a68dfd43f48d607a6b10e - languageName: node - linkType: hard - "fast-xml-parser@npm:5.4.1": version: 5.4.1 resolution: "fast-xml-parser@npm:5.4.1" @@ -13964,19 +13884,6 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:^5.3.4": - version: 5.5.5 - resolution: "fast-xml-parser@npm:5.5.5" - dependencies: - fast-xml-builder: "npm:^1.1.3" - path-expression-matcher: "npm:^1.1.3" - strnum: "npm:^2.1.2" - bin: - fxparser: src/cli/cli.js - checksum: 10c0/d159b331e7c3ea27e388ece304988f8dc57e8cbd9d91f4ab824c78c1ed7915f10b77032ec72ed4a9ddb872db4261b5ee0699d2b6a4a80e06dfc95174dde35e93 - languageName: node - linkType: hard - "fastest-levenshtein@npm:^1.0.12": version: 1.0.12 resolution: "fastest-levenshtein@npm:1.0.12" @@ -14026,6 +13933,16 @@ __metadata: languageName: node linkType: hard +"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": + version: 3.2.0 + resolution: "fetch-blob@npm:3.2.0" + dependencies: + node-domexception: "npm:^1.0.0" + web-streams-polyfill: "npm:^3.0.3" + checksum: 10c0/60054bf47bfa10fb0ba6cb7742acec2f37c1f56344f79a70bb8b1c48d77675927c720ff3191fa546410a0442c998d27ab05e9144c32d530d8a52fbe68f843b69 + languageName: node + linkType: hard + "figures@npm:3.2.0, figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -14220,20 +14137,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^2.5.5": - version: 2.5.5 - resolution: "form-data@npm:2.5.5" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - hasown: "npm:^2.0.2" - mime-types: "npm:^2.1.35" - safe-buffer: "npm:^5.2.1" - checksum: 10c0/7fb70447849fc9bce4d01fe9a626f6587441f85779a2803b67f803e1ab52b0bd78db0a7acd80d944c665f68ca90936c327f1244b730719b638a0219e98b20488 - languageName: node - linkType: hard - "form-data@npm:^4.0.0": version: 4.0.4 resolution: "form-data@npm:4.0.4" @@ -14260,6 +14163,15 @@ __metadata: languageName: node linkType: hard +"formdata-polyfill@npm:^4.0.10": + version: 4.0.10 + resolution: "formdata-polyfill@npm:4.0.10" + dependencies: + fetch-blob: "npm:^3.1.2" + checksum: 10c0/5392ec484f9ce0d5e0d52fb5a78e7486637d516179b0eb84d81389d7eccf9ca2f663079da56f761355c0a65792810e3b345dc24db9a8bbbcf24ef3c8c88570c6 + languageName: node + linkType: hard + "formidable@npm:^3.5.4": version: 3.5.4 resolution: "formidable@npm:3.5.4" @@ -14454,27 +14366,25 @@ __metadata: languageName: node linkType: hard -"gaxios@npm:^6.0.0, gaxios@npm:^6.0.2, gaxios@npm:^6.1.1": - version: 6.7.1 - resolution: "gaxios@npm:6.7.1" +"gaxios@npm:^7.0.0, gaxios@npm:^7.0.0-rc.4, gaxios@npm:^7.1.4": + version: 7.1.4 + resolution: "gaxios@npm:7.1.4" dependencies: extend: "npm:^3.0.2" https-proxy-agent: "npm:^7.0.1" - is-stream: "npm:^2.0.0" - node-fetch: "npm:^2.6.9" - uuid: "npm:^9.0.1" - checksum: 10c0/53e92088470661c5bc493a1de29d05aff58b1f0009ec5e7903f730f892c3642a93e264e61904383741ccbab1ce6e519f12a985bba91e13527678b32ee6d7d3fd + node-fetch: "npm:^3.3.2" + checksum: 10c0/147adf5f2606442945d8b19df1e9fe2833a5ec30af00743d0c44292899c5eef1c0a77b74ff07d9dfdc6b009c08af1f3f3d1d5d772109fde50c92435533795803 languageName: node linkType: hard -"gcp-metadata@npm:^6.1.0": - version: 6.1.1 - resolution: "gcp-metadata@npm:6.1.1" +"gcp-metadata@npm:8.1.2": + version: 8.1.2 + resolution: "gcp-metadata@npm:8.1.2" dependencies: - gaxios: "npm:^6.1.1" - google-logging-utils: "npm:^0.0.2" + gaxios: "npm:^7.0.0" + google-logging-utils: "npm:^1.0.0" json-bigint: "npm:^1.0.0" - checksum: 10c0/71f6ad4800aa622c246ceec3955014c0c78cdcfe025971f9558b9379f4019f5e65772763428ee8c3244fa81b8631977316eaa71a823493f82e5c44d7259ffac8 + checksum: 10c0/15a61231a9410dc11c2828d2c9fdc8b0a939f1af746195c44edc6f2ffea0acab52cef3a7b9828069a36fd5d68bda730f7328a415fe42a01258f6e249dfba6908 languageName: node linkType: hard @@ -14873,24 +14783,37 @@ __metadata: languageName: node linkType: hard -"google-auth-library@npm:^9.6.3": - version: 9.15.1 - resolution: "google-auth-library@npm:9.15.1" +"google-auth-library@npm:^10.1.0": + version: 10.6.2 + resolution: "google-auth-library@npm:10.6.2" dependencies: base64-js: "npm:^1.3.0" ecdsa-sig-formatter: "npm:^1.0.11" - gaxios: "npm:^6.1.1" - gcp-metadata: "npm:^6.1.0" - gtoken: "npm:^7.0.0" + gaxios: "npm:^7.1.4" + gcp-metadata: "npm:8.1.2" + google-logging-utils: "npm:1.1.3" jws: "npm:^4.0.0" - checksum: 10c0/6eef36d9a9cb7decd11e920ee892579261c6390104b3b24d3e0f3889096673189fe2ed0ee43fd563710e2560de98e63ad5aa4967b91e7f4e69074a422d5f7b65 + checksum: 10c0/4878d9070e751202eff8adca7a78a41f045c460f611a62d8c0c14ac4bd33d66afc5d788ef82225873dadc7cde401d47f223f3c109f1a192564164fdd44a36614 languageName: node linkType: hard -"google-logging-utils@npm:^0.0.2": - version: 0.0.2 - resolution: "google-logging-utils@npm:0.0.2" - checksum: 10c0/9a4bbd470dd101c77405e450fffca8592d1d7114f245a121288d04a957aca08c9dea2dd1a871effe71e41540d1bb0494731a0b0f6fea4358e77f06645e4268c1 +"google-logging-utils@npm:1.1.3, google-logging-utils@npm:^1.0.0": + version: 1.1.3 + resolution: "google-logging-utils@npm:1.1.3" + checksum: 10c0/e65201c7e96543bd1423b9324013736646b9eed60941e0bfa47b9bfd146d2f09cf3df1c99ca60b7d80a726075263ead049ee72de53372cb8458c3bc55c2c1e59 + languageName: node + linkType: hard + +"googleapis-common@npm:^8.0.0": + version: 8.0.1 + resolution: "googleapis-common@npm:8.0.1" + dependencies: + extend: "npm:^3.0.2" + gaxios: "npm:^7.0.0-rc.4" + google-auth-library: "npm:^10.1.0" + qs: "npm:^6.7.0" + url-template: "npm:^2.0.8" + checksum: 10c0/ee939fdfcaea32c528e7be64621b3e6b35e612f2456c8d4aca835e0a01ccec52f4ea2ac9509b083128398631a6cd66512c400adb4d0375a4638c55888ccdea7f languageName: node linkType: hard @@ -14931,16 +14854,6 @@ __metadata: languageName: node linkType: hard -"gtoken@npm:^7.0.0": - version: 7.1.0 - resolution: "gtoken@npm:7.1.0" - dependencies: - gaxios: "npm:^6.0.0" - jws: "npm:^4.0.0" - checksum: 10c0/0a3dcacb1a3c4578abe1ee01c7d0bf20bffe8ded3ee73fc58885d53c00f6eb43b4e1372ff179f0da3ed5cfebd5b7c6ab8ae2776f1787e90d943691b4fe57c716 - languageName: node - linkType: hard - "handlebars@npm:^4.7.7": version: 4.7.9 resolution: "handlebars@npm:4.7.9" @@ -15169,13 +15082,6 @@ __metadata: languageName: node linkType: hard -"html-entities@npm:^2.5.2": - version: 2.6.0 - resolution: "html-entities@npm:2.6.0" - checksum: 10c0/7c8b15d9ea0cd00dc9279f61bab002ba6ca8a7a0f3c36ed2db3530a67a9621c017830d1d2c1c65beb9b8e3436ea663e9cf8b230472e0e413359399413b27c8b7 - languageName: node - linkType: hard - "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -17647,7 +17553,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -17683,15 +17589,6 @@ __metadata: languageName: node linkType: hard -"mime@npm:^3.0.0": - version: 3.0.0 - resolution: "mime@npm:3.0.0" - bin: - mime: cli.js - checksum: 10c0/402e792a8df1b2cc41cb77f0dcc46472b7944b7ec29cb5bbcd398624b6b97096728f1239766d3fdeb20551dd8d94738344c195a6ea10c4f906eb0356323b0531 - languageName: node - linkType: hard - "mimic-fn@npm:^1.0.0": version: 1.2.0 resolution: "mimic-fn@npm:1.2.0" @@ -18556,6 +18453,13 @@ __metadata: languageName: node linkType: hard +"node-domexception@npm:^1.0.0": + version: 1.0.0 + resolution: "node-domexception@npm:1.0.0" + checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b + languageName: node + linkType: hard + "node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -18570,7 +18474,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9": +"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.7": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -18584,6 +18488,17 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^3.3.2": + version: 3.3.2 + resolution: "node-fetch@npm:3.3.2" + dependencies: + data-uri-to-buffer: "npm:^4.0.0" + fetch-blob: "npm:^3.1.4" + formdata-polyfill: "npm:^4.0.10" + checksum: 10c0/f3d5e56190562221398c9f5750198b34cf6113aa304e34ee97c94fd300ec578b25b2c2906edba922050fce983338fde0d5d34fcb0fc3336ade5bd0e429ad7538 + languageName: node + linkType: hard + "node-forge@npm:^1.3.3": version: 1.4.0 resolution: "node-forge@npm:1.4.0" @@ -19389,7 +19304,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^3.0.1, p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": +"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": version: 3.1.0 resolution: "p-limit@npm:3.1.0" dependencies: @@ -19710,13 +19625,6 @@ __metadata: languageName: node linkType: hard -"path-expression-matcher@npm:^1.1.3": - version: 1.1.3 - resolution: "path-expression-matcher@npm:1.1.3" - checksum: 10c0/45c01471bc62c5f38d069418aec831763e6f45bb85f9520b08de441e6cd14f84b3098ecb66255e819c2af21102abcd2b45550dc1285996717ce9292802df2bc5 - languageName: node - linkType: hard - "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -20778,7 +20686,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.14.1": +"qs@npm:^6.14.1, qs@npm:^6.7.0": version: 6.15.0 resolution: "qs@npm:6.15.0" dependencies: @@ -21566,24 +21474,6 @@ __metadata: languageName: node linkType: hard -"retry-request@npm:^7.0.0": - version: 7.0.2 - resolution: "retry-request@npm:7.0.2" - dependencies: - "@types/request": "npm:^2.48.8" - extend: "npm:^3.0.2" - teeny-request: "npm:^9.0.0" - checksum: 10c0/c79936695a43db1bc82a7bad348a1e0be1c363799be2e1fa87b8c3aeb5dabf0ccb023b811aa5000c000ee73e196b88febff7d3e22cbb63a77175228514256155 - languageName: node - linkType: hard - -"retry@npm:0.13.1": - version: 0.13.1 - resolution: "retry@npm:0.13.1" - checksum: 10c0/9ae822ee19db2163497e074ea919780b1efa00431d197c7afdb950e42bf109196774b92a49fc9821f0b8b328a98eea6017410bfc5e8a0fc19c85c6d11adb3772 - languageName: node - linkType: hard - "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -21797,7 +21687,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 @@ -22650,22 +22540,6 @@ __metadata: languageName: node linkType: hard -"stream-events@npm:^1.0.5": - version: 1.0.5 - resolution: "stream-events@npm:1.0.5" - dependencies: - stubs: "npm:^3.0.0" - checksum: 10c0/5d235a5799a483e94ea8829526fe9d95d76460032d5e78555fe4f801949ac6a27ea2212e4e0827c55f78726b3242701768adf2d33789465f51b31ed8ebd6b086 - languageName: node - linkType: hard - -"stream-shift@npm:^1.0.2": - version: 1.0.3 - resolution: "stream-shift@npm:1.0.3" - checksum: 10c0/939cd1051ca750d240a0625b106a2b988c45fb5a3be0cebe9a9858cb01bc1955e8c7b9fac17a9462976bea4a7b704e317c5c2200c70f0ca715a3363b9aa4fd3b - languageName: node - linkType: hard - "streamsearch@npm:^1.1.0": version: 1.1.0 resolution: "streamsearch@npm:1.1.0" @@ -22887,13 +22761,6 @@ __metadata: languageName: node linkType: hard -"stubs@npm:^3.0.0": - version: 3.0.0 - resolution: "stubs@npm:3.0.0" - checksum: 10c0/841a4ab8c76795d34aefe129185763b55fbf2e4693208215627caea4dd62e1299423dcd96f708d3128e3dfa0e669bae2cb912e6e906d7d81eaf6493196570923 - languageName: node - linkType: hard - "styled-jsx@npm:5.1.1": version: 5.1.1 resolution: "styled-jsx@npm:5.1.1" @@ -23128,19 +22995,6 @@ __metadata: languageName: node linkType: hard -"teeny-request@npm:^9.0.0": - version: 9.0.0 - resolution: "teeny-request@npm:9.0.0" - dependencies: - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.0" - node-fetch: "npm:^2.6.9" - stream-events: "npm:^1.0.5" - uuid: "npm:^9.0.0" - checksum: 10c0/1c51a284075b57b7b7f970fc8d855d611912f0e485aa1d1dfda3c0be3f2df392e4ce83b1b39877134041abb7c255f3777f175b27323ef5bf008839e42a1958bc - languageName: node - linkType: hard - "temp-dir@npm:1.0.0": version: 1.0.0 resolution: "temp-dir@npm:1.0.0" @@ -24124,6 +23978,13 @@ __metadata: languageName: node linkType: hard +"url-template@npm:^2.0.8": + version: 2.0.8 + resolution: "url-template@npm:2.0.8" + checksum: 10c0/56a15057eacbcf05d52b0caed8279c8451b3dd9d32856a1fdd91c6dc84dcb1646f12bafc756b7ade62ca5b1564da8efd7baac5add35868bafb43eb024c62805b + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -24147,16 +24008,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^8.0.0": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54 - languageName: node - linkType: hard - -"uuid@npm:^9.0.0, uuid@npm:^9.0.1": +"uuid@npm:^9.0.0": version: 9.0.1 resolution: "uuid@npm:9.0.1" bin: @@ -24782,6 +24634,13 @@ __metadata: languageName: node linkType: hard +"web-streams-polyfill@npm:^3.0.3": + version: 3.3.3 + resolution: "web-streams-polyfill@npm:3.3.3" + checksum: 10c0/64e855c47f6c8330b5436147db1c75cb7e7474d924166800e8e2aab5eb6c76aac4981a84261dd2982b3e754490900b99791c80ae1407a9fa0dcff74f82ea3a7f + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1"