capacitor-launchdarkly 0.0.0-stage → 0.1.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.
Files changed (40) hide show
  1. package/CapacitorLaunchdarkly.podspec +20 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +32 -0
  4. package/README.md +747 -2
  5. package/android/build.gradle +68 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/Json.kt +67 -0
  8. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/LaunchDarklyClient.kt +250 -0
  9. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/LaunchDarklyPlugin.kt +148 -0
  10. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/LdConfigFactory.kt +34 -0
  11. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/StartOptions.kt +76 -0
  12. package/android/src/main/kotlin/io/github/maximbelov/launchdarkly/StoredContext.kt +47 -0
  13. package/android/src/main/res/.gitkeep +0 -0
  14. package/dist/docs.json +1174 -0
  15. package/dist/esm/definitions.d.ts +520 -0
  16. package/dist/esm/definitions.js +2 -0
  17. package/dist/esm/definitions.js.map +1 -0
  18. package/dist/esm/index.d.ts +4 -0
  19. package/dist/esm/index.js +7 -0
  20. package/dist/esm/index.js.map +1 -0
  21. package/dist/esm/web.d.ts +46 -0
  22. package/dist/esm/web.js +204 -0
  23. package/dist/esm/web.js.map +1 -0
  24. package/dist/plugin.cjs.js +221 -0
  25. package/dist/plugin.cjs.js.map +1 -0
  26. package/dist/plugin.js +224 -0
  27. package/dist/plugin.js.map +1 -0
  28. package/ios/Sources/LaunchDarklyPlugin/ConfigFactory.swift +29 -0
  29. package/ios/Sources/LaunchDarklyPlugin/JSONValues.swift +68 -0
  30. package/ios/Sources/LaunchDarklyPlugin/LaunchDarklyClient.swift +165 -0
  31. package/ios/Sources/LaunchDarklyPlugin/LaunchDarklyPlugin.swift +169 -0
  32. package/ios/Sources/LaunchDarklyPlugin/PrivacyInfo.xcprivacy +23 -0
  33. package/ios/Sources/LaunchDarklyPlugin/StartOptions.swift +79 -0
  34. package/ios/Sources/LaunchDarklyPlugin/StoredContext.swift +43 -0
  35. package/ios/Tests/LaunchDarklyPluginTests/BillingSafetyTests.swift +53 -0
  36. package/ios/Tests/LaunchDarklyPluginTests/JSONValuesTests.swift +67 -0
  37. package/ios/Tests/LaunchDarklyPluginTests/LaunchDarklyPluginTests.swift +37 -0
  38. package/ios/Tests/LaunchDarklyPluginTests/PluginConfigurationTests.swift +52 -0
  39. package/ios/Tests/LaunchDarklyPluginTests/StartContextTests.swift +36 -0
  40. package/package.json +105 -4
@@ -0,0 +1,204 @@
1
+ import { WebPlugin } from '@capacitor/core';
2
+ /** The key the plugin keeps the context of the last `identify()` under in `localStorage`. */
3
+ export const STORED_CONTEXT_KEY = 'CapacitorLaunchDarkly.context';
4
+ const DEFAULT_WAIT_SECONDS = 5;
5
+ export const MISSING_SDK_MESSAGE = 'The LaunchDarkly web SDK is not installed. To use this plugin on the web, run: npm install @launchdarkly/js-client-sdk';
6
+ // Imported only when a web app starts the client, so a native-only app never loads it.
7
+ const importSdk = () => import('@launchdarkly/js-client-sdk');
8
+ /**
9
+ * The web implementation, on LaunchDarkly's browser SDK. It follows the native rules: one client per page, a context the
10
+ * caller gave with its key (an anonymous context without a key is refused rather than given a generated one), and a context
11
+ * stored by `identify()` that wins over the one `initialize()` is given.
12
+ */
13
+ export class LaunchDarklyWeb extends WebPlugin {
14
+ constructor(loadSdk = importSdk) {
15
+ super();
16
+ this.loadSdk = loadSdk;
17
+ this.options = {};
18
+ this.initialized = false;
19
+ this.lastValues = {};
20
+ }
21
+ async initialize(options) {
22
+ var _a, _b, _c, _d;
23
+ const clientSideId = options === null || options === void 0 ? void 0 : options.clientSideId;
24
+ if (!clientSideId)
25
+ throw new Error('initialize needs a clientSideId on the web.');
26
+ if (this.clientSideId === clientSideId) {
27
+ await this.starting;
28
+ return this.state();
29
+ }
30
+ requireKeys(options.context);
31
+ const sdk = await this.sdk();
32
+ if (this.client)
33
+ await this.close();
34
+ const startOptions = (_a = options.options) !== null && _a !== void 0 ? _a : {};
35
+ // The given context plays the part of initialContext: a context an earlier identify() stored wins over it.
36
+ const context = (_b = readStoredContext()) !== null && _b !== void 0 ? _b : options.context;
37
+ const streaming = ((_c = startOptions.streaming) !== null && _c !== void 0 ? _c : true) && !startOptions.offline;
38
+ const client = sdk.createClient(clientSideId, context, Object.assign({ streaming, withReasons: (_d = startOptions.evaluationReasons) !== null && _d !== void 0 ? _d : false }, (startOptions.application ? { applicationInfo: startOptions.application } : {})));
39
+ this.client = client;
40
+ this.clientSideId = clientSideId;
41
+ this.options = startOptions;
42
+ this.context = context;
43
+ this.initialized = false;
44
+ client.on('change', (_context, keys) => this.flagsChanged(client, keys));
45
+ const bootstrap = startOptions.bootstrap;
46
+ this.starting = client
47
+ .start(Object.assign({ timeout: seconds(startOptions.startWaitSeconds) }, (bootstrap && bootstrap !== 'localStorage' ? { bootstrap } : {})))
48
+ .then((result) => {
49
+ if (this.client !== client)
50
+ return;
51
+ this.initialized = result.status === 'complete';
52
+ this.lastValues = Object.assign({}, client.allFlags());
53
+ });
54
+ await this.starting;
55
+ return this.state();
56
+ }
57
+ async waitForInitialization(options) {
58
+ const client = this.client;
59
+ if (!client)
60
+ return { initialized: false };
61
+ if (!this.initialized) {
62
+ const result = await client.waitForInitialization({ timeout: seconds(options === null || options === void 0 ? void 0 : options.timeoutSeconds) });
63
+ if (this.client === client && result.status === 'complete')
64
+ this.initialized = true;
65
+ }
66
+ return { initialized: this.initialized };
67
+ }
68
+ async getState() {
69
+ await this.starting;
70
+ return this.state();
71
+ }
72
+ async identify(options) {
73
+ const client = this.started();
74
+ requireKeys(options === null || options === void 0 ? void 0 : options.context);
75
+ const result = await client.identify(options.context, { timeout: seconds(options.timeoutSeconds) });
76
+ if (result.status === 'error' || result.status === 'shed') {
77
+ throw new Error(result.status === 'shed' ? 'identify was replaced by a later identify' : 'identify failed');
78
+ }
79
+ // On a timeout the SDK has switched to the context and keeps loading its flags; only the wait is over.
80
+ this.context = options.context;
81
+ writeStoredContext(options.context);
82
+ return { timedOut: result.status === 'timeout' };
83
+ }
84
+ async variation(options) {
85
+ var _a;
86
+ const defaultValue = (_a = options.defaultValue) !== null && _a !== void 0 ? _a : null;
87
+ const value = this.client ? this.client.jsonVariation(options.key, defaultValue) : defaultValue;
88
+ return { value: value !== null && value !== void 0 ? value : null };
89
+ }
90
+ async allFlags() {
91
+ return { flags: this.client ? Object.assign({}, this.client.allFlags()) : {} };
92
+ }
93
+ async setStreaming(options) {
94
+ const client = this.started();
95
+ this.options = Object.assign(Object.assign({}, this.options), { streaming: options.enabled });
96
+ client.setStreaming(options.enabled);
97
+ }
98
+ async setOnline(options) {
99
+ var _a;
100
+ // The browser SDK has no offline mode: offline closes the stream, online opens it again when streaming is on.
101
+ const client = this.started();
102
+ client.setStreaming(options.online ? ((_a = this.options.streaming) !== null && _a !== void 0 ? _a : true) : false);
103
+ }
104
+ async flush() {
105
+ var _a;
106
+ await ((_a = this.client) === null || _a === void 0 ? void 0 : _a.flush());
107
+ }
108
+ async close() {
109
+ const client = this.client;
110
+ this.client = undefined;
111
+ this.clientSideId = undefined;
112
+ this.context = undefined;
113
+ this.initialized = false;
114
+ this.starting = undefined;
115
+ this.lastValues = {};
116
+ await (client === null || client === void 0 ? void 0 : client.close());
117
+ }
118
+ async clearStoredContext() {
119
+ try {
120
+ localStorage.removeItem(STORED_CONTEXT_KEY);
121
+ }
122
+ catch (_a) {
123
+ // No storage (a private window, blocked site data): nothing was stored either.
124
+ }
125
+ }
126
+ async sdk() {
127
+ try {
128
+ return await this.loadSdk();
129
+ }
130
+ catch (error) {
131
+ throw new Error(`${MISSING_SDK_MESSAGE} (${error instanceof Error ? error.message : String(error)})`, {
132
+ cause: error,
133
+ });
134
+ }
135
+ }
136
+ started() {
137
+ if (!this.client)
138
+ throw new Error('The client is not started.');
139
+ return this.client;
140
+ }
141
+ state() {
142
+ return Object.assign({ initialized: this.initialized, flags: this.client ? Object.assign({}, this.client.allFlags()) : {} }, (this.context ? { context: this.context } : {}));
143
+ }
144
+ flagsChanged(client, keys) {
145
+ if (this.client !== client)
146
+ return;
147
+ const flags = client.allFlags();
148
+ for (const key of keys) {
149
+ const value = key in flags ? flags[key] : null;
150
+ const hadPrevious = key in this.lastValues;
151
+ const previous = this.lastValues[key];
152
+ if (key in flags)
153
+ this.lastValues[key] = flags[key];
154
+ else
155
+ delete this.lastValues[key];
156
+ this.notifyListeners('flagChange', hadPrevious ? { key, value, previous } : { key, value });
157
+ }
158
+ }
159
+ }
160
+ function seconds(value) {
161
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : DEFAULT_WAIT_SECONDS;
162
+ }
163
+ /**
164
+ * Refuses a context whose key (or the key of any kind in a multi-context) is missing or empty. The browser SDK would generate
165
+ * one for an anonymous context, stored per browser, and every browser would then count as a context of its own.
166
+ */
167
+ export function requireKeys(context) {
168
+ var _a;
169
+ if (!context || typeof context !== 'object')
170
+ throw new Error('A context is needed.');
171
+ const parts = context.kind === 'multi'
172
+ ? Object.entries(context).filter(([kind]) => kind !== 'kind')
173
+ : [[String((_a = context.kind) !== null && _a !== void 0 ? _a : 'user'), context]];
174
+ if (parts.length === 0)
175
+ throw new Error('Invalid context: a multi-context needs at least one kind.');
176
+ for (const [kind, part] of parts) {
177
+ const key = part === null || part === void 0 ? void 0 : part.key;
178
+ if (typeof key !== 'string' || key === '') {
179
+ throw new Error(`Invalid context: the ${kind} context has no key. Pass one, also for an anonymous context.`);
180
+ }
181
+ }
182
+ }
183
+ function readStoredContext() {
184
+ try {
185
+ const json = localStorage.getItem(STORED_CONTEXT_KEY);
186
+ if (!json)
187
+ return undefined;
188
+ const context = JSON.parse(json);
189
+ requireKeys(context);
190
+ return context;
191
+ }
192
+ catch (_a) {
193
+ return undefined;
194
+ }
195
+ }
196
+ function writeStoredContext(context) {
197
+ try {
198
+ localStorage.setItem(STORED_CONTEXT_KEY, JSON.stringify(context));
199
+ }
200
+ catch (_a) {
201
+ // No storage: the next start begins with the context initialize() is given.
202
+ }
203
+ }
204
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport type { LDClient, LDOptions } from '@launchdarkly/js-client-sdk';\n\nimport type {\n AllFlagsResult,\n IdentifyOptions,\n IdentifyResult,\n InitializeOptions,\n LaunchDarklyOptions,\n LaunchDarklyPlugin,\n LaunchDarklyState,\n LDContext,\n LDFlagSet,\n SetOnlineOptions,\n SetStreamingOptions,\n VariationOptions,\n VariationResult,\n WaitForInitializationOptions,\n WaitForInitializationResult,\n} from './definitions';\n\n/** The part of `@launchdarkly/js-client-sdk` the plugin uses. */\nexport interface WebSdk {\n createClient(clientSideId: string, context: LDContext, options?: LDOptions): LDClient;\n}\n\n/** The key the plugin keeps the context of the last `identify()` under in `localStorage`. */\nexport const STORED_CONTEXT_KEY = 'CapacitorLaunchDarkly.context';\n\nconst DEFAULT_WAIT_SECONDS = 5;\n\nexport const MISSING_SDK_MESSAGE =\n 'The LaunchDarkly web SDK is not installed. To use this plugin on the web, run: npm install @launchdarkly/js-client-sdk';\n\n// Imported only when a web app starts the client, so a native-only app never loads it.\nconst importSdk = (): Promise<WebSdk> => import('@launchdarkly/js-client-sdk');\n\n/**\n * The web implementation, on LaunchDarkly's browser SDK. It follows the native rules: one client per page, a context the\n * caller gave with its key (an anonymous context without a key is refused rather than given a generated one), and a context\n * stored by `identify()` that wins over the one `initialize()` is given.\n */\nexport class LaunchDarklyWeb extends WebPlugin implements LaunchDarklyPlugin {\n private client?: LDClient;\n private clientSideId?: string;\n private options: LaunchDarklyOptions = {};\n private context?: LDContext;\n private initialized = false;\n private starting?: Promise<void>;\n private lastValues: LDFlagSet = {};\n\n constructor(private readonly loadSdk: () => Promise<WebSdk> = importSdk) {\n super();\n }\n\n async initialize(options: InitializeOptions): Promise<LaunchDarklyState> {\n const clientSideId = options?.clientSideId;\n if (!clientSideId) throw new Error('initialize needs a clientSideId on the web.');\n if (this.clientSideId === clientSideId) {\n await this.starting;\n return this.state();\n }\n requireKeys(options.context);\n const sdk = await this.sdk();\n if (this.client) await this.close();\n\n const startOptions = options.options ?? {};\n // The given context plays the part of initialContext: a context an earlier identify() stored wins over it.\n const context = readStoredContext() ?? options.context;\n const streaming = (startOptions.streaming ?? true) && !startOptions.offline;\n const client = sdk.createClient(clientSideId, context, {\n streaming,\n withReasons: startOptions.evaluationReasons ?? false,\n ...(startOptions.application ? { applicationInfo: startOptions.application } : {}),\n });\n this.client = client;\n this.clientSideId = clientSideId;\n this.options = startOptions;\n this.context = context;\n this.initialized = false;\n client.on('change', (_context: unknown, keys: string[]) => this.flagsChanged(client, keys));\n\n const bootstrap = startOptions.bootstrap;\n this.starting = client\n .start({\n timeout: seconds(startOptions.startWaitSeconds),\n // 'localStorage' is the SDK's own behaviour: it starts from the flags it cached for the context.\n ...(bootstrap && bootstrap !== 'localStorage' ? { bootstrap } : {}),\n })\n .then((result) => {\n if (this.client !== client) return;\n this.initialized = result.status === 'complete';\n this.lastValues = { ...client.allFlags() };\n });\n await this.starting;\n return this.state();\n }\n\n async waitForInitialization(options?: WaitForInitializationOptions): Promise<WaitForInitializationResult> {\n const client = this.client;\n if (!client) return { initialized: false };\n if (!this.initialized) {\n const result = await client.waitForInitialization({ timeout: seconds(options?.timeoutSeconds) });\n if (this.client === client && result.status === 'complete') this.initialized = true;\n }\n return { initialized: this.initialized };\n }\n\n async getState(): Promise<LaunchDarklyState> {\n await this.starting;\n return this.state();\n }\n\n async identify(options: IdentifyOptions): Promise<IdentifyResult> {\n const client = this.started();\n requireKeys(options?.context);\n const result = await client.identify(options.context, { timeout: seconds(options.timeoutSeconds) });\n if (result.status === 'error' || result.status === 'shed') {\n throw new Error(result.status === 'shed' ? 'identify was replaced by a later identify' : 'identify failed');\n }\n // On a timeout the SDK has switched to the context and keeps loading its flags; only the wait is over.\n this.context = options.context;\n writeStoredContext(options.context);\n return { timedOut: result.status === 'timeout' };\n }\n\n async variation(options: VariationOptions): Promise<VariationResult> {\n const defaultValue = options.defaultValue ?? null;\n const value = this.client ? this.client.jsonVariation(options.key, defaultValue) : defaultValue;\n return { value: value ?? null };\n }\n\n async allFlags(): Promise<AllFlagsResult> {\n return { flags: this.client ? { ...this.client.allFlags() } : {} };\n }\n\n async setStreaming(options: SetStreamingOptions): Promise<void> {\n const client = this.started();\n this.options = { ...this.options, streaming: options.enabled };\n client.setStreaming(options.enabled);\n }\n\n async setOnline(options: SetOnlineOptions): Promise<void> {\n // The browser SDK has no offline mode: offline closes the stream, online opens it again when streaming is on.\n const client = this.started();\n client.setStreaming(options.online ? (this.options.streaming ?? true) : false);\n }\n\n async flush(): Promise<void> {\n await this.client?.flush();\n }\n\n async close(): Promise<void> {\n const client = this.client;\n this.client = undefined;\n this.clientSideId = undefined;\n this.context = undefined;\n this.initialized = false;\n this.starting = undefined;\n this.lastValues = {};\n await client?.close();\n }\n\n async clearStoredContext(): Promise<void> {\n try {\n localStorage.removeItem(STORED_CONTEXT_KEY);\n } catch {\n // No storage (a private window, blocked site data): nothing was stored either.\n }\n }\n\n private async sdk(): Promise<WebSdk> {\n try {\n return await this.loadSdk();\n } catch (error) {\n throw new Error(`${MISSING_SDK_MESSAGE} (${error instanceof Error ? error.message : String(error)})`, {\n cause: error,\n });\n }\n }\n\n private started(): LDClient {\n if (!this.client) throw new Error('The client is not started.');\n return this.client;\n }\n\n private state(): LaunchDarklyState {\n return {\n initialized: this.initialized,\n flags: this.client ? { ...this.client.allFlags() } : {},\n ...(this.context ? { context: this.context } : {}),\n };\n }\n\n private flagsChanged(client: LDClient, keys: string[]) {\n if (this.client !== client) return;\n const flags = client.allFlags();\n for (const key of keys) {\n const value = key in flags ? flags[key] : null;\n const hadPrevious = key in this.lastValues;\n const previous = this.lastValues[key];\n if (key in flags) this.lastValues[key] = flags[key];\n else delete this.lastValues[key];\n this.notifyListeners('flagChange', hadPrevious ? { key, value, previous } : { key, value });\n }\n }\n}\n\nfunction seconds(value: number | undefined): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : DEFAULT_WAIT_SECONDS;\n}\n\n/**\n * Refuses a context whose key (or the key of any kind in a multi-context) is missing or empty. The browser SDK would generate\n * one for an anonymous context, stored per browser, and every browser would then count as a context of its own.\n */\nexport function requireKeys(context: LDContext | undefined): void {\n if (!context || typeof context !== 'object') throw new Error('A context is needed.');\n const parts: [string, unknown][] =\n context.kind === 'multi'\n ? Object.entries(context).filter(([kind]) => kind !== 'kind')\n : [[String(context.kind ?? 'user'), context]];\n if (parts.length === 0) throw new Error('Invalid context: a multi-context needs at least one kind.');\n for (const [kind, part] of parts) {\n const key = (part as { key?: unknown } | null)?.key;\n if (typeof key !== 'string' || key === '') {\n throw new Error(`Invalid context: the ${kind} context has no key. Pass one, also for an anonymous context.`);\n }\n }\n}\n\nfunction readStoredContext(): LDContext | undefined {\n try {\n const json = localStorage.getItem(STORED_CONTEXT_KEY);\n if (!json) return undefined;\n const context = JSON.parse(json) as LDContext;\n requireKeys(context);\n return context;\n } catch {\n return undefined;\n }\n}\n\nfunction writeStoredContext(context: LDContext): void {\n try {\n localStorage.setItem(STORED_CONTEXT_KEY, JSON.stringify(context));\n } catch {\n // No storage: the next start begins with the context initialize() is given.\n }\n}\n"]}
@@ -0,0 +1,221 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const LaunchDarkly = core.registerPlugin('LaunchDarkly', {
6
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.LaunchDarklyWeb()),
7
+ });
8
+
9
+ /** The key the plugin keeps the context of the last `identify()` under in `localStorage`. */
10
+ const STORED_CONTEXT_KEY = 'CapacitorLaunchDarkly.context';
11
+ const DEFAULT_WAIT_SECONDS = 5;
12
+ const MISSING_SDK_MESSAGE = 'The LaunchDarkly web SDK is not installed. To use this plugin on the web, run: npm install @launchdarkly/js-client-sdk';
13
+ // Imported only when a web app starts the client, so a native-only app never loads it.
14
+ const importSdk = () => import('@launchdarkly/js-client-sdk');
15
+ /**
16
+ * The web implementation, on LaunchDarkly's browser SDK. It follows the native rules: one client per page, a context the
17
+ * caller gave with its key (an anonymous context without a key is refused rather than given a generated one), and a context
18
+ * stored by `identify()` that wins over the one `initialize()` is given.
19
+ */
20
+ class LaunchDarklyWeb extends core.WebPlugin {
21
+ constructor(loadSdk = importSdk) {
22
+ super();
23
+ this.loadSdk = loadSdk;
24
+ this.options = {};
25
+ this.initialized = false;
26
+ this.lastValues = {};
27
+ }
28
+ async initialize(options) {
29
+ var _a, _b, _c, _d;
30
+ const clientSideId = options === null || options === void 0 ? void 0 : options.clientSideId;
31
+ if (!clientSideId)
32
+ throw new Error('initialize needs a clientSideId on the web.');
33
+ if (this.clientSideId === clientSideId) {
34
+ await this.starting;
35
+ return this.state();
36
+ }
37
+ requireKeys(options.context);
38
+ const sdk = await this.sdk();
39
+ if (this.client)
40
+ await this.close();
41
+ const startOptions = (_a = options.options) !== null && _a !== void 0 ? _a : {};
42
+ // The given context plays the part of initialContext: a context an earlier identify() stored wins over it.
43
+ const context = (_b = readStoredContext()) !== null && _b !== void 0 ? _b : options.context;
44
+ const streaming = ((_c = startOptions.streaming) !== null && _c !== void 0 ? _c : true) && !startOptions.offline;
45
+ const client = sdk.createClient(clientSideId, context, Object.assign({ streaming, withReasons: (_d = startOptions.evaluationReasons) !== null && _d !== void 0 ? _d : false }, (startOptions.application ? { applicationInfo: startOptions.application } : {})));
46
+ this.client = client;
47
+ this.clientSideId = clientSideId;
48
+ this.options = startOptions;
49
+ this.context = context;
50
+ this.initialized = false;
51
+ client.on('change', (_context, keys) => this.flagsChanged(client, keys));
52
+ const bootstrap = startOptions.bootstrap;
53
+ this.starting = client
54
+ .start(Object.assign({ timeout: seconds(startOptions.startWaitSeconds) }, (bootstrap && bootstrap !== 'localStorage' ? { bootstrap } : {})))
55
+ .then((result) => {
56
+ if (this.client !== client)
57
+ return;
58
+ this.initialized = result.status === 'complete';
59
+ this.lastValues = Object.assign({}, client.allFlags());
60
+ });
61
+ await this.starting;
62
+ return this.state();
63
+ }
64
+ async waitForInitialization(options) {
65
+ const client = this.client;
66
+ if (!client)
67
+ return { initialized: false };
68
+ if (!this.initialized) {
69
+ const result = await client.waitForInitialization({ timeout: seconds(options === null || options === void 0 ? void 0 : options.timeoutSeconds) });
70
+ if (this.client === client && result.status === 'complete')
71
+ this.initialized = true;
72
+ }
73
+ return { initialized: this.initialized };
74
+ }
75
+ async getState() {
76
+ await this.starting;
77
+ return this.state();
78
+ }
79
+ async identify(options) {
80
+ const client = this.started();
81
+ requireKeys(options === null || options === void 0 ? void 0 : options.context);
82
+ const result = await client.identify(options.context, { timeout: seconds(options.timeoutSeconds) });
83
+ if (result.status === 'error' || result.status === 'shed') {
84
+ throw new Error(result.status === 'shed' ? 'identify was replaced by a later identify' : 'identify failed');
85
+ }
86
+ // On a timeout the SDK has switched to the context and keeps loading its flags; only the wait is over.
87
+ this.context = options.context;
88
+ writeStoredContext(options.context);
89
+ return { timedOut: result.status === 'timeout' };
90
+ }
91
+ async variation(options) {
92
+ var _a;
93
+ const defaultValue = (_a = options.defaultValue) !== null && _a !== void 0 ? _a : null;
94
+ const value = this.client ? this.client.jsonVariation(options.key, defaultValue) : defaultValue;
95
+ return { value: value !== null && value !== void 0 ? value : null };
96
+ }
97
+ async allFlags() {
98
+ return { flags: this.client ? Object.assign({}, this.client.allFlags()) : {} };
99
+ }
100
+ async setStreaming(options) {
101
+ const client = this.started();
102
+ this.options = Object.assign(Object.assign({}, this.options), { streaming: options.enabled });
103
+ client.setStreaming(options.enabled);
104
+ }
105
+ async setOnline(options) {
106
+ var _a;
107
+ // The browser SDK has no offline mode: offline closes the stream, online opens it again when streaming is on.
108
+ const client = this.started();
109
+ client.setStreaming(options.online ? ((_a = this.options.streaming) !== null && _a !== void 0 ? _a : true) : false);
110
+ }
111
+ async flush() {
112
+ var _a;
113
+ await ((_a = this.client) === null || _a === void 0 ? void 0 : _a.flush());
114
+ }
115
+ async close() {
116
+ const client = this.client;
117
+ this.client = undefined;
118
+ this.clientSideId = undefined;
119
+ this.context = undefined;
120
+ this.initialized = false;
121
+ this.starting = undefined;
122
+ this.lastValues = {};
123
+ await (client === null || client === void 0 ? void 0 : client.close());
124
+ }
125
+ async clearStoredContext() {
126
+ try {
127
+ localStorage.removeItem(STORED_CONTEXT_KEY);
128
+ }
129
+ catch (_a) {
130
+ // No storage (a private window, blocked site data): nothing was stored either.
131
+ }
132
+ }
133
+ async sdk() {
134
+ try {
135
+ return await this.loadSdk();
136
+ }
137
+ catch (error) {
138
+ throw new Error(`${MISSING_SDK_MESSAGE} (${error instanceof Error ? error.message : String(error)})`, {
139
+ cause: error,
140
+ });
141
+ }
142
+ }
143
+ started() {
144
+ if (!this.client)
145
+ throw new Error('The client is not started.');
146
+ return this.client;
147
+ }
148
+ state() {
149
+ return Object.assign({ initialized: this.initialized, flags: this.client ? Object.assign({}, this.client.allFlags()) : {} }, (this.context ? { context: this.context } : {}));
150
+ }
151
+ flagsChanged(client, keys) {
152
+ if (this.client !== client)
153
+ return;
154
+ const flags = client.allFlags();
155
+ for (const key of keys) {
156
+ const value = key in flags ? flags[key] : null;
157
+ const hadPrevious = key in this.lastValues;
158
+ const previous = this.lastValues[key];
159
+ if (key in flags)
160
+ this.lastValues[key] = flags[key];
161
+ else
162
+ delete this.lastValues[key];
163
+ this.notifyListeners('flagChange', hadPrevious ? { key, value, previous } : { key, value });
164
+ }
165
+ }
166
+ }
167
+ function seconds(value) {
168
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : DEFAULT_WAIT_SECONDS;
169
+ }
170
+ /**
171
+ * Refuses a context whose key (or the key of any kind in a multi-context) is missing or empty. The browser SDK would generate
172
+ * one for an anonymous context, stored per browser, and every browser would then count as a context of its own.
173
+ */
174
+ function requireKeys(context) {
175
+ var _a;
176
+ if (!context || typeof context !== 'object')
177
+ throw new Error('A context is needed.');
178
+ const parts = context.kind === 'multi'
179
+ ? Object.entries(context).filter(([kind]) => kind !== 'kind')
180
+ : [[String((_a = context.kind) !== null && _a !== void 0 ? _a : 'user'), context]];
181
+ if (parts.length === 0)
182
+ throw new Error('Invalid context: a multi-context needs at least one kind.');
183
+ for (const [kind, part] of parts) {
184
+ const key = part === null || part === void 0 ? void 0 : part.key;
185
+ if (typeof key !== 'string' || key === '') {
186
+ throw new Error(`Invalid context: the ${kind} context has no key. Pass one, also for an anonymous context.`);
187
+ }
188
+ }
189
+ }
190
+ function readStoredContext() {
191
+ try {
192
+ const json = localStorage.getItem(STORED_CONTEXT_KEY);
193
+ if (!json)
194
+ return undefined;
195
+ const context = JSON.parse(json);
196
+ requireKeys(context);
197
+ return context;
198
+ }
199
+ catch (_a) {
200
+ return undefined;
201
+ }
202
+ }
203
+ function writeStoredContext(context) {
204
+ try {
205
+ localStorage.setItem(STORED_CONTEXT_KEY, JSON.stringify(context));
206
+ }
207
+ catch (_a) {
208
+ // No storage: the next start begins with the context initialize() is given.
209
+ }
210
+ }
211
+
212
+ var web = /*#__PURE__*/Object.freeze({
213
+ __proto__: null,
214
+ LaunchDarklyWeb: LaunchDarklyWeb,
215
+ MISSING_SDK_MESSAGE: MISSING_SDK_MESSAGE,
216
+ STORED_CONTEXT_KEY: STORED_CONTEXT_KEY,
217
+ requireKeys: requireKeys
218
+ });
219
+
220
+ exports.LaunchDarkly = LaunchDarkly;
221
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst LaunchDarkly = registerPlugin('LaunchDarkly', {\n web: () => import('./web').then((m) => new m.LaunchDarklyWeb()),\n});\nexport * from './definitions';\nexport { LaunchDarkly };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/** The key the plugin keeps the context of the last `identify()` under in `localStorage`. */\nexport const STORED_CONTEXT_KEY = 'CapacitorLaunchDarkly.context';\nconst DEFAULT_WAIT_SECONDS = 5;\nexport const MISSING_SDK_MESSAGE = 'The LaunchDarkly web SDK is not installed. To use this plugin on the web, run: npm install @launchdarkly/js-client-sdk';\n// Imported only when a web app starts the client, so a native-only app never loads it.\nconst importSdk = () => import('@launchdarkly/js-client-sdk');\n/**\n * The web implementation, on LaunchDarkly's browser SDK. It follows the native rules: one client per page, a context the\n * caller gave with its key (an anonymous context without a key is refused rather than given a generated one), and a context\n * stored by `identify()` that wins over the one `initialize()` is given.\n */\nexport class LaunchDarklyWeb extends WebPlugin {\n constructor(loadSdk = importSdk) {\n super();\n this.loadSdk = loadSdk;\n this.options = {};\n this.initialized = false;\n this.lastValues = {};\n }\n async initialize(options) {\n var _a, _b, _c, _d;\n const clientSideId = options === null || options === void 0 ? void 0 : options.clientSideId;\n if (!clientSideId)\n throw new Error('initialize needs a clientSideId on the web.');\n if (this.clientSideId === clientSideId) {\n await this.starting;\n return this.state();\n }\n requireKeys(options.context);\n const sdk = await this.sdk();\n if (this.client)\n await this.close();\n const startOptions = (_a = options.options) !== null && _a !== void 0 ? _a : {};\n // The given context plays the part of initialContext: a context an earlier identify() stored wins over it.\n const context = (_b = readStoredContext()) !== null && _b !== void 0 ? _b : options.context;\n const streaming = ((_c = startOptions.streaming) !== null && _c !== void 0 ? _c : true) && !startOptions.offline;\n const client = sdk.createClient(clientSideId, context, Object.assign({ streaming, withReasons: (_d = startOptions.evaluationReasons) !== null && _d !== void 0 ? _d : false }, (startOptions.application ? { applicationInfo: startOptions.application } : {})));\n this.client = client;\n this.clientSideId = clientSideId;\n this.options = startOptions;\n this.context = context;\n this.initialized = false;\n client.on('change', (_context, keys) => this.flagsChanged(client, keys));\n const bootstrap = startOptions.bootstrap;\n this.starting = client\n .start(Object.assign({ timeout: seconds(startOptions.startWaitSeconds) }, (bootstrap && bootstrap !== 'localStorage' ? { bootstrap } : {})))\n .then((result) => {\n if (this.client !== client)\n return;\n this.initialized = result.status === 'complete';\n this.lastValues = Object.assign({}, client.allFlags());\n });\n await this.starting;\n return this.state();\n }\n async waitForInitialization(options) {\n const client = this.client;\n if (!client)\n return { initialized: false };\n if (!this.initialized) {\n const result = await client.waitForInitialization({ timeout: seconds(options === null || options === void 0 ? void 0 : options.timeoutSeconds) });\n if (this.client === client && result.status === 'complete')\n this.initialized = true;\n }\n return { initialized: this.initialized };\n }\n async getState() {\n await this.starting;\n return this.state();\n }\n async identify(options) {\n const client = this.started();\n requireKeys(options === null || options === void 0 ? void 0 : options.context);\n const result = await client.identify(options.context, { timeout: seconds(options.timeoutSeconds) });\n if (result.status === 'error' || result.status === 'shed') {\n throw new Error(result.status === 'shed' ? 'identify was replaced by a later identify' : 'identify failed');\n }\n // On a timeout the SDK has switched to the context and keeps loading its flags; only the wait is over.\n this.context = options.context;\n writeStoredContext(options.context);\n return { timedOut: result.status === 'timeout' };\n }\n async variation(options) {\n var _a;\n const defaultValue = (_a = options.defaultValue) !== null && _a !== void 0 ? _a : null;\n const value = this.client ? this.client.jsonVariation(options.key, defaultValue) : defaultValue;\n return { value: value !== null && value !== void 0 ? value : null };\n }\n async allFlags() {\n return { flags: this.client ? Object.assign({}, this.client.allFlags()) : {} };\n }\n async setStreaming(options) {\n const client = this.started();\n this.options = Object.assign(Object.assign({}, this.options), { streaming: options.enabled });\n client.setStreaming(options.enabled);\n }\n async setOnline(options) {\n var _a;\n // The browser SDK has no offline mode: offline closes the stream, online opens it again when streaming is on.\n const client = this.started();\n client.setStreaming(options.online ? ((_a = this.options.streaming) !== null && _a !== void 0 ? _a : true) : false);\n }\n async flush() {\n var _a;\n await ((_a = this.client) === null || _a === void 0 ? void 0 : _a.flush());\n }\n async close() {\n const client = this.client;\n this.client = undefined;\n this.clientSideId = undefined;\n this.context = undefined;\n this.initialized = false;\n this.starting = undefined;\n this.lastValues = {};\n await (client === null || client === void 0 ? void 0 : client.close());\n }\n async clearStoredContext() {\n try {\n localStorage.removeItem(STORED_CONTEXT_KEY);\n }\n catch (_a) {\n // No storage (a private window, blocked site data): nothing was stored either.\n }\n }\n async sdk() {\n try {\n return await this.loadSdk();\n }\n catch (error) {\n throw new Error(`${MISSING_SDK_MESSAGE} (${error instanceof Error ? error.message : String(error)})`, {\n cause: error,\n });\n }\n }\n started() {\n if (!this.client)\n throw new Error('The client is not started.');\n return this.client;\n }\n state() {\n return Object.assign({ initialized: this.initialized, flags: this.client ? Object.assign({}, this.client.allFlags()) : {} }, (this.context ? { context: this.context } : {}));\n }\n flagsChanged(client, keys) {\n if (this.client !== client)\n return;\n const flags = client.allFlags();\n for (const key of keys) {\n const value = key in flags ? flags[key] : null;\n const hadPrevious = key in this.lastValues;\n const previous = this.lastValues[key];\n if (key in flags)\n this.lastValues[key] = flags[key];\n else\n delete this.lastValues[key];\n this.notifyListeners('flagChange', hadPrevious ? { key, value, previous } : { key, value });\n }\n }\n}\nfunction seconds(value) {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : DEFAULT_WAIT_SECONDS;\n}\n/**\n * Refuses a context whose key (or the key of any kind in a multi-context) is missing or empty. The browser SDK would generate\n * one for an anonymous context, stored per browser, and every browser would then count as a context of its own.\n */\nexport function requireKeys(context) {\n var _a;\n if (!context || typeof context !== 'object')\n throw new Error('A context is needed.');\n const parts = context.kind === 'multi'\n ? Object.entries(context).filter(([kind]) => kind !== 'kind')\n : [[String((_a = context.kind) !== null && _a !== void 0 ? _a : 'user'), context]];\n if (parts.length === 0)\n throw new Error('Invalid context: a multi-context needs at least one kind.');\n for (const [kind, part] of parts) {\n const key = part === null || part === void 0 ? void 0 : part.key;\n if (typeof key !== 'string' || key === '') {\n throw new Error(`Invalid context: the ${kind} context has no key. Pass one, also for an anonymous context.`);\n }\n }\n}\nfunction readStoredContext() {\n try {\n const json = localStorage.getItem(STORED_CONTEXT_KEY);\n if (!json)\n return undefined;\n const context = JSON.parse(json);\n requireKeys(context);\n return context;\n }\n catch (_a) {\n return undefined;\n }\n}\nfunction writeStoredContext(context) {\n try {\n localStorage.setItem(STORED_CONTEXT_KEY, JSON.stringify(context));\n }\n catch (_a) {\n // No storage: the next start begins with the context initialize() is given.\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}