From de82e0337278ea8864e8efca475eb8073302e565 Mon Sep 17 00:00:00 2001 From: Niklas Mollenhauer Date: Fri, 6 Dec 2024 00:07:15 +0100 Subject: [PATCH] Use `crypto.randomUUID()` instead of `uuid` module The `crypto` global is available in all supported Node.js versions as well as [in all major browsers](https://caniuse.com/mdn-api_crypto_randomuuid). The uuid module is rendered unnecessary for uuidv4. --- package-lock.json | 23 +------------------ package.json | 4 +--- src/eventarc/eventarc-utils.ts | 11 ++++----- .../remote-config/condition-evaluator.spec.ts | 9 ++++---- 4 files changed, 11 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c63c94dc7..bbff82dbcb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,8 +17,7 @@ "google-auth-library": "^9.14.2", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", - "node-forge": "^1.3.1", - "uuid": "^11.0.2" + "node-forge": "^1.3.1" }, "devDependencies": { "@firebase/api-documenter": "^0.4.0", @@ -39,7 +38,6 @@ "@types/request-promise": "^4.1.41", "@types/sinon": "^17.0.2", "@types/sinon-chai": "^3.0.0", - "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.16.1", "@typescript-eslint/parser": "^7.16.1", "bcrypt": "^5.0.0", @@ -1855,13 +1853,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -11313,18 +11304,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index 49e9840509..3765c62efd 100644 --- a/package.json +++ b/package.json @@ -212,8 +212,7 @@ "google-auth-library": "^9.14.2", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", - "node-forge": "^1.3.1", - "uuid": "^11.0.2" + "node-forge": "^1.3.1" }, "optionalDependencies": { "@google-cloud/firestore": "^7.11.0", @@ -238,7 +237,6 @@ "@types/request-promise": "^4.1.41", "@types/sinon": "^17.0.2", "@types/sinon-chai": "^3.0.0", - "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.16.1", "@typescript-eslint/parser": "^7.16.1", "bcrypt": "^5.0.0", diff --git a/src/eventarc/eventarc-utils.ts b/src/eventarc/eventarc-utils.ts index 6bf6531285..0fe0e1f6b2 100644 --- a/src/eventarc/eventarc-utils.ts +++ b/src/eventarc/eventarc-utils.ts @@ -17,12 +17,11 @@ import { PrefixedFirebaseError } from '../utils/error'; import { CloudEvent } from './cloudevent'; -import { v4 as uuid } from 'uuid'; import * as validator from '../utils/validator'; // List of CloudEvent properties that are handled "by hand" and should be skipped by // automatic attribute copy. -const TOP_LEVEL_CE_ATTRS: string[] = +const TOP_LEVEL_CE_ATTRS: string[] = ['id', 'type', 'specversion', 'source', 'data', 'time', 'datacontenttype', 'subject']; export type EventarcErrorCode = 'unknown-error' | 'invalid-argument' @@ -50,7 +49,7 @@ export function toCloudEventProtoFormat(ce: CloudEvent): any { } const out: Record = { '@type': 'type.googleapis.com/io.cloudevents.v1.CloudEvent', - 'id': ce.id ?? uuid(), + 'id': ce.id ?? crypto.randomUUID(), 'type': ce.type, 'specVersion': ce.specversion ?? '1.0', 'source': source @@ -72,7 +71,7 @@ export function toCloudEventProtoFormat(ce: CloudEvent): any { if (typeof ce.datacontenttype !== 'undefined') { if (!validator.isNonEmptyString(ce.datacontenttype)) { throw new FirebaseEventarcError( - 'invalid-argument', + 'invalid-argument', "CloudEvent 'datacontenttype' if specified must be non-empty string."); } setAttribute(out, 'datacontenttype', { @@ -82,7 +81,7 @@ export function toCloudEventProtoFormat(ce: CloudEvent): any { if (ce.subject) { if (!validator.isNonEmptyString(ce.subject)) { throw new FirebaseEventarcError( - 'invalid-argument', + 'invalid-argument', "CloudEvent 'subject' if specified must be non-empty string."); } setAttribute(out, 'subject', { @@ -109,7 +108,7 @@ export function toCloudEventProtoFormat(ce: CloudEvent): any { } } else { throw new FirebaseEventarcError( - 'invalid-argument', + 'invalid-argument', `CloudEvent 'data' must be string or an object (which are converted to JSON), got '${typeof ce.data}'.`); } diff --git a/test/unit/remote-config/condition-evaluator.spec.ts b/test/unit/remote-config/condition-evaluator.spec.ts index 8bfa168df6..71d4934858 100644 --- a/test/unit/remote-config/condition-evaluator.spec.ts +++ b/test/unit/remote-config/condition-evaluator.spec.ts @@ -26,7 +26,6 @@ import { NamedCondition, OneOfCondition, } from '../../../src/remote-config/remote-config-api'; -import { v4 as uuidv4 } from 'uuid'; import { clone } from 'lodash'; import * as crypto from 'crypto'; @@ -754,7 +753,7 @@ describe('ConditionEvaluator', () => { describe('known percent condition values', () => { // This test is useful for ensuring consistency across all places we - // evaluate percent conditions. It creates a set of 10 conditions targeting 50% + // evaluate percent conditions. It creates a set of 10 conditions targeting 50% // with randomizationIds 0-9 and a constant `seed` value. const conditionEvaluator = new ConditionEvaluator(); @@ -782,8 +781,8 @@ describe('ConditionEvaluator', () => { testCases.map(({ randomizationId, seed, result }) => { - const idSummary = randomizationId.length > 25 - ? `a ${randomizationId.length} character randomizationID` + const idSummary = randomizationId.length > 25 + ? `a ${randomizationId.length} character randomizationID` : `"${randomizationId}"`; it(`should evaluate ${idSummary} with seed "${seed}" to ${result}`, () => { @@ -907,7 +906,7 @@ describe('ConditionEvaluator', () => { ...clone(condition), seed: 'seed' }; - const context = { randomizationId: uuidv4() } + const context = { randomizationId: crypto.randomUUID() } if (conditionEvaluator.evaluateConditions([{ name: 'is_enabled', condition: { percent: clonedCondition }