launchdarkly-js-sdk-common 5.7.1 → 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/src/index.js CHANGED
@@ -18,7 +18,13 @@ const { checkContext, getContextKeys } = require('./context');
18
18
  const { InspectorTypes, InspectorManager } = require('./InspectorManager');
19
19
  const timedPromise = require('./timedPromise');
20
20
  const createHookRunner = require('./HookRunner');
21
- const { getPluginHooks, registerPlugins, createPluginEnvironment } = require('./plugins');
21
+ const FlagStore = require('./FlagStore');
22
+ const {
23
+ getPluginHooks,
24
+ registerPlugins,
25
+ registerPluginsForDebugOverride,
26
+ createPluginEnvironment,
27
+ } = require('./plugins');
22
28
  const changeEvent = 'change';
23
29
  const internalChangeEvent = 'internal-change';
24
30
  const highTimeoutThreshold = 5;
@@ -76,7 +82,8 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
76
82
 
77
83
  const requestor = Requestor(platform, options, environment);
78
84
 
79
- let flags = {};
85
+ const flagStore = FlagStore();
86
+
80
87
  let useLocalStorage;
81
88
  let streamActive;
82
89
  let streamForcedState = options.streaming;
@@ -188,7 +195,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
188
195
  function notifyInspectionFlagsChanged() {
189
196
  if (inspectorManager.hasListeners(InspectorTypes.flagDetailsChanged)) {
190
197
  inspectorManager.onFlags(
191
- Object.entries(flags)
198
+ Object.entries(flagStore.getFlagsWithOverrides())
192
199
  .map(([key, value]) => ({ key, detail: getFlagDetail(value) }))
193
200
  .reduce((acc, cur) => {
194
201
  // eslint-disable-next-line no-param-reassign
@@ -232,7 +239,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
232
239
  default: defaultValue,
233
240
  creationDate: now.getTime(),
234
241
  };
235
- const flag = flags[key];
242
+ const flag = flagStore.getFlags()[key];
236
243
  if (flag) {
237
244
  event.version = flag.flagVersion ? flag.flagVersion : flag.version;
238
245
  event.trackEvents = flag.trackEvents;
@@ -262,7 +269,10 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
262
269
  if (stateProvider) {
263
270
  // We're being controlled by another client instance, so only that instance is allowed to change the context
264
271
  logger.warn(messages.identifyDisabled());
265
- return utils.wrapPromiseCallback(Promise.resolve(utils.transformVersionedValuesToValues(flags)), onDone);
272
+ return utils.wrapPromiseCallback(
273
+ Promise.resolve(utils.transformVersionedValuesToValues(flagStore.getFlagsWithOverrides())),
274
+ onDone
275
+ );
266
276
  }
267
277
  let afterIdentify;
268
278
  const clearFirst = useLocalStorage && persistentFlagStore ? persistentFlagStore.clearFlags() : Promise.resolve();
@@ -328,10 +338,10 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
328
338
 
329
339
  function variationDetailInternal(key, defaultValue, sendEvent, includeReasonInEvent, isAllFlags, notifyInspection) {
330
340
  let detail;
331
- let flag;
332
341
 
333
- if (flags && utils.objectHasOwnProperty(flags, key) && flags[key] && !flags[key].deleted) {
334
- flag = flags[key];
342
+ const flag = flagStore.get(key);
343
+
344
+ if (flag) {
335
345
  detail = getFlagDetail(flag);
336
346
  if (flag.value === null || flag.value === undefined) {
337
347
  detail.value = defaultValue;
@@ -373,21 +383,14 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
373
383
  function allFlags() {
374
384
  const results = {};
375
385
 
376
- if (!flags) {
386
+ const allFlags = flagStore.getFlagsWithOverrides();
387
+
388
+ if (!allFlags) {
377
389
  return results;
378
390
  }
379
391
 
380
- for (const key in flags) {
381
- if (utils.objectHasOwnProperty(flags, key) && !flags[key].deleted) {
382
- results[key] = variationDetailInternal(
383
- key,
384
- null,
385
- !options.sendEventsOnlyForVariation,
386
- false,
387
- true,
388
- false
389
- ).value;
390
- }
392
+ for (const key in allFlags) {
393
+ results[key] = variationDetailInternal(key, null, !options.sendEventsOnlyForVariation, false, true, false).value;
391
394
  }
392
395
 
393
396
  return results;
@@ -485,6 +488,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
485
488
  // If both the flag and the patch have a version property, then the patch version must be
486
489
  // greater than the flag version for us to accept the patch. If either one has no version
487
490
  // then the patch always succeeds.
491
+ const flags = flagStore.getFlags();
488
492
  const oldFlag = flags[data.key];
489
493
  if (!oldFlag || !oldFlag.version || !data.version || oldFlag.version < data.version) {
490
494
  logger.debug(messages.debugStreamPatch(data.key));
@@ -492,6 +496,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
492
496
  const newFlag = utils.extend({}, data);
493
497
  delete newFlag['key'];
494
498
  flags[data.key] = newFlag;
499
+ flagStore.setFlags(flags);
495
500
  const newDetail = getFlagDetail(newFlag);
496
501
  if (oldFlag) {
497
502
  mods[data.key] = { previous: oldFlag.value, current: newDetail };
@@ -509,6 +514,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
509
514
  if (!data) {
510
515
  return;
511
516
  }
517
+ const flags = flagStore.getFlags();
512
518
  if (!flags[data.key] || flags[data.key].version < data.version) {
513
519
  logger.debug(messages.debugStreamDelete(data.key));
514
520
  const mods = {};
@@ -516,6 +522,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
516
522
  mods[data.key] = { previous: flags[data.key].value };
517
523
  }
518
524
  flags[data.key] = { version: data.version, deleted: true };
525
+ flagStore.setFlags(flags);
519
526
  notifyInspectionFlagChanged(data, flags[data.key]);
520
527
  handleFlagChanges(mods); // don't wait for this Promise to be resolved
521
528
  } else {
@@ -542,6 +549,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
542
549
  return Promise.resolve();
543
550
  }
544
551
 
552
+ const flags = flagStore.getFlags();
545
553
  for (const key in flags) {
546
554
  if (utils.objectHasOwnProperty(flags, key) && flags[key]) {
547
555
  if (newFlags[key] && !utils.deepEquals(newFlags[key].value, flags[key].value)) {
@@ -557,7 +565,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
557
565
  }
558
566
  }
559
567
 
560
- flags = { ...newFlags };
568
+ flagStore.setFlags({ ...newFlags });
561
569
 
562
570
  notifyInspectionFlagsChanged();
563
571
 
@@ -580,7 +588,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
580
588
  });
581
589
 
582
590
  emitter.emit(changeEvent, changeEventParams);
583
- emitter.emit(internalChangeEvent, flags);
591
+ emitter.emit(internalChangeEvent, flagStore.getFlagsWithOverrides());
584
592
 
585
593
  // By default, we send feature evaluation events whenever we have received new flag values -
586
594
  // the client has in effect evaluated these flags just by receiving them. This can be suppressed
@@ -595,7 +603,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
595
603
  }
596
604
 
597
605
  if (useLocalStorage && persistentFlagStore) {
598
- return persistentFlagStore.saveFlags(flags);
606
+ return persistentFlagStore.saveFlags(flagStore.getFlags());
599
607
  } else {
600
608
  return Promise.resolve();
601
609
  }
@@ -666,7 +674,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
666
674
  if (typeof options.bootstrap === 'object') {
667
675
  // Set the flags as soon as possible before we get into any async code, so application code can read
668
676
  // them even if the ready event has not yet fired.
669
- flags = readFlagsFromBootstrap(options.bootstrap);
677
+ flagStore.setFlags(readFlagsFromBootstrap(options.bootstrap));
670
678
  }
671
679
 
672
680
  if (stateProvider) {
@@ -718,7 +726,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
718
726
  function finishInitWithLocalStorage() {
719
727
  return persistentFlagStore.loadFlags().then(storedFlags => {
720
728
  if (storedFlags === null || storedFlags === undefined) {
721
- flags = {};
729
+ flagStore.setFlags({});
722
730
  return requestor
723
731
  .fetchFlagSettings(ident.getContext(), hash)
724
732
  .then(requestedFlags => replaceAllFlags(requestedFlags || {}))
@@ -731,7 +739,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
731
739
  // We're reading the flags from local storage. Signal that we're ready,
732
740
  // then update localStorage for the next page load. We won't signal changes or update
733
741
  // the in-memory flags unless you subscribe for changes
734
- flags = storedFlags;
742
+ flagStore.setFlags(storedFlags);
735
743
  utils.onNextTick(signalSuccessfulInit);
736
744
 
737
745
  return requestor
@@ -746,14 +754,14 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
746
754
  return requestor
747
755
  .fetchFlagSettings(ident.getContext(), hash)
748
756
  .then(requestedFlags => {
749
- flags = requestedFlags || {};
757
+ flagStore.setFlags(requestedFlags || {});
750
758
 
751
759
  notifyInspectionFlagsChanged();
752
760
  // Note, we don't need to call updateSettings here because local storage and change events are not relevant
753
761
  signalSuccessfulInit();
754
762
  })
755
763
  .catch(err => {
756
- flags = {};
764
+ flagStore.setFlags({});
757
765
  signalFailedInit(err);
758
766
  });
759
767
  }
@@ -761,7 +769,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
761
769
  function initFromStateProvider(state) {
762
770
  environment = state.environment;
763
771
  ident.setContext(state.context);
764
- flags = { ...state.flags };
772
+ flagStore.setFlags({ ...state.flags });
765
773
  utils.onNextTick(signalSuccessfulInit);
766
774
  }
767
775
 
@@ -800,7 +808,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
800
808
  }
801
809
  const finishClose = () => {
802
810
  closed = true;
803
- flags = {};
811
+ flagStore.setFlags({});
804
812
  };
805
813
  const p = Promise.resolve()
806
814
  .then(() => {
@@ -820,7 +828,7 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
820
828
 
821
829
  function getFlagsInternal() {
822
830
  // used by Electron integration
823
- return flags;
831
+ return flagStore.getFlagsWithOverrides();
824
832
  }
825
833
 
826
834
  function waitForInitializationWithTimeout(timeout) {
@@ -880,6 +888,94 @@ function initialize(env, context, specifiedOptions, platform, extraOptionDefs) {
880
888
 
881
889
  registerPlugins(logger, pluginEnvironment, client, plugins);
882
890
 
891
+ function setOverride(key, value) {
892
+ const mods = {};
893
+
894
+ const currentFlag = flagStore.get(key);
895
+ const currentValue = currentFlag ? currentFlag.value : null;
896
+
897
+ if (currentValue === value) {
898
+ logger.debug(`setOverride: No change needed for ${key}, value already ${value}`);
899
+ return;
900
+ }
901
+
902
+ flagStore.setOverride(key, value);
903
+ const newFlag = flagStore.get(key);
904
+ const newDetail = getFlagDetail(newFlag);
905
+
906
+ mods[key] = { previous: currentValue, current: newDetail };
907
+
908
+ notifyInspectionFlagChanged({ key }, newFlag);
909
+ handleFlagChanges(mods);
910
+ }
911
+
912
+ function removeOverride(key) {
913
+ const flagOverrides = flagStore.getFlagOverrides();
914
+ if (!flagOverrides[key]) {
915
+ return; // No override to remove
916
+ }
917
+
918
+ const mods = {};
919
+ const oldOverride = flagOverrides[key];
920
+ const flags = flagStore.getFlags();
921
+ const realFlag = flags[key];
922
+
923
+ mods[key] = { previous: oldOverride.value, current: realFlag ? getFlagDetail(realFlag) : undefined };
924
+
925
+ flagStore.removeOverride(key);
926
+ notifyInspectionFlagChanged({ key }, realFlag);
927
+ handleFlagChanges(mods); // don't wait for this Promise to be resolved
928
+ }
929
+
930
+ function clearAllOverrides() {
931
+ const flagOverrides = flagStore.getFlagOverrides();
932
+ if (Object.keys(flagOverrides).length === 0) {
933
+ return; // No overrides to clear
934
+ }
935
+
936
+ const mods = {};
937
+ const flags = flagStore.getFlags();
938
+ Object.keys(flagOverrides).forEach(key => {
939
+ const oldOverride = flagOverrides[key];
940
+ const realFlag = flags[key];
941
+
942
+ mods[key] = { previous: oldOverride.value, current: realFlag ? getFlagDetail(realFlag) : undefined };
943
+ });
944
+
945
+ flagStore.clearAllOverrides();
946
+
947
+ if (Object.keys(mods).length > 0) {
948
+ handleFlagChanges(mods); // don't wait for this Promise to be resolved
949
+ }
950
+ }
951
+
952
+ function getAllOverrides() {
953
+ const flagOverrides = flagStore.getFlagOverrides();
954
+
955
+ if (!flagOverrides) {
956
+ return {}; // No overrides set
957
+ }
958
+
959
+ const result = {};
960
+ Object.keys(flagOverrides).forEach(key => {
961
+ const override = flagOverrides[key];
962
+ if (override) {
963
+ result[key] = override.value;
964
+ }
965
+ });
966
+ return result;
967
+ }
968
+
969
+ const debugOverride = {
970
+ setOverride: setOverride,
971
+ removeOverride: removeOverride,
972
+ clearAllOverrides: clearAllOverrides,
973
+ getAllOverrides: getAllOverrides,
974
+ };
975
+
976
+ // Register plugins for debug override capabilities
977
+ registerPluginsForDebugOverride(logger, debugOverride, plugins);
978
+
883
979
  return {
884
980
  client: client, // The client object containing all public methods.
885
981
  options: options, // The validated configuration object, including all defaults.
package/src/plugins.js CHANGED
@@ -56,6 +56,22 @@ function registerPlugins(logger, environmentMetadata, client, plugins) {
56
56
  });
57
57
  }
58
58
 
59
+ /**
60
+ * Registers plugins for debug override capabilities
61
+ * @param {{ error: (message: string) => void }} logger - The logger instance
62
+ * @param {Object} debugOverride - The debug override interface object
63
+ * @param {Array<{registerDebug?: (debugOverride: object) => void}>} plugins - Array of plugin objects that may implement registerDebug
64
+ */
65
+ function registerPluginsForDebugOverride(logger, debugOverride, plugins) {
66
+ plugins.forEach(plugin => {
67
+ try {
68
+ plugin.registerDebug?.(debugOverride);
69
+ } catch (error) {
70
+ logger.error(`Exception thrown registering debug override with plugin ${getPluginName(logger, plugin)}.`);
71
+ }
72
+ });
73
+ }
74
+
59
75
  /**
60
76
  * Creates a plugin environment object
61
77
  * @param {{userAgent: string, version: string}} platform - The platform object
@@ -105,5 +121,6 @@ function createPluginEnvironment(platform, env, options) {
105
121
  module.exports = {
106
122
  getPluginHooks,
107
123
  registerPlugins,
124
+ registerPluginsForDebugOverride,
108
125
  createPluginEnvironment,
109
126
  };
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 };
package/test-types.ts CHANGED
@@ -55,7 +55,7 @@ const plugin: ld.LDPlugin = {
55
55
  }),
56
56
  register(client: ld.LDClientBase, environmentMetadata: ld.LDPluginEnvironmentMetadata): void {
57
57
  },
58
-
58
+ registerDebug(debugOverride: ld.LDDebugOverride): void {},
59
59
  getHooks(metadata: ld.LDPluginEnvironmentMetadata): ld.Hook[] {
60
60
  return [];
61
61
  },
package/typings.d.ts CHANGED
@@ -74,7 +74,7 @@ declare module 'launchdarkly-js-sdk-common' {
74
74
  }
75
75
 
76
76
  /**
77
- * Meta-data about a hook implementation.
77
+ * Metadata about a hook implementation.
78
78
  */
79
79
  export interface HookMetadata {
80
80
  /**
@@ -149,7 +149,6 @@ declare module 'launchdarkly-js-sdk-common' {
149
149
  readonly metricValue?: number;
150
150
  }
151
151
 
152
-
153
152
  /**
154
153
  * Interface for extending SDK functionality via hooks.
155
154
  */
@@ -251,7 +250,7 @@ declare module 'launchdarkly-js-sdk-common' {
251
250
  }
252
251
 
253
252
  /**
254
- * Meta-data about a plugin implementation.
253
+ * Metadata about a plugin implementation.
255
254
  *
256
255
  * May be used in logs and analytics to identify the plugin.
257
256
  */
@@ -363,6 +362,59 @@ export interface LDPlugin {
363
362
  * @param metadata
364
363
  */
365
364
  getHooks?(metadata: LDPluginEnvironmentMetadata): Hook[];
365
+
366
+ /**
367
+ * An optional function called if the plugin wants to register debug capabilities.
368
+ * This method allows plugins to receive a debug override interface for
369
+ * temporarily overriding flag values during development and testing.
370
+ *
371
+ * @experimental This interface is experimental and intended for use by LaunchDarkly tools at this time.
372
+ * The API may change in future versions.
373
+ *
374
+ * @param debugOverride The debug override interface instance
375
+ */
376
+ registerDebug?(debugOverride: LDDebugOverride): void;
377
+ }
378
+
379
+ /**
380
+ * Debug interface for plugins that need to override flag values during development.
381
+ * This interface provides methods to temporarily override flag values that take
382
+ * precedence over the actual flag values from LaunchDarkly. These overrides are
383
+ * useful for testing, development, and debugging scenarios.
384
+ *
385
+ * @experimental This interface is experimental and intended for use by LaunchDarkly tools at this time.
386
+ * The API may change in future versions.
387
+ */
388
+ export interface LDDebugOverride {
389
+ /**
390
+ * Set an override value for a flag that takes precedence over the real flag value.
391
+ *
392
+ * @param flagKey The flag key.
393
+ * @param value The override value.
394
+ */
395
+ setOverride(flagKey: string, value: LDFlagValue): void;
396
+
397
+ /**
398
+ * Remove an override value for a flag, reverting to the real flag value.
399
+ *
400
+ * @param flagKey The flag key.
401
+ */
402
+ removeOverride(flagKey: string): void;
403
+
404
+ /**
405
+ * Clear all override values, reverting all flags to their real values.
406
+ */
407
+ clearAllOverrides(): void;
408
+
409
+ /**
410
+ * Get all currently active flag overrides.
411
+ *
412
+ * @returns
413
+ * An object containing all active overrides as key-value pairs,
414
+ * where keys are flag keys and values are the overridden flag values.
415
+ * Returns an empty object if no overrides are active.
416
+ */
417
+ getAllOverrides(): LDFlagSet;
366
418
  }
367
419
 
368
420
  /**
@@ -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 }}