launchdarkly-js-sdk-common 5.8.0 → 5.8.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/.github/workflows/dependency-scan.yml +30 -0
- package/.github/workflows/lint-pr-title.yml +3 -0
- package/.github/workflows/release-please.yml +49 -7
- package/.github/workflows/stale.yml +14 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +7 -0
- package/package.json +2 -3
- package/src/AnonymousContextProcessor.js +2 -2
- package/src/EventSender.js +2 -2
- package/src/__tests__/diagnosticEvents-test.js +6 -0
- package/src/diagnosticEvents.js +2 -5
- package/src/uuid.js +70 -0
- package/.github/workflows/manual-publish.yml +0 -42
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Dependency Scan
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
generate-nodejs-sbom:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
|
|
14
|
+
|
|
15
|
+
- name: Generate SBOM
|
|
16
|
+
uses: launchdarkly/gh-actions/actions/dependency-scan/generate-sbom@main
|
|
17
|
+
with:
|
|
18
|
+
types: 'nodejs'
|
|
19
|
+
|
|
20
|
+
evaluate-policy:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
needs:
|
|
23
|
+
- generate-nodejs-sbom
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
|
|
26
|
+
|
|
27
|
+
- name: Evaluate SBOM Policy
|
|
28
|
+
uses: launchdarkly/gh-actions/actions/dependency-scan/evaluate-policy@main
|
|
29
|
+
with:
|
|
30
|
+
artifacts-pattern: bom-*
|
|
@@ -4,14 +4,28 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
dry-run:
|
|
10
|
+
description: 'Is this a dry run. If so no package will be published.'
|
|
11
|
+
type: boolean
|
|
12
|
+
required: true
|
|
13
|
+
prerelease:
|
|
14
|
+
description: 'Is this a prerelease. If so, then the latest tag will not be updated in npm.'
|
|
15
|
+
type: boolean
|
|
16
|
+
required: true
|
|
7
17
|
|
|
8
18
|
jobs:
|
|
9
19
|
release-please:
|
|
10
20
|
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write
|
|
23
|
+
pull-requests: write
|
|
24
|
+
if: github.event_name == 'push'
|
|
11
25
|
outputs:
|
|
12
26
|
release_created: ${{ steps.release.outputs.release_created }}
|
|
13
27
|
steps:
|
|
14
|
-
- uses: googleapis/release-please-action@
|
|
28
|
+
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
|
|
15
29
|
id: release
|
|
16
30
|
with:
|
|
17
31
|
token: ${{secrets.GITHUB_TOKEN}}
|
|
@@ -28,14 +42,13 @@ jobs:
|
|
|
28
42
|
|
|
29
43
|
- uses: actions/setup-node@v4
|
|
30
44
|
with:
|
|
31
|
-
node-version:
|
|
45
|
+
node-version: 24.x
|
|
32
46
|
registry-url: 'https://registry.npmjs.org'
|
|
33
47
|
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ssm_parameter_pairs: '/production/common/releasing/npm/token = NODE_AUTH_TOKEN'
|
|
48
|
+
- name: Update NPM
|
|
49
|
+
shell: bash
|
|
50
|
+
# Must be greater than 11.5.1 for OIDC.
|
|
51
|
+
run: npm install -g npm@11.6.2
|
|
39
52
|
|
|
40
53
|
- name: Install Dependencies
|
|
41
54
|
run: npm install
|
|
@@ -55,3 +68,32 @@ jobs:
|
|
|
55
68
|
uses: ./.github/actions/publish-docs
|
|
56
69
|
with:
|
|
57
70
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
71
|
+
|
|
72
|
+
manual-publish-package:
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
if: github.event_name == 'workflow_dispatch'
|
|
75
|
+
permissions:
|
|
76
|
+
id-token: write
|
|
77
|
+
contents: write
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
|
|
81
|
+
- uses: actions/setup-node@v4
|
|
82
|
+
with:
|
|
83
|
+
node-version: 24.x
|
|
84
|
+
registry-url: 'https://registry.npmjs.org'
|
|
85
|
+
|
|
86
|
+
- name: Update NPM
|
|
87
|
+
shell: bash
|
|
88
|
+
# Must be greater than 11.5.1 for OIDC.
|
|
89
|
+
run: npm install -g npm@11.6.2
|
|
90
|
+
|
|
91
|
+
- name: Install Dependencies
|
|
92
|
+
run: npm install
|
|
93
|
+
|
|
94
|
+
- id: publish-npm
|
|
95
|
+
name: Publish NPM Package
|
|
96
|
+
uses: ./.github/actions/publish-npm
|
|
97
|
+
with:
|
|
98
|
+
dry-run: ${{ inputs.dry-run }}
|
|
99
|
+
prerelease: ${{ inputs.prerelease }}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
name: "Close stale issues and PRs"
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
schedule:
|
|
5
|
+
# Happen once per day at 1:30 AM
|
|
6
|
+
- cron: "30 1 * * *"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
issues: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
sdk-close-stale:
|
|
14
|
+
uses: launchdarkly/gh-actions/.github/workflows/sdk-stale.yml@main
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the `launchdarkly-js-sdk-common` package will be documented in this file. Changes that affect the dependent SDKs such as `launchdarkly-js-client-sdk` should also be logged in those projects, in the next release that uses the updated version of this package. This project adheres to [Semantic Versioning](http://semver.org).
|
|
4
4
|
|
|
5
|
+
## [5.8.1](https://github.com/launchdarkly/js-sdk-common/compare/5.8.0...5.8.1) (2026-05-21)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* remove uuid dependency, replace with inline implementation ([#146](https://github.com/launchdarkly/js-sdk-common/issues/146)) ([98c87d0](https://github.com/launchdarkly/js-sdk-common/commit/98c87d02a6c58b336bbb40b7a80f9bb3489bbed9))
|
|
11
|
+
|
|
5
12
|
## [5.8.0](https://github.com/launchdarkly/js-sdk-common/compare/5.7.1...5.8.0) (2025-09-05)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "launchdarkly-js-sdk-common",
|
|
3
|
-
"version": "5.8.
|
|
3
|
+
"version": "5.8.1",
|
|
4
4
|
"description": "LaunchDarkly SDK for JavaScript - common code",
|
|
5
5
|
"author": "LaunchDarkly <team@launchdarkly.com>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,8 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"base64-js": "^1.3.0",
|
|
52
|
-
"fast-deep-equal": "^2.0.1"
|
|
53
|
-
"uuid": "^8.0.0"
|
|
52
|
+
"fast-deep-equal": "^2.0.1"
|
|
54
53
|
},
|
|
55
54
|
"repository": {
|
|
56
55
|
"type": "git",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { randomUuidV4 } = require('./uuid');
|
|
2
2
|
const { getContextKinds } = require('./context');
|
|
3
3
|
|
|
4
4
|
const errors = require('./errors');
|
|
@@ -57,7 +57,7 @@ function AnonymousContextProcessor(persistentStorage) {
|
|
|
57
57
|
context.key = cachedId;
|
|
58
58
|
return context;
|
|
59
59
|
} else {
|
|
60
|
-
const id =
|
|
60
|
+
const id = randomUuidV4();
|
|
61
61
|
context.key = id;
|
|
62
62
|
return setCachedContextKey(id, kind).then(() => context);
|
|
63
63
|
}
|
package/src/EventSender.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const errors = require('./errors');
|
|
2
2
|
const utils = require('./utils');
|
|
3
|
-
const {
|
|
3
|
+
const { randomUuidV4 } = require('./uuid');
|
|
4
4
|
const { getLDHeaders, transformHeaders } = require('./headers');
|
|
5
5
|
|
|
6
6
|
function EventSender(platform, environmentId, options) {
|
|
@@ -25,7 +25,7 @@ function EventSender(platform, environmentId, options) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const jsonBody = JSON.stringify(events);
|
|
28
|
-
const payloadId = isDiagnostic ? null :
|
|
28
|
+
const payloadId = isDiagnostic ? null : randomUuidV4();
|
|
29
29
|
|
|
30
30
|
function doPostRequest(canRetry) {
|
|
31
31
|
const headers = isDiagnostic
|
|
@@ -16,6 +16,12 @@ describe('DiagnosticId', () => {
|
|
|
16
16
|
expect(id1.diagnosticId).not.toEqual(id2.diagnosticId);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
it('generates valid UUID v4 format', () => {
|
|
20
|
+
const id = DiagnosticId('key');
|
|
21
|
+
const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
22
|
+
expect(id.diagnosticId).toMatch(uuidV4Regex);
|
|
23
|
+
});
|
|
24
|
+
|
|
19
25
|
it('uses only last 6 characters of key', () => {
|
|
20
26
|
const id = DiagnosticId('0123456789abcdef');
|
|
21
27
|
expect(id.sdkKeySuffix).toEqual('abcdef');
|
package/src/diagnosticEvents.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
const {
|
|
2
|
-
// Note that in the diagnostic events spec, these IDs are to be generated with UUID v4. However,
|
|
3
|
-
// in JS we were already using v1 for unique context keys, so to avoid bringing in two packages we
|
|
4
|
-
// will use v1 here as well.
|
|
1
|
+
const { randomUuidV4 } = require('./uuid');
|
|
5
2
|
|
|
6
3
|
const { baseOptionDefs } = require('./configuration');
|
|
7
4
|
const messages = require('./messages');
|
|
@@ -9,7 +6,7 @@ const { appendUrlPath } = require('./utils');
|
|
|
9
6
|
|
|
10
7
|
function DiagnosticId(sdkKey) {
|
|
11
8
|
const ret = {
|
|
12
|
-
diagnosticId:
|
|
9
|
+
diagnosticId: randomUuidV4(),
|
|
13
10
|
};
|
|
14
11
|
if (sdkKey) {
|
|
15
12
|
ret.sdkKeySuffix = sdkKey.length > 6 ? sdkKey.substring(sdkKey.length - 6) : sdkKey;
|
package/src/uuid.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* global crypto */
|
|
2
|
+
// The implementation in this file generates UUIDs in v4 format and is suitable
|
|
3
|
+
// for use as a UUID in LaunchDarkly events. It is not a rigorous implementation.
|
|
4
|
+
//
|
|
5
|
+
// Adapted from:
|
|
6
|
+
// https://github.com/launchdarkly/js-core/blob/main/packages/sdk/browser/src/platform/randomUuidV4.ts
|
|
7
|
+
|
|
8
|
+
// It uses crypto.randomUUID when available.
|
|
9
|
+
// If crypto.randomUUID is not available, then it uses random values and forms
|
|
10
|
+
// the UUID itself.
|
|
11
|
+
// When possible it uses crypto.getRandomValues, but it can use Math.random
|
|
12
|
+
// if crypto.getRandomValues is not available.
|
|
13
|
+
|
|
14
|
+
// UUIDv4 Struct definition.
|
|
15
|
+
// https://www.rfc-archive.org/getrfc.php?rfc=4122
|
|
16
|
+
// Appendix A. Appendix A - Sample Implementation
|
|
17
|
+
const timeLow = { start: 0, end: 3 };
|
|
18
|
+
const timeMid = { start: 4, end: 5 };
|
|
19
|
+
const timeHiAndVersion = { start: 6, end: 7 };
|
|
20
|
+
const clockSeqHiAndReserved = { start: 8, end: 8 };
|
|
21
|
+
const clockSeqLow = { start: 9, end: 9 };
|
|
22
|
+
const nodes = { start: 10, end: 15 };
|
|
23
|
+
|
|
24
|
+
function getRandom128bit() {
|
|
25
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
26
|
+
const typedArray = new Uint8Array(16);
|
|
27
|
+
crypto.getRandomValues(typedArray);
|
|
28
|
+
return [...typedArray.values()];
|
|
29
|
+
}
|
|
30
|
+
const values = [];
|
|
31
|
+
for (let index = 0; index < 16; index += 1) {
|
|
32
|
+
values.push(Math.floor(Math.random() * 256));
|
|
33
|
+
}
|
|
34
|
+
return values;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hex(bytes, range) {
|
|
38
|
+
let strVal = '';
|
|
39
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
40
|
+
strVal += bytes[index].toString(16).padStart(2, '0');
|
|
41
|
+
}
|
|
42
|
+
return strVal;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function formatDataAsUuidV4(bytes) {
|
|
46
|
+
// eslint-disable-next-line no-bitwise, no-param-reassign
|
|
47
|
+
bytes[clockSeqHiAndReserved.start] = (bytes[clockSeqHiAndReserved.start] | 0x80) & 0xbf;
|
|
48
|
+
// eslint-disable-next-line no-bitwise, no-param-reassign
|
|
49
|
+
bytes[timeHiAndVersion.start] = (bytes[timeHiAndVersion.start] & 0x0f) | 0x40;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
`${hex(bytes, timeLow)}-${hex(bytes, timeMid)}-${hex(bytes, timeHiAndVersion)}-` +
|
|
53
|
+
`${hex(bytes, clockSeqHiAndReserved)}${hex(bytes, clockSeqLow)}-${hex(bytes, nodes)}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function fallbackUuidV4() {
|
|
58
|
+
const bytes = getRandom128bit();
|
|
59
|
+
return formatDataAsUuidV4(bytes);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function randomUuidV4() {
|
|
63
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
64
|
+
return crypto.randomUUID();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return fallbackUuidV4();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { randomUuidV4, fallbackUuidV4, formatDataAsUuidV4 };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
name: Manual Publish Package
|
|
2
|
-
on:
|
|
3
|
-
workflow_dispatch:
|
|
4
|
-
inputs:
|
|
5
|
-
dry-run:
|
|
6
|
-
description: 'Is this a dry run. If so no package will be published.'
|
|
7
|
-
type: boolean
|
|
8
|
-
required: true
|
|
9
|
-
prerelease:
|
|
10
|
-
description: 'Is this a prerelease. If so, then the latest tag will not be updated in npm.'
|
|
11
|
-
type: boolean
|
|
12
|
-
required: true
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
publish-package:
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
permissions:
|
|
18
|
-
id-token: write
|
|
19
|
-
contents: write
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v4
|
|
22
|
-
|
|
23
|
-
- uses: actions/setup-node@v4
|
|
24
|
-
with:
|
|
25
|
-
node-version: 20.x
|
|
26
|
-
registry-url: 'https://registry.npmjs.org'
|
|
27
|
-
|
|
28
|
-
- uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
|
|
29
|
-
name: 'Get NPM token'
|
|
30
|
-
with:
|
|
31
|
-
aws_assume_role: ${{ vars.AWS_ROLE_ARN }}
|
|
32
|
-
ssm_parameter_pairs: '/production/common/releasing/npm/token = NODE_AUTH_TOKEN'
|
|
33
|
-
|
|
34
|
-
- name: Install Dependencies
|
|
35
|
-
run: npm install
|
|
36
|
-
|
|
37
|
-
- id: publish-npm
|
|
38
|
-
name: Publish NPM Package
|
|
39
|
-
uses: ./.github/actions/publish-npm
|
|
40
|
-
with:
|
|
41
|
-
dry-run: ${{ inputs.dry-run }}
|
|
42
|
-
prerelease: ${{ inputs.prerelease }}
|