@harborclient/sdk 0.6.17 → 0.7.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.
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +0 -1
- package/dist/http/resolveRequest.test.js +1 -2
- package/dist/runtime/react.d.ts +0 -6
- package/dist/runtime/react.js +2 -70
- package/dist/runtime/reactHost.js +0 -52
- package/dist/runtime/store.d.ts +0 -101
- package/dist/runtime/store.d.ts.map +1 -1
- package/dist/runtime/store.js +0 -94
- package/dist/runtime/store.ts +0 -203
- package/dist/runtime/viewHost.js +1 -2
- package/dist/runtime-utils.d.ts +0 -59
- package/dist/runtime-utils.d.ts.map +1 -1
- package/dist/runtime-utils.js +0 -66
- package/dist/runtime-utils.test.js +1 -74
- package/dist/storage/index.d.ts +0 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +0 -1
- package/dist/types.d.ts +0 -14
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -35
- package/dist/build/index.d.ts +0 -59
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js +0 -107
- package/dist/components/portalToBody.d.ts +0 -10
- package/dist/components/portalToBody.d.ts.map +0 -1
- package/dist/components/portalToBody.js +0 -14
- package/dist/eslint/index.d.ts +0 -9
- package/dist/eslint/index.d.ts.map +0 -1
- package/dist/eslint/index.js +0 -18
- package/dist/runtime/jsx-runtime-host.d.ts +0 -44
- package/dist/runtime/jsx-runtime-host.js +0 -42
- package/dist/runtime/react-dom.d.ts +0 -1
- package/dist/runtime/react-dom.js +0 -16
- package/dist/storage/validate.d.ts +0 -71
- package/dist/storage/validate.d.ts.map +0 -1
- package/dist/storage/validate.js +0 -111
- package/dist/storage/validate.test.d.ts +0 -2
- package/dist/storage/validate.test.d.ts.map +0 -1
- package/dist/storage/validate.test.js +0 -78
- package/dist/store.test.d.ts +0 -2
- package/dist/store.test.d.ts.map +0 -1
- package/dist/store.test.js +0 -248
- package/tsconfig.base.json +0 -15
package/dist/store.test.js
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
|
|
2
|
-
import { createExternalStore, createStorageStore, setIntervalDisposable, syncOnWindowFocus } from './runtime/store.js';
|
|
3
|
-
/**
|
|
4
|
-
* Builds an in-memory storage mock for store tests.
|
|
5
|
-
*
|
|
6
|
-
* @param initial - Seed values keyed by storage key.
|
|
7
|
-
*/
|
|
8
|
-
function createMockStorage(initial = {}) {
|
|
9
|
-
const data = { ...initial };
|
|
10
|
-
const getMock = jest.fn(async (key) => data[key]);
|
|
11
|
-
const setMock = jest.fn(async (key, value) => {
|
|
12
|
-
data[key] = value;
|
|
13
|
-
});
|
|
14
|
-
return {
|
|
15
|
-
data,
|
|
16
|
-
get: getMock,
|
|
17
|
-
set: setMock,
|
|
18
|
-
getMock,
|
|
19
|
-
setMock
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
describe('createExternalStore', () => {
|
|
23
|
-
it('notifies subscribers when setState is called', () => {
|
|
24
|
-
const store = createExternalStore(0);
|
|
25
|
-
const listener = jest.fn();
|
|
26
|
-
store.subscribe(listener);
|
|
27
|
-
store.setState(1);
|
|
28
|
-
expect(listener).toHaveBeenCalledTimes(1);
|
|
29
|
-
expect(store.getSnapshot()).toBe(1);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
describe('createStorageStore', () => {
|
|
33
|
-
it('starts from parse(undefined)', () => {
|
|
34
|
-
const storage = createMockStorage();
|
|
35
|
-
const store = createStorageStore({
|
|
36
|
-
storage,
|
|
37
|
-
key: 'items',
|
|
38
|
-
parse: (raw) => (Array.isArray(raw) ? raw : [])
|
|
39
|
-
});
|
|
40
|
-
expect(store.getSnapshot()).toEqual([]);
|
|
41
|
-
});
|
|
42
|
-
it('persists and updates the snapshot via set', async () => {
|
|
43
|
-
const storage = createMockStorage();
|
|
44
|
-
const store = createStorageStore({
|
|
45
|
-
storage,
|
|
46
|
-
key: 'items',
|
|
47
|
-
parse: (raw) => (Array.isArray(raw) ? raw : [])
|
|
48
|
-
});
|
|
49
|
-
const listener = jest.fn();
|
|
50
|
-
store.subscribe(listener);
|
|
51
|
-
await store.set(['a']);
|
|
52
|
-
expect(store.getSnapshot()).toEqual(['a']);
|
|
53
|
-
expect(storage.setMock).toHaveBeenCalledWith('items', ['a']);
|
|
54
|
-
expect(listener).toHaveBeenCalledTimes(1);
|
|
55
|
-
});
|
|
56
|
-
it('skips set when equals reports no change', async () => {
|
|
57
|
-
const storage = createMockStorage({ items: ['a'] });
|
|
58
|
-
const store = createStorageStore({
|
|
59
|
-
storage,
|
|
60
|
-
key: 'items',
|
|
61
|
-
parse: (raw) => (Array.isArray(raw) ? raw : [])
|
|
62
|
-
});
|
|
63
|
-
await store.reloadFromStorage();
|
|
64
|
-
const listener = jest.fn();
|
|
65
|
-
store.subscribe(listener);
|
|
66
|
-
await store.set(['a']);
|
|
67
|
-
expect(listener).not.toHaveBeenCalled();
|
|
68
|
-
expect(storage.setMock).not.toHaveBeenCalled();
|
|
69
|
-
});
|
|
70
|
-
it('reloadFromStorage applies parsed storage values', async () => {
|
|
71
|
-
const storage = createMockStorage({ count: 3 });
|
|
72
|
-
const store = createStorageStore({
|
|
73
|
-
storage,
|
|
74
|
-
key: 'count',
|
|
75
|
-
parse: (raw) => (typeof raw === 'number' ? raw : 0)
|
|
76
|
-
});
|
|
77
|
-
const listener = jest.fn();
|
|
78
|
-
store.subscribe(listener);
|
|
79
|
-
await store.reloadFromStorage();
|
|
80
|
-
expect(store.getSnapshot()).toBe(3);
|
|
81
|
-
expect(listener).toHaveBeenCalledTimes(1);
|
|
82
|
-
});
|
|
83
|
-
it('reloadFromStorage skips notify when parsed value is unchanged', async () => {
|
|
84
|
-
const storage = createMockStorage({ count: 2 });
|
|
85
|
-
const store = createStorageStore({
|
|
86
|
-
storage,
|
|
87
|
-
key: 'count',
|
|
88
|
-
parse: (raw) => (typeof raw === 'number' ? raw : 0)
|
|
89
|
-
});
|
|
90
|
-
await store.reloadFromStorage();
|
|
91
|
-
const listener = jest.fn();
|
|
92
|
-
store.subscribe(listener);
|
|
93
|
-
await store.reloadFromStorage();
|
|
94
|
-
expect(listener).not.toHaveBeenCalled();
|
|
95
|
-
});
|
|
96
|
-
it('uses a custom equals function', async () => {
|
|
97
|
-
const storage = createMockStorage();
|
|
98
|
-
const store = createStorageStore({
|
|
99
|
-
storage,
|
|
100
|
-
key: 'status',
|
|
101
|
-
parse: (raw) => raw && typeof raw === 'object' && 'running' in raw
|
|
102
|
-
? raw
|
|
103
|
-
: { running: false },
|
|
104
|
-
equals: (a, b) => a.running === b.running
|
|
105
|
-
});
|
|
106
|
-
await store.set({ running: true });
|
|
107
|
-
const listener = jest.fn();
|
|
108
|
-
store.subscribe(listener);
|
|
109
|
-
storage.data.status = { running: true, port: 8080 };
|
|
110
|
-
await store.reloadFromStorage();
|
|
111
|
-
expect(listener).not.toHaveBeenCalled();
|
|
112
|
-
expect(store.getSnapshot()).toEqual({ running: true });
|
|
113
|
-
});
|
|
114
|
-
it('keeps the current snapshot when storage is missing and keepCurrentWhenMissing is true', async () => {
|
|
115
|
-
const storage = createMockStorage();
|
|
116
|
-
const store = createStorageStore({
|
|
117
|
-
storage,
|
|
118
|
-
key: 'status',
|
|
119
|
-
parse: () => ({ running: false }),
|
|
120
|
-
keepCurrentWhenMissing: true
|
|
121
|
-
});
|
|
122
|
-
await store.set({ running: true });
|
|
123
|
-
delete storage.data.status;
|
|
124
|
-
const listener = jest.fn();
|
|
125
|
-
store.subscribe(listener);
|
|
126
|
-
await store.reloadFromStorage();
|
|
127
|
-
expect(listener).not.toHaveBeenCalled();
|
|
128
|
-
expect(store.getSnapshot()).toEqual({ running: true });
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
describe('setIntervalDisposable', () => {
|
|
132
|
-
beforeEach(() => {
|
|
133
|
-
jest.useFakeTimers();
|
|
134
|
-
});
|
|
135
|
-
afterEach(() => {
|
|
136
|
-
jest.useRealTimers();
|
|
137
|
-
});
|
|
138
|
-
it('invokes the callback on an interval until disposed', () => {
|
|
139
|
-
const callback = jest.fn();
|
|
140
|
-
const disposable = setIntervalDisposable(callback, 100);
|
|
141
|
-
jest.advanceTimersByTime(250);
|
|
142
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
143
|
-
disposable.dispose();
|
|
144
|
-
jest.advanceTimersByTime(200);
|
|
145
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
describe('syncOnWindowFocus', () => {
|
|
149
|
-
const focusListeners = new Set();
|
|
150
|
-
const visibilityListeners = new Set();
|
|
151
|
-
const originalWindow = globalThis.window;
|
|
152
|
-
const originalDocument = globalThis.document;
|
|
153
|
-
beforeEach(() => {
|
|
154
|
-
jest.useFakeTimers();
|
|
155
|
-
focusListeners.clear();
|
|
156
|
-
visibilityListeners.clear();
|
|
157
|
-
globalThis.window = {
|
|
158
|
-
addEventListener: (type, listener) => {
|
|
159
|
-
if (type === 'focus' && typeof listener === 'function') {
|
|
160
|
-
focusListeners.add(listener);
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
removeEventListener: (type, listener) => {
|
|
164
|
-
if (type === 'focus' && typeof listener === 'function') {
|
|
165
|
-
focusListeners.delete(listener);
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
dispatchEvent: (event) => {
|
|
169
|
-
if (event.type === 'focus') {
|
|
170
|
-
for (const listener of focusListeners) {
|
|
171
|
-
listener(event);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
globalThis.document = {
|
|
178
|
-
addEventListener: (type, listener) => {
|
|
179
|
-
if (type === 'visibilitychange' && typeof listener === 'function') {
|
|
180
|
-
visibilityListeners.add(listener);
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
removeEventListener: (type, listener) => {
|
|
184
|
-
if (type === 'visibilitychange' && typeof listener === 'function') {
|
|
185
|
-
visibilityListeners.delete(listener);
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
dispatchEvent: (event) => {
|
|
189
|
-
if (event.type === 'visibilitychange') {
|
|
190
|
-
for (const listener of visibilityListeners) {
|
|
191
|
-
listener(event);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
});
|
|
198
|
-
afterEach(() => {
|
|
199
|
-
jest.useRealTimers();
|
|
200
|
-
globalThis.window = originalWindow;
|
|
201
|
-
globalThis.document = originalDocument;
|
|
202
|
-
});
|
|
203
|
-
it('reloads stores on focus, visibility change, mount, and interval', async () => {
|
|
204
|
-
const storage = createMockStorage({ count: 1 });
|
|
205
|
-
const store = createStorageStore({
|
|
206
|
-
storage,
|
|
207
|
-
key: 'count',
|
|
208
|
-
parse: (raw) => (typeof raw === 'number' ? raw : 0)
|
|
209
|
-
});
|
|
210
|
-
const reloadSpy = jest.spyOn(store, 'reloadFromStorage');
|
|
211
|
-
const disposable = syncOnWindowFocus(store, { intervalMs: 500 });
|
|
212
|
-
expect(reloadSpy).toHaveBeenCalledTimes(1);
|
|
213
|
-
storage.data.count = 2;
|
|
214
|
-
window.dispatchEvent(new Event('focus'));
|
|
215
|
-
expect(reloadSpy).toHaveBeenCalledTimes(2);
|
|
216
|
-
storage.data.count = 3;
|
|
217
|
-
document.dispatchEvent(new Event('visibilitychange'));
|
|
218
|
-
expect(reloadSpy).toHaveBeenCalledTimes(3);
|
|
219
|
-
storage.data.count = 4;
|
|
220
|
-
jest.advanceTimersByTime(500);
|
|
221
|
-
expect(reloadSpy).toHaveBeenCalledTimes(4);
|
|
222
|
-
disposable.dispose();
|
|
223
|
-
storage.data.count = 5;
|
|
224
|
-
window.dispatchEvent(new Event('focus'));
|
|
225
|
-
jest.advanceTimersByTime(500);
|
|
226
|
-
expect(reloadSpy).toHaveBeenCalledTimes(4);
|
|
227
|
-
await store.reloadFromStorage();
|
|
228
|
-
expect(store.getSnapshot()).toBe(5);
|
|
229
|
-
});
|
|
230
|
-
it('reloads multiple stores together', async () => {
|
|
231
|
-
const storage = createMockStorage();
|
|
232
|
-
const first = createStorageStore({
|
|
233
|
-
storage,
|
|
234
|
-
key: 'first',
|
|
235
|
-
parse: (raw) => (typeof raw === 'number' ? raw : 0)
|
|
236
|
-
});
|
|
237
|
-
const second = createStorageStore({
|
|
238
|
-
storage,
|
|
239
|
-
key: 'second',
|
|
240
|
-
parse: (raw) => (typeof raw === 'number' ? raw : 0)
|
|
241
|
-
});
|
|
242
|
-
const reloadFirst = jest.spyOn(first, 'reloadFromStorage');
|
|
243
|
-
const reloadSecond = jest.spyOn(second, 'reloadFromStorage');
|
|
244
|
-
syncOnWindowFocus([first, second]).dispose();
|
|
245
|
-
expect(reloadFirst).toHaveBeenCalledTimes(1);
|
|
246
|
-
expect(reloadSecond).toHaveBeenCalledTimes(1);
|
|
247
|
-
});
|
|
248
|
-
});
|
package/tsconfig.base.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"jsx": "react-jsx",
|
|
7
|
-
"jsxImportSource": "@harborclient/sdk",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"noEmit": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"lib": ["ES2022", "DOM"],
|
|
13
|
-
"types": ["react"]
|
|
14
|
-
}
|
|
15
|
-
}
|