@launchdarkly/toolbar 0.14.0-beta.1 → 0.16.0-beta.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/README.md +31 -5
- package/dist/hooks/EventStore.d.ts +6 -0
- package/dist/js/index.js +118 -111
- package/dist/js/plugins/index.js +10 -3
- package/dist/plugins/EventInterceptionPlugin.d.ts +2 -0
- package/package.json +19 -42
- package/dist/js/plugins/FlagOverridePlugin.js +0 -133
package/dist/js/plugins/index.js
CHANGED
|
@@ -130,14 +130,18 @@ class FlagOverridePlugin {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
const
|
|
133
|
+
const DEFAULT_MAX_EVENTS = 100;
|
|
134
134
|
class EventStore {
|
|
135
135
|
events = [];
|
|
136
136
|
listeners = new Set();
|
|
137
|
+
maxEvents;
|
|
138
|
+
constructor(config = {}){
|
|
139
|
+
this.maxEvents = config.maxEvents ?? DEFAULT_MAX_EVENTS;
|
|
140
|
+
}
|
|
137
141
|
addEvent(event) {
|
|
138
142
|
try {
|
|
139
143
|
this.events.push(event);
|
|
140
|
-
if (this.events.length >
|
|
144
|
+
if (this.events.length > this.maxEvents) this.events.splice(0, this.events.length - this.maxEvents);
|
|
141
145
|
this.notifyListeners();
|
|
142
146
|
} catch (error) {
|
|
143
147
|
console.warn('Event store error:', error);
|
|
@@ -371,9 +375,12 @@ class EventInterceptionPlugin {
|
|
|
371
375
|
constructor(config = {}){
|
|
372
376
|
this.config = {
|
|
373
377
|
enableLogging: false,
|
|
378
|
+
eventCapacity: 100,
|
|
374
379
|
...config
|
|
375
380
|
};
|
|
376
|
-
this.eventStore = new EventStore(
|
|
381
|
+
this.eventStore = new EventStore({
|
|
382
|
+
maxEvents: this.config.eventCapacity
|
|
383
|
+
});
|
|
377
384
|
const onNewEvent = (event)=>{
|
|
378
385
|
if (this.config.enableLogging) console.log('🎯 Event intercepted:', {
|
|
379
386
|
kind: event.kind,
|
|
@@ -9,6 +9,8 @@ export interface EventInterceptionPluginConfig {
|
|
|
9
9
|
filter?: EventFilter;
|
|
10
10
|
/** Enable console logging for debugging */
|
|
11
11
|
enableLogging?: boolean;
|
|
12
|
+
/** Maximum number of events to store. The default value is 100. */
|
|
13
|
+
eventCapacity?: number;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Plugin dedicated to intercepting and processing LaunchDarkly events
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@launchdarkly/toolbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0-beta.1",
|
|
4
4
|
"description": "A React component that provides a developer-friendly toolbar for interacting with LaunchDarkly during development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"launchdarkly",
|
|
@@ -36,10 +36,6 @@
|
|
|
36
36
|
"./plugins": {
|
|
37
37
|
"types": "./dist/plugins/index.d.ts",
|
|
38
38
|
"import": "./dist/js/plugins/index.js"
|
|
39
|
-
},
|
|
40
|
-
"./plugins/FlagOverridePlugin": {
|
|
41
|
-
"types": "./dist/plugins/FlagOverridePlugin.d.ts",
|
|
42
|
-
"import": "./dist/js/plugins/FlagOverridePlugin.js"
|
|
43
39
|
}
|
|
44
40
|
},
|
|
45
41
|
"files": [
|
|
@@ -50,56 +46,31 @@
|
|
|
50
46
|
"not dead",
|
|
51
47
|
"not IE 11"
|
|
52
48
|
],
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build:storybook": "storybook build",
|
|
55
|
-
"build": "rslib build && node scripts/fix-base-url.cjs",
|
|
56
|
-
"demo:build": "pnpm build && pnpm --filter launchdarkly-toolbar-demo build",
|
|
57
|
-
"demo:dev": "pnpm --filter launchdarkly-toolbar-demo dev",
|
|
58
|
-
"demo:restart": "./scripts/dev-restart.sh",
|
|
59
|
-
"demo": "pnpm build && pnpm --filter launchdarkly-toolbar-demo dev",
|
|
60
|
-
"dev:link": "./scripts/setup-local-links.sh",
|
|
61
|
-
"dev:status": "./scripts/dev-status.sh",
|
|
62
|
-
"dev:unlink": "./scripts/remove-local-links.sh",
|
|
63
|
-
"dev:watch": "./scripts/smart-watch-simple.sh",
|
|
64
|
-
"dev": "rslib build --watch",
|
|
65
|
-
"format": "prettier --write .",
|
|
66
|
-
"format:ci": "prettier --check .",
|
|
67
|
-
"lint": "oxlint",
|
|
68
|
-
"release": "pnpm build && npm publish",
|
|
69
|
-
"storybook": "storybook dev -p 6006",
|
|
70
|
-
"test:e2e:ci:ui": "TEST_ENV=ci playwright test --ui --config=./e2e/playwright.config.ts",
|
|
71
|
-
"test:e2e:ci": "TEST_ENV=ci playwright test --config=./e2e/playwright.config.ts",
|
|
72
|
-
"test:e2e:local:ui": "TEST_ENV=local playwright test --ui --config=./e2e/playwright.config.ts",
|
|
73
|
-
"test:e2e:local": "TEST_ENV=local playwright test --config=./e2e/playwright.config.ts",
|
|
74
|
-
"test": "vitest run",
|
|
75
|
-
"upgrade-launchpad": "pnpm up \"@launchpad-ui/*\" \"@internationalized/*\" react-aria \"@react-aria/*\" \"@react-types/*\" \"@react-stately/*\" react-stately react-aria-components react react-dom @types/react @types/react-dom --latest -r"
|
|
76
|
-
},
|
|
77
49
|
"devDependencies": {
|
|
78
|
-
"@playwright/test": "^1.53.1",
|
|
79
50
|
"@rsbuild/core": "1.5.4",
|
|
80
51
|
"@rsbuild/plugin-react": "^1.4.0",
|
|
81
52
|
"@rslib/core": "^0.13.0",
|
|
82
|
-
"@storybook/addon-docs": "^9.0.5",
|
|
83
|
-
"@storybook/addon-essentials": "^9.0.0-alpha.12",
|
|
84
|
-
"@storybook/addon-interactions": "^9.0.0-alpha.10",
|
|
85
|
-
"@storybook/addon-links": "^9.0.5",
|
|
86
|
-
"@storybook/addon-onboarding": "^9.0.5",
|
|
87
|
-
"@storybook/blocks": "^9.0.0-alpha.17",
|
|
88
|
-
"@storybook/react": "^9.0.5",
|
|
89
|
-
"@storybook/test": "^9.0.0-alpha.2",
|
|
90
53
|
"@testing-library/jest-dom": "^6.6.3",
|
|
91
54
|
"@testing-library/react": "^16.3.0",
|
|
92
55
|
"@types/node": "^24.0.4",
|
|
93
56
|
"@types/react": "^19.1.13",
|
|
94
57
|
"@vanilla-extract/vite-plugin": "^5.1.1",
|
|
58
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
95
59
|
"jsdom": "^26.1.0",
|
|
96
60
|
"launchdarkly-js-client-sdk": "^3.9.0",
|
|
97
61
|
"oxlint": "^1.0.0",
|
|
98
|
-
"prettier": "^3.5.3",
|
|
99
62
|
"react": "^19.1.1",
|
|
100
63
|
"storybook": "^9.0.5",
|
|
101
64
|
"storybook-addon-rslib": "^2.0.0",
|
|
102
65
|
"storybook-react-rsbuild": "^2.0.0",
|
|
66
|
+
"@storybook/addon-docs": "^9.0.5",
|
|
67
|
+
"@storybook/addon-essentials": "^9.0.0-alpha.12",
|
|
68
|
+
"@storybook/addon-interactions": "^9.0.0-alpha.10",
|
|
69
|
+
"@storybook/addon-links": "^9.0.5",
|
|
70
|
+
"@storybook/addon-onboarding": "^9.0.5",
|
|
71
|
+
"@storybook/blocks": "^9.0.0-alpha.17",
|
|
72
|
+
"@storybook/react": "^9.0.5",
|
|
73
|
+
"@storybook/test": "^9.0.0-alpha.2",
|
|
103
74
|
"typescript": "^5.8.3",
|
|
104
75
|
"vitest": "^3.2.2",
|
|
105
76
|
"webpack": "5.101.3"
|
|
@@ -108,7 +79,6 @@
|
|
|
108
79
|
"launchdarkly-js-client-sdk": "^3.9.0",
|
|
109
80
|
"react": "^18.0.0 || ^19.0.0"
|
|
110
81
|
},
|
|
111
|
-
"private": false,
|
|
112
82
|
"publishConfig": {
|
|
113
83
|
"access": "public"
|
|
114
84
|
},
|
|
@@ -129,5 +99,12 @@
|
|
|
129
99
|
"react-hook-form": "7.59.0",
|
|
130
100
|
"react-router": "7.5.2"
|
|
131
101
|
},
|
|
132
|
-
"
|
|
133
|
-
|
|
102
|
+
"scripts": {
|
|
103
|
+
"build": "rslib build && node ../../scripts/fix-base-url.cjs dist/js/index.js",
|
|
104
|
+
"dev": "rslib build --watch",
|
|
105
|
+
"test": "vitest run",
|
|
106
|
+
"lint": "oxlint",
|
|
107
|
+
"storybook": "storybook dev -p 6006",
|
|
108
|
+
"build:storybook": "storybook build"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
const DEFAULT_STORAGE_NAMESPACE = 'ld-flag-override';
|
|
2
|
-
class FlagOverridePlugin {
|
|
3
|
-
debugOverride;
|
|
4
|
-
config;
|
|
5
|
-
ldClient = null;
|
|
6
|
-
constructor(config = {}){
|
|
7
|
-
this.config = {
|
|
8
|
-
storageNamespace: config.storageNamespace ?? DEFAULT_STORAGE_NAMESPACE
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
getMetadata() {
|
|
12
|
-
return {
|
|
13
|
-
name: 'FlagOverridePlugin'
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
getHooks(_metadata) {
|
|
17
|
-
return [];
|
|
18
|
-
}
|
|
19
|
-
register(ldClient) {
|
|
20
|
-
this.ldClient = ldClient;
|
|
21
|
-
}
|
|
22
|
-
registerDebug(debugOverride) {
|
|
23
|
-
this.debugOverride = debugOverride;
|
|
24
|
-
this.loadExistingOverrides();
|
|
25
|
-
}
|
|
26
|
-
loadExistingOverrides() {
|
|
27
|
-
if (!this.debugOverride) return;
|
|
28
|
-
const storage = this.getStorage();
|
|
29
|
-
if (!storage) return;
|
|
30
|
-
try {
|
|
31
|
-
for(let i = 0; i < storage.length; i++){
|
|
32
|
-
const key = storage.key(i);
|
|
33
|
-
if (!key?.startsWith(this.config.storageNamespace + ':')) continue;
|
|
34
|
-
const storedValue = storage.getItem(key);
|
|
35
|
-
if (storedValue) try {
|
|
36
|
-
const value = JSON.parse(storedValue);
|
|
37
|
-
const flagKey = key.replace(this.config.storageNamespace + ':', '');
|
|
38
|
-
this.debugOverride.setOverride(flagKey, value);
|
|
39
|
-
} catch {
|
|
40
|
-
console.warn('flagOverridePlugin: Invalid stored value for', key);
|
|
41
|
-
storage.removeItem(key);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('flagOverridePlugin: Error loading existing overrides:', error);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
setOverride(flagKey, value) {
|
|
49
|
-
if (!this.debugOverride) return void console.warn('flagOverridePlugin: Debug interface not available');
|
|
50
|
-
if (!flagKey || 'string' != typeof flagKey) return void console.error('flagOverridePlugin: Invalid flag key:', flagKey);
|
|
51
|
-
if (void 0 === value) return void console.error('flagOverridePlugin: Cannot set undefined value for flag override');
|
|
52
|
-
try {
|
|
53
|
-
this.persistOverride(flagKey, value);
|
|
54
|
-
this.debugOverride.setOverride(flagKey, value);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error('flagOverridePlugin: Failed to set override:', error);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
removeOverride(flagKey) {
|
|
60
|
-
if (!this.debugOverride) return void console.warn('flagOverridePlugin: Debug interface not available');
|
|
61
|
-
if (!flagKey || 'string' != typeof flagKey) return void console.error('flagOverridePlugin: Invalid flag key:', flagKey);
|
|
62
|
-
try {
|
|
63
|
-
this.removePersistedOverride(flagKey);
|
|
64
|
-
this.debugOverride.removeOverride(flagKey);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('flagOverridePlugin: Failed to remove override:', error);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
clearAllOverrides() {
|
|
70
|
-
if (!this.debugOverride) return void console.warn('flagOverridePlugin: Debug interface not available');
|
|
71
|
-
try {
|
|
72
|
-
this.clearPersistedOverrides();
|
|
73
|
-
this.debugOverride.clearAllOverrides();
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error('flagOverridePlugin: Failed to clear overrides:', error);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
getAllOverrides() {
|
|
79
|
-
if (!this.debugOverride) {
|
|
80
|
-
console.warn('flagOverridePlugin: Debug interface not available');
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
return this.debugOverride.getAllOverrides();
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error('flagOverridePlugin: Failed to get overrides:', error);
|
|
87
|
-
return {};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
getClient() {
|
|
91
|
-
return this.ldClient;
|
|
92
|
-
}
|
|
93
|
-
getStorage() {
|
|
94
|
-
if ('undefined' == typeof window) return null;
|
|
95
|
-
return window.localStorage;
|
|
96
|
-
}
|
|
97
|
-
persistOverride(flagKey, value) {
|
|
98
|
-
const storage = this.getStorage();
|
|
99
|
-
if (!storage) return;
|
|
100
|
-
try {
|
|
101
|
-
const storageKey = `${this.config.storageNamespace}:${flagKey}`;
|
|
102
|
-
storage.setItem(storageKey, JSON.stringify(value));
|
|
103
|
-
} catch (error) {
|
|
104
|
-
console.error('flagOverridePlugin: Failed to persist override:', error);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
removePersistedOverride(flagKey) {
|
|
108
|
-
const storage = this.getStorage();
|
|
109
|
-
if (!storage) return;
|
|
110
|
-
try {
|
|
111
|
-
const storageKey = `${this.config.storageNamespace}:${flagKey}`;
|
|
112
|
-
storage.removeItem(storageKey);
|
|
113
|
-
} catch (error) {
|
|
114
|
-
console.error('flagOverridePlugin: Failed to remove persisted override:', error);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
clearPersistedOverrides() {
|
|
118
|
-
const storage = this.getStorage();
|
|
119
|
-
if (!storage) return;
|
|
120
|
-
try {
|
|
121
|
-
const keysToRemove = [];
|
|
122
|
-
const prefix = this.config.storageNamespace + ':';
|
|
123
|
-
for(let i = 0; i < storage.length; i++){
|
|
124
|
-
const key = storage.key(i);
|
|
125
|
-
if (key?.startsWith(prefix)) keysToRemove.push(key);
|
|
126
|
-
}
|
|
127
|
-
keysToRemove.forEach((key)=>storage.removeItem(key));
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error('flagOverridePlugin: Failed to clear persisted overrides:', error);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
export { FlagOverridePlugin };
|