@flopflip/launchdarkly-adapter 13.2.2 → 13.3.0

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.
@@ -0,0 +1,10 @@
1
+ import { type TCacheIdentifiers, type TFlags } from '@flopflip/types';
2
+ import { type LDContext } from 'launchdarkly-js-client-sdk';
3
+ declare const CACHE_PREFIX = "@flopflip/launchdarkly-adapter";
4
+ declare function getCache(cacheIdentifier: TCacheIdentifiers, cacheKey: LDContext['key']): Promise<{
5
+ set(flags: TFlags): any;
6
+ get(): any;
7
+ unset(): any;
8
+ }>;
9
+ declare function getCachedFlags(cacheIdentifier: TCacheIdentifiers): Promise<any>;
10
+ export { CACHE_PREFIX, getCache, getCachedFlags };
@@ -1 +1,2 @@
1
1
  export { default } from "./adapter.js";
2
+ export { getCachedFlags } from "./cache.js";
@@ -1,3 +1,3 @@
1
1
  declare const version = "__@FLOPFLIP/VERSION_OF_RELEASE__";
2
2
  export { version };
3
- export { default } from "./adapter/index.js";
3
+ export { default, getCachedFlags } from "./adapter/index.js";
@@ -40,14 +40,74 @@ var isEqual__default = /*#__PURE__*/_interopDefault(isEqual);
40
40
  var mitt__default = /*#__PURE__*/_interopDefault(mitt);
41
41
  var warning__default = /*#__PURE__*/_interopDefault(warning);
42
42
 
43
- const STORAGE_SLICE = '@flopflip';
43
+ const CACHE_PREFIX = '@flopflip/launchdarkly-adapter';
44
+ const FLAGS_KEY = 'flags';
45
+ const FLAGS_REFERENCE_KEY = 'flags-reference';
46
+ async function importCache(cacheIdentifier) {
47
+ let cacheModule;
48
+ switch (cacheIdentifier) {
49
+ case types.cacheIdentifiers.local:
50
+ {
51
+ cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/localstorage-cache')); });
52
+ break;
53
+ }
54
+ case types.cacheIdentifiers.session:
55
+ {
56
+ cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/sessionstorage-cache')); });
57
+ break;
58
+ }
59
+ }
60
+ return cacheModule;
61
+ }
62
+ async function getCache(cacheIdentifier, cacheKey) {
63
+ const cacheModule = await importCache(cacheIdentifier);
64
+ const createCache = cacheModule.default;
65
+ const flagsCachePrefix = [CACHE_PREFIX, cacheKey].filter(Boolean).join('/');
66
+ const flagsCache = createCache({
67
+ prefix: flagsCachePrefix
68
+ });
69
+ const referenceCache = createCache({
70
+ prefix: CACHE_PREFIX
71
+ });
72
+ return {
73
+ set(flags) {
74
+ const haveFlagsBeenWritten = flagsCache.set(FLAGS_KEY, flags);
75
+ if (haveFlagsBeenWritten) {
76
+ referenceCache.set(FLAGS_REFERENCE_KEY, [flagsCachePrefix, FLAGS_KEY].join('/'));
77
+ }
78
+ return haveFlagsBeenWritten;
79
+ },
80
+ get() {
81
+ return flagsCache.get(FLAGS_KEY);
82
+ },
83
+ unset() {
84
+ referenceCache.unset(FLAGS_REFERENCE_KEY);
85
+ return flagsCache.unset(FLAGS_KEY);
86
+ }
87
+ };
88
+ }
89
+ async function getCachedFlags(cacheIdentifier) {
90
+ const cacheModule = await importCache(cacheIdentifier);
91
+ const createCache = cacheModule.default;
92
+ const referenceCache = createCache({
93
+ prefix: CACHE_PREFIX
94
+ });
95
+ const reference = referenceCache.get(FLAGS_REFERENCE_KEY);
96
+ if (reference) {
97
+ // Cache without prefix as the reference is already prefixed.
98
+ const flagsCache = createCache({
99
+ prefix: ''
100
+ });
101
+ return flagsCache.get(reference);
102
+ }
103
+ }
104
+
44
105
  var _adapterState = /*#__PURE__*/_classPrivateFieldLooseKey("adapterState");
45
106
  var _updateFlagsInAdapterState = /*#__PURE__*/_classPrivateFieldLooseKey("updateFlagsInAdapterState");
46
107
  var _getIsAdapterUnsubscribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAdapterUnsubscribed");
47
108
  var _getIsFlagUnsubcribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagUnsubcribed");
48
109
  var _getIsFlagLocked = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagLocked");
49
110
  var _withoutUnsubscribedOrLockedFlags = /*#__PURE__*/_classPrivateFieldLooseKey("withoutUnsubscribedOrLockedFlags");
50
- var _getCache = /*#__PURE__*/_classPrivateFieldLooseKey("getCache");
51
111
  var _getIsAnonymousContext = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAnonymousContext");
52
112
  var _ensureContext = /*#__PURE__*/_classPrivateFieldLooseKey("ensureContext");
53
113
  var _initializeClient = /*#__PURE__*/_classPrivateFieldLooseKey("initializeClient");
@@ -104,42 +164,6 @@ class LaunchDarklyAdapter {
104
164
  return !_classPrivateFieldLooseBase(this, _getIsFlagUnsubcribed)[_getIsFlagUnsubcribed](flagName) && !_classPrivateFieldLooseBase(this, _getIsFlagLocked)[_getIsFlagLocked](flagName);
105
165
  }))
106
166
  });
107
- Object.defineProperty(this, _getCache, {
108
- writable: true,
109
- value: async (cacheIdentifier, cacheKey) => {
110
- let cacheModule;
111
-
112
- // eslint-disable-next-line default-case, @typescript-eslint/switch-exhaustiveness-check
113
- switch (cacheIdentifier) {
114
- case types.cacheIdentifiers.local:
115
- {
116
- cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/localstorage-cache')); });
117
- break;
118
- }
119
- case types.cacheIdentifiers.session:
120
- {
121
- cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/sessionstorage-cache')); });
122
- break;
123
- }
124
- }
125
- const createCache = cacheModule.default;
126
- const cachePrefix = [STORAGE_SLICE, cacheKey].filter(Boolean).join('/');
127
- const cache = createCache({
128
- prefix: cachePrefix
129
- });
130
- return {
131
- set(flags) {
132
- return cache.set('flags', flags);
133
- },
134
- get() {
135
- return cache.get('flags');
136
- },
137
- unset() {
138
- return cache.unset('flags');
139
- }
140
- };
141
- }
142
- });
143
167
  Object.defineProperty(this, _getIsAnonymousContext, {
144
168
  writable: true,
145
169
  value: context => !(context !== null && context !== void 0 && context.key)
@@ -171,7 +195,8 @@ class LaunchDarklyAdapter {
171
195
  writable: true,
172
196
  value: async _ref5 => {
173
197
  let flags = _ref5.flags,
174
- throwOnInitializationFailure = _ref5.throwOnInitializationFailure;
198
+ throwOnInitializationFailure = _ref5.throwOnInitializationFailure,
199
+ cacheIdentifier = _ref5.cacheIdentifier;
175
200
  if (_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client) {
176
201
  return _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client.waitForInitialization().then(async () => {
177
202
  let flagsFromSdk;
@@ -189,6 +214,11 @@ class LaunchDarklyAdapter {
189
214
  }
190
215
  if (flagsFromSdk) {
191
216
  const normalizedFlags = adapterUtilities.normalizeFlags(flagsFromSdk);
217
+ if (cacheIdentifier) {
218
+ var _classPrivateFieldLoo2;
219
+ const cache = await getCache(cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
220
+ cache.set(normalizedFlags);
221
+ }
192
222
  const flags = _classPrivateFieldLooseBase(this, _withoutUnsubscribedOrLockedFlags)[_withoutUnsubscribedOrLockedFlags](normalizedFlags);
193
223
  this.updateFlags(flags);
194
224
  }
@@ -237,7 +267,6 @@ class LaunchDarklyAdapter {
237
267
  const updatedFlags = {
238
268
  [normalizedFlagName]: normalizedFlagValue
239
269
  };
240
-
241
270
  // NOTE: Adapter state needs to be updated outside of debounced-fn
242
271
  // so that no flag updates are lost.
243
272
  _classPrivateFieldLooseBase(this, _updateFlagsInAdapterState)[_updateFlagsInAdapterState](updatedFlags);
@@ -320,7 +349,7 @@ class LaunchDarklyAdapter {
320
349
  let cachedFlags;
321
350
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](context);
322
351
  if (adapterArgs.cacheIdentifier) {
323
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, context.key);
352
+ const cache = await getCache(adapterArgs.cacheIdentifier, context.key);
324
353
  cachedFlags = cache.get();
325
354
  if (cachedFlags) {
326
355
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].flags = cachedFlags;
@@ -330,18 +359,16 @@ class LaunchDarklyAdapter {
330
359
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client = _classPrivateFieldLooseBase(this, _initializeClient)[_initializeClient](sdk.clientSideId, _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, (_sdk$clientOptions = sdk.clientOptions) !== null && _sdk$clientOptions !== void 0 ? _sdk$clientOptions : {});
331
360
  return _classPrivateFieldLooseBase(this, _getInitialFlags)[_getInitialFlags]({
332
361
  flags,
333
- throwOnInitializationFailure
334
- }).then(async _ref9 => {
362
+ throwOnInitializationFailure,
363
+ cacheIdentifier: adapterArgs.cacheIdentifier
364
+ }).then(_ref9 => {
335
365
  let flagsFromSdk = _ref9.flagsFromSdk,
336
366
  initializationStatus = _ref9.initializationStatus;
337
- if (subscribeToFlagChanges && flagsFromSdk) _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
338
- flagsFromSdk,
339
- flagsUpdateDelayMs
340
- });
341
- if (adapterArgs.cacheIdentifier) {
342
- var _classPrivateFieldLoo2;
343
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
344
- cache.set(flagsFromSdk !== null && flagsFromSdk !== void 0 ? flagsFromSdk : {});
367
+ if (subscribeToFlagChanges && flagsFromSdk) {
368
+ _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
369
+ flagsFromSdk,
370
+ flagsUpdateDelayMs
371
+ });
345
372
  }
346
373
  return {
347
374
  initializationStatus
@@ -350,14 +377,14 @@ class LaunchDarklyAdapter {
350
377
  }
351
378
  async reconfigure(adapterArgs, _adapterEventHandlers) {
352
379
  if (!this.getIsConfigurationStatus(types.AdapterConfigurationStatus.Configured)) return Promise.reject(new Error('@flopflip/launchdarkly-adapter: please configure adapter before reconfiguring.'));
353
- const nextContext = adapterArgs.context;
380
+ const nextContext = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](adapterArgs.context);
354
381
  if (!isEqual__default["default"](_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, nextContext)) {
355
382
  if (adapterArgs.cacheIdentifier) {
356
383
  var _classPrivateFieldLoo3;
357
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
384
+ const cache = await getCache(adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
358
385
  cache.unset();
359
386
  }
360
- _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](nextContext);
387
+ _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = nextContext;
361
388
  await _classPrivateFieldLooseBase(this, _changeClientContext)[_changeClientContext](_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context);
362
389
  return Promise.resolve({
363
390
  initializationStatus: types.AdapterInitializationStatus.Succeeded
@@ -392,7 +419,8 @@ class LaunchDarklyAdapter {
392
419
  const adapter = new LaunchDarklyAdapter();
393
420
  adapterUtilities.exposeGlobally(adapter);
394
421
 
395
- const version = "13.2.2";
422
+ const version = "13.3.0";
396
423
 
397
424
  exports["default"] = adapter;
425
+ exports.getCachedFlags = getCachedFlags;
398
426
  exports.version = version;
@@ -40,14 +40,74 @@ var isEqual__default = /*#__PURE__*/_interopDefault(isEqual);
40
40
  var mitt__default = /*#__PURE__*/_interopDefault(mitt);
41
41
  var warning__default = /*#__PURE__*/_interopDefault(warning);
42
42
 
43
- const STORAGE_SLICE = '@flopflip';
43
+ const CACHE_PREFIX = '@flopflip/launchdarkly-adapter';
44
+ const FLAGS_KEY = 'flags';
45
+ const FLAGS_REFERENCE_KEY = 'flags-reference';
46
+ async function importCache(cacheIdentifier) {
47
+ let cacheModule;
48
+ switch (cacheIdentifier) {
49
+ case types.cacheIdentifiers.local:
50
+ {
51
+ cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/localstorage-cache')); });
52
+ break;
53
+ }
54
+ case types.cacheIdentifiers.session:
55
+ {
56
+ cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/sessionstorage-cache')); });
57
+ break;
58
+ }
59
+ }
60
+ return cacheModule;
61
+ }
62
+ async function getCache(cacheIdentifier, cacheKey) {
63
+ const cacheModule = await importCache(cacheIdentifier);
64
+ const createCache = cacheModule.default;
65
+ const flagsCachePrefix = [CACHE_PREFIX, cacheKey].filter(Boolean).join('/');
66
+ const flagsCache = createCache({
67
+ prefix: flagsCachePrefix
68
+ });
69
+ const referenceCache = createCache({
70
+ prefix: CACHE_PREFIX
71
+ });
72
+ return {
73
+ set(flags) {
74
+ const haveFlagsBeenWritten = flagsCache.set(FLAGS_KEY, flags);
75
+ if (haveFlagsBeenWritten) {
76
+ referenceCache.set(FLAGS_REFERENCE_KEY, [flagsCachePrefix, FLAGS_KEY].join('/'));
77
+ }
78
+ return haveFlagsBeenWritten;
79
+ },
80
+ get() {
81
+ return flagsCache.get(FLAGS_KEY);
82
+ },
83
+ unset() {
84
+ referenceCache.unset(FLAGS_REFERENCE_KEY);
85
+ return flagsCache.unset(FLAGS_KEY);
86
+ }
87
+ };
88
+ }
89
+ async function getCachedFlags(cacheIdentifier) {
90
+ const cacheModule = await importCache(cacheIdentifier);
91
+ const createCache = cacheModule.default;
92
+ const referenceCache = createCache({
93
+ prefix: CACHE_PREFIX
94
+ });
95
+ const reference = referenceCache.get(FLAGS_REFERENCE_KEY);
96
+ if (reference) {
97
+ // Cache without prefix as the reference is already prefixed.
98
+ const flagsCache = createCache({
99
+ prefix: ''
100
+ });
101
+ return flagsCache.get(reference);
102
+ }
103
+ }
104
+
44
105
  var _adapterState = /*#__PURE__*/_classPrivateFieldLooseKey("adapterState");
45
106
  var _updateFlagsInAdapterState = /*#__PURE__*/_classPrivateFieldLooseKey("updateFlagsInAdapterState");
46
107
  var _getIsAdapterUnsubscribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAdapterUnsubscribed");
47
108
  var _getIsFlagUnsubcribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagUnsubcribed");
48
109
  var _getIsFlagLocked = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagLocked");
49
110
  var _withoutUnsubscribedOrLockedFlags = /*#__PURE__*/_classPrivateFieldLooseKey("withoutUnsubscribedOrLockedFlags");
50
- var _getCache = /*#__PURE__*/_classPrivateFieldLooseKey("getCache");
51
111
  var _getIsAnonymousContext = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAnonymousContext");
52
112
  var _ensureContext = /*#__PURE__*/_classPrivateFieldLooseKey("ensureContext");
53
113
  var _initializeClient = /*#__PURE__*/_classPrivateFieldLooseKey("initializeClient");
@@ -104,42 +164,6 @@ class LaunchDarklyAdapter {
104
164
  return !_classPrivateFieldLooseBase(this, _getIsFlagUnsubcribed)[_getIsFlagUnsubcribed](flagName) && !_classPrivateFieldLooseBase(this, _getIsFlagLocked)[_getIsFlagLocked](flagName);
105
165
  }))
106
166
  });
107
- Object.defineProperty(this, _getCache, {
108
- writable: true,
109
- value: async (cacheIdentifier, cacheKey) => {
110
- let cacheModule;
111
-
112
- // eslint-disable-next-line default-case, @typescript-eslint/switch-exhaustiveness-check
113
- switch (cacheIdentifier) {
114
- case types.cacheIdentifiers.local:
115
- {
116
- cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/localstorage-cache')); });
117
- break;
118
- }
119
- case types.cacheIdentifiers.session:
120
- {
121
- cacheModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@flopflip/sessionstorage-cache')); });
122
- break;
123
- }
124
- }
125
- const createCache = cacheModule.default;
126
- const cachePrefix = [STORAGE_SLICE, cacheKey].filter(Boolean).join('/');
127
- const cache = createCache({
128
- prefix: cachePrefix
129
- });
130
- return {
131
- set(flags) {
132
- return cache.set('flags', flags);
133
- },
134
- get() {
135
- return cache.get('flags');
136
- },
137
- unset() {
138
- return cache.unset('flags');
139
- }
140
- };
141
- }
142
- });
143
167
  Object.defineProperty(this, _getIsAnonymousContext, {
144
168
  writable: true,
145
169
  value: context => !(context !== null && context !== void 0 && context.key)
@@ -171,7 +195,8 @@ class LaunchDarklyAdapter {
171
195
  writable: true,
172
196
  value: async _ref5 => {
173
197
  let flags = _ref5.flags,
174
- throwOnInitializationFailure = _ref5.throwOnInitializationFailure;
198
+ throwOnInitializationFailure = _ref5.throwOnInitializationFailure,
199
+ cacheIdentifier = _ref5.cacheIdentifier;
175
200
  if (_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client) {
176
201
  return _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client.waitForInitialization().then(async () => {
177
202
  let flagsFromSdk;
@@ -189,6 +214,11 @@ class LaunchDarklyAdapter {
189
214
  }
190
215
  if (flagsFromSdk) {
191
216
  const normalizedFlags = adapterUtilities.normalizeFlags(flagsFromSdk);
217
+ if (cacheIdentifier) {
218
+ var _classPrivateFieldLoo2;
219
+ const cache = await getCache(cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
220
+ cache.set(normalizedFlags);
221
+ }
192
222
  const flags = _classPrivateFieldLooseBase(this, _withoutUnsubscribedOrLockedFlags)[_withoutUnsubscribedOrLockedFlags](normalizedFlags);
193
223
  this.updateFlags(flags);
194
224
  }
@@ -237,7 +267,6 @@ class LaunchDarklyAdapter {
237
267
  const updatedFlags = {
238
268
  [normalizedFlagName]: normalizedFlagValue
239
269
  };
240
-
241
270
  // NOTE: Adapter state needs to be updated outside of debounced-fn
242
271
  // so that no flag updates are lost.
243
272
  _classPrivateFieldLooseBase(this, _updateFlagsInAdapterState)[_updateFlagsInAdapterState](updatedFlags);
@@ -320,7 +349,7 @@ class LaunchDarklyAdapter {
320
349
  let cachedFlags;
321
350
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](context);
322
351
  if (adapterArgs.cacheIdentifier) {
323
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, context.key);
352
+ const cache = await getCache(adapterArgs.cacheIdentifier, context.key);
324
353
  cachedFlags = cache.get();
325
354
  if (cachedFlags) {
326
355
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].flags = cachedFlags;
@@ -330,18 +359,16 @@ class LaunchDarklyAdapter {
330
359
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client = _classPrivateFieldLooseBase(this, _initializeClient)[_initializeClient](sdk.clientSideId, _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, (_sdk$clientOptions = sdk.clientOptions) !== null && _sdk$clientOptions !== void 0 ? _sdk$clientOptions : {});
331
360
  return _classPrivateFieldLooseBase(this, _getInitialFlags)[_getInitialFlags]({
332
361
  flags,
333
- throwOnInitializationFailure
334
- }).then(async _ref9 => {
362
+ throwOnInitializationFailure,
363
+ cacheIdentifier: adapterArgs.cacheIdentifier
364
+ }).then(_ref9 => {
335
365
  let flagsFromSdk = _ref9.flagsFromSdk,
336
366
  initializationStatus = _ref9.initializationStatus;
337
- if (subscribeToFlagChanges && flagsFromSdk) _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
338
- flagsFromSdk,
339
- flagsUpdateDelayMs
340
- });
341
- if (adapterArgs.cacheIdentifier) {
342
- var _classPrivateFieldLoo2;
343
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
344
- cache.set(flagsFromSdk !== null && flagsFromSdk !== void 0 ? flagsFromSdk : {});
367
+ if (subscribeToFlagChanges && flagsFromSdk) {
368
+ _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
369
+ flagsFromSdk,
370
+ flagsUpdateDelayMs
371
+ });
345
372
  }
346
373
  return {
347
374
  initializationStatus
@@ -350,14 +377,14 @@ class LaunchDarklyAdapter {
350
377
  }
351
378
  async reconfigure(adapterArgs, _adapterEventHandlers) {
352
379
  if (!this.getIsConfigurationStatus(types.AdapterConfigurationStatus.Configured)) return Promise.reject(new Error('@flopflip/launchdarkly-adapter: please configure adapter before reconfiguring.'));
353
- const nextContext = adapterArgs.context;
380
+ const nextContext = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](adapterArgs.context);
354
381
  if (!isEqual__default["default"](_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, nextContext)) {
355
382
  if (adapterArgs.cacheIdentifier) {
356
383
  var _classPrivateFieldLoo3;
357
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
384
+ const cache = await getCache(adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
358
385
  cache.unset();
359
386
  }
360
- _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](nextContext);
387
+ _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = nextContext;
361
388
  await _classPrivateFieldLooseBase(this, _changeClientContext)[_changeClientContext](_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context);
362
389
  return Promise.resolve({
363
390
  initializationStatus: types.AdapterInitializationStatus.Succeeded
@@ -392,7 +419,8 @@ class LaunchDarklyAdapter {
392
419
  const adapter = new LaunchDarklyAdapter();
393
420
  adapterUtilities.exposeGlobally(adapter);
394
421
 
395
- const version = "13.2.2";
422
+ const version = "13.3.0";
396
423
 
397
424
  exports["default"] = adapter;
425
+ exports.getCachedFlags = getCachedFlags;
398
426
  exports.version = version;
@@ -3,7 +3,7 @@ import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
3
3
  import _classPrivateFieldLooseBase from '@babel/runtime/helpers/esm/classPrivateFieldLooseBase';
4
4
  import _classPrivateFieldLooseKey from '@babel/runtime/helpers/esm/classPrivateFieldLooseKey';
5
5
  import { exposeGlobally, denormalizeFlagName, normalizeFlags, normalizeFlag } from '@flopflip/adapter-utilities';
6
- import { AdapterSubscriptionStatus, cacheIdentifiers, AdapterConfigurationStatus, AdapterInitializationStatus, adapterIdentifiers } from '@flopflip/types';
6
+ import { cacheIdentifiers, AdapterSubscriptionStatus, AdapterConfigurationStatus, AdapterInitializationStatus, adapterIdentifiers } from '@flopflip/types';
7
7
  import debounce from 'debounce-fn';
8
8
  import { initialize } from 'launchdarkly-js-client-sdk';
9
9
  import isEqual from 'lodash/isEqual';
@@ -11,14 +11,74 @@ import mitt from 'mitt';
11
11
  import warning from 'tiny-warning';
12
12
  import { merge } from 'ts-deepmerge';
13
13
 
14
- const STORAGE_SLICE = '@flopflip';
14
+ const CACHE_PREFIX = '@flopflip/launchdarkly-adapter';
15
+ const FLAGS_KEY = 'flags';
16
+ const FLAGS_REFERENCE_KEY = 'flags-reference';
17
+ async function importCache(cacheIdentifier) {
18
+ let cacheModule;
19
+ switch (cacheIdentifier) {
20
+ case cacheIdentifiers.local:
21
+ {
22
+ cacheModule = await import('@flopflip/localstorage-cache');
23
+ break;
24
+ }
25
+ case cacheIdentifiers.session:
26
+ {
27
+ cacheModule = await import('@flopflip/sessionstorage-cache');
28
+ break;
29
+ }
30
+ }
31
+ return cacheModule;
32
+ }
33
+ async function getCache(cacheIdentifier, cacheKey) {
34
+ const cacheModule = await importCache(cacheIdentifier);
35
+ const createCache = cacheModule.default;
36
+ const flagsCachePrefix = [CACHE_PREFIX, cacheKey].filter(Boolean).join('/');
37
+ const flagsCache = createCache({
38
+ prefix: flagsCachePrefix
39
+ });
40
+ const referenceCache = createCache({
41
+ prefix: CACHE_PREFIX
42
+ });
43
+ return {
44
+ set(flags) {
45
+ const haveFlagsBeenWritten = flagsCache.set(FLAGS_KEY, flags);
46
+ if (haveFlagsBeenWritten) {
47
+ referenceCache.set(FLAGS_REFERENCE_KEY, [flagsCachePrefix, FLAGS_KEY].join('/'));
48
+ }
49
+ return haveFlagsBeenWritten;
50
+ },
51
+ get() {
52
+ return flagsCache.get(FLAGS_KEY);
53
+ },
54
+ unset() {
55
+ referenceCache.unset(FLAGS_REFERENCE_KEY);
56
+ return flagsCache.unset(FLAGS_KEY);
57
+ }
58
+ };
59
+ }
60
+ async function getCachedFlags(cacheIdentifier) {
61
+ const cacheModule = await importCache(cacheIdentifier);
62
+ const createCache = cacheModule.default;
63
+ const referenceCache = createCache({
64
+ prefix: CACHE_PREFIX
65
+ });
66
+ const reference = referenceCache.get(FLAGS_REFERENCE_KEY);
67
+ if (reference) {
68
+ // Cache without prefix as the reference is already prefixed.
69
+ const flagsCache = createCache({
70
+ prefix: ''
71
+ });
72
+ return flagsCache.get(reference);
73
+ }
74
+ }
75
+
15
76
  var _adapterState = /*#__PURE__*/_classPrivateFieldLooseKey("adapterState");
16
77
  var _updateFlagsInAdapterState = /*#__PURE__*/_classPrivateFieldLooseKey("updateFlagsInAdapterState");
17
78
  var _getIsAdapterUnsubscribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAdapterUnsubscribed");
18
79
  var _getIsFlagUnsubcribed = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagUnsubcribed");
19
80
  var _getIsFlagLocked = /*#__PURE__*/_classPrivateFieldLooseKey("getIsFlagLocked");
20
81
  var _withoutUnsubscribedOrLockedFlags = /*#__PURE__*/_classPrivateFieldLooseKey("withoutUnsubscribedOrLockedFlags");
21
- var _getCache = /*#__PURE__*/_classPrivateFieldLooseKey("getCache");
22
82
  var _getIsAnonymousContext = /*#__PURE__*/_classPrivateFieldLooseKey("getIsAnonymousContext");
23
83
  var _ensureContext = /*#__PURE__*/_classPrivateFieldLooseKey("ensureContext");
24
84
  var _initializeClient = /*#__PURE__*/_classPrivateFieldLooseKey("initializeClient");
@@ -75,42 +135,6 @@ class LaunchDarklyAdapter {
75
135
  return !_classPrivateFieldLooseBase(this, _getIsFlagUnsubcribed)[_getIsFlagUnsubcribed](flagName) && !_classPrivateFieldLooseBase(this, _getIsFlagLocked)[_getIsFlagLocked](flagName);
76
136
  }))
77
137
  });
78
- Object.defineProperty(this, _getCache, {
79
- writable: true,
80
- value: async (cacheIdentifier, cacheKey) => {
81
- let cacheModule;
82
-
83
- // eslint-disable-next-line default-case, @typescript-eslint/switch-exhaustiveness-check
84
- switch (cacheIdentifier) {
85
- case cacheIdentifiers.local:
86
- {
87
- cacheModule = await import('@flopflip/localstorage-cache');
88
- break;
89
- }
90
- case cacheIdentifiers.session:
91
- {
92
- cacheModule = await import('@flopflip/sessionstorage-cache');
93
- break;
94
- }
95
- }
96
- const createCache = cacheModule.default;
97
- const cachePrefix = [STORAGE_SLICE, cacheKey].filter(Boolean).join('/');
98
- const cache = createCache({
99
- prefix: cachePrefix
100
- });
101
- return {
102
- set(flags) {
103
- return cache.set('flags', flags);
104
- },
105
- get() {
106
- return cache.get('flags');
107
- },
108
- unset() {
109
- return cache.unset('flags');
110
- }
111
- };
112
- }
113
- });
114
138
  Object.defineProperty(this, _getIsAnonymousContext, {
115
139
  writable: true,
116
140
  value: context => !(context !== null && context !== void 0 && context.key)
@@ -142,7 +166,8 @@ class LaunchDarklyAdapter {
142
166
  writable: true,
143
167
  value: async _ref5 => {
144
168
  let flags = _ref5.flags,
145
- throwOnInitializationFailure = _ref5.throwOnInitializationFailure;
169
+ throwOnInitializationFailure = _ref5.throwOnInitializationFailure,
170
+ cacheIdentifier = _ref5.cacheIdentifier;
146
171
  if (_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client) {
147
172
  return _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client.waitForInitialization().then(async () => {
148
173
  let flagsFromSdk;
@@ -160,6 +185,11 @@ class LaunchDarklyAdapter {
160
185
  }
161
186
  if (flagsFromSdk) {
162
187
  const normalizedFlags = normalizeFlags(flagsFromSdk);
188
+ if (cacheIdentifier) {
189
+ var _classPrivateFieldLoo2;
190
+ const cache = await getCache(cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
191
+ cache.set(normalizedFlags);
192
+ }
163
193
  const flags = _classPrivateFieldLooseBase(this, _withoutUnsubscribedOrLockedFlags)[_withoutUnsubscribedOrLockedFlags](normalizedFlags);
164
194
  this.updateFlags(flags);
165
195
  }
@@ -208,7 +238,6 @@ class LaunchDarklyAdapter {
208
238
  const updatedFlags = {
209
239
  [normalizedFlagName]: normalizedFlagValue
210
240
  };
211
-
212
241
  // NOTE: Adapter state needs to be updated outside of debounced-fn
213
242
  // so that no flag updates are lost.
214
243
  _classPrivateFieldLooseBase(this, _updateFlagsInAdapterState)[_updateFlagsInAdapterState](updatedFlags);
@@ -291,7 +320,7 @@ class LaunchDarklyAdapter {
291
320
  let cachedFlags;
292
321
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](context);
293
322
  if (adapterArgs.cacheIdentifier) {
294
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, context.key);
323
+ const cache = await getCache(adapterArgs.cacheIdentifier, context.key);
295
324
  cachedFlags = cache.get();
296
325
  if (cachedFlags) {
297
326
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].flags = cachedFlags;
@@ -301,18 +330,16 @@ class LaunchDarklyAdapter {
301
330
  _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].client = _classPrivateFieldLooseBase(this, _initializeClient)[_initializeClient](sdk.clientSideId, _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, (_sdk$clientOptions = sdk.clientOptions) !== null && _sdk$clientOptions !== void 0 ? _sdk$clientOptions : {});
302
331
  return _classPrivateFieldLooseBase(this, _getInitialFlags)[_getInitialFlags]({
303
332
  flags,
304
- throwOnInitializationFailure
305
- }).then(async _ref9 => {
333
+ throwOnInitializationFailure,
334
+ cacheIdentifier: adapterArgs.cacheIdentifier
335
+ }).then(_ref9 => {
306
336
  let flagsFromSdk = _ref9.flagsFromSdk,
307
337
  initializationStatus = _ref9.initializationStatus;
308
- if (subscribeToFlagChanges && flagsFromSdk) _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
309
- flagsFromSdk,
310
- flagsUpdateDelayMs
311
- });
312
- if (adapterArgs.cacheIdentifier) {
313
- var _classPrivateFieldLoo2;
314
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo2 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo2 === void 0 ? void 0 : _classPrivateFieldLoo2.key);
315
- cache.set(flagsFromSdk !== null && flagsFromSdk !== void 0 ? flagsFromSdk : {});
338
+ if (subscribeToFlagChanges && flagsFromSdk) {
339
+ _classPrivateFieldLooseBase(this, _setupFlagSubcription)[_setupFlagSubcription]({
340
+ flagsFromSdk,
341
+ flagsUpdateDelayMs
342
+ });
316
343
  }
317
344
  return {
318
345
  initializationStatus
@@ -321,14 +348,14 @@ class LaunchDarklyAdapter {
321
348
  }
322
349
  async reconfigure(adapterArgs, _adapterEventHandlers) {
323
350
  if (!this.getIsConfigurationStatus(AdapterConfigurationStatus.Configured)) return Promise.reject(new Error('@flopflip/launchdarkly-adapter: please configure adapter before reconfiguring.'));
324
- const nextContext = adapterArgs.context;
351
+ const nextContext = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](adapterArgs.context);
325
352
  if (!isEqual(_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context, nextContext)) {
326
353
  if (adapterArgs.cacheIdentifier) {
327
354
  var _classPrivateFieldLoo3;
328
- const cache = await _classPrivateFieldLooseBase(this, _getCache)[_getCache](adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
355
+ const cache = await getCache(adapterArgs.cacheIdentifier, (_classPrivateFieldLoo3 = _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context) === null || _classPrivateFieldLoo3 === void 0 ? void 0 : _classPrivateFieldLoo3.key);
329
356
  cache.unset();
330
357
  }
331
- _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = _classPrivateFieldLooseBase(this, _ensureContext)[_ensureContext](nextContext);
358
+ _classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context = nextContext;
332
359
  await _classPrivateFieldLooseBase(this, _changeClientContext)[_changeClientContext](_classPrivateFieldLooseBase(this, _adapterState)[_adapterState].context);
333
360
  return Promise.resolve({
334
361
  initializationStatus: AdapterInitializationStatus.Succeeded
@@ -363,6 +390,6 @@ class LaunchDarklyAdapter {
363
390
  const adapter = new LaunchDarklyAdapter();
364
391
  exposeGlobally(adapter);
365
392
 
366
- const version = "13.2.2";
393
+ const version = "13.3.0";
367
394
 
368
- export { adapter as default, version };
395
+ export { adapter as default, getCachedFlags, version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flopflip/launchdarkly-adapter",
3
- "version": "13.2.2",
3
+ "version": "13.3.0",
4
4
  "description": "A adapter around the LaunchDarkly client for flipflop",
5
5
  "main": "dist/flopflip-launchdarkly-adapter.cjs.js",
6
6
  "module": "dist/flopflip-launchdarkly-adapter.esm.js",
@@ -27,10 +27,10 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@babel/runtime": "7.24.0",
30
- "@flopflip/adapter-utilities": "13.2.2",
31
- "@flopflip/localstorage-cache": "13.2.2",
32
- "@flopflip/sessionstorage-cache": "13.2.2",
33
- "@flopflip/types": "13.2.2",
30
+ "@flopflip/adapter-utilities": "13.3.0",
31
+ "@flopflip/localstorage-cache": "13.3.0",
32
+ "@flopflip/sessionstorage-cache": "13.3.0",
33
+ "@flopflip/types": "13.3.0",
34
34
  "debounce-fn": "4.0.0",
35
35
  "launchdarkly-js-client-sdk": "3.1.4",
36
36
  "lodash": "4.17.21",