@sanity/cli-core 0.1.0-alpha.5 → 0.1.0-alpha.6
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/config/cli/schemas.d.ts +15 -0
- package/dist/config/cli/schemas.js +5 -2
- package/dist/config/cli/schemas.js.map +1 -1
- package/dist/config/cli/types/cliConfig.d.ts +9 -0
- package/dist/config/cli/types/cliConfig.js.map +1 -1
- package/dist/loaders/studio/studioWorkerLoader.worker.js +9 -24
- package/dist/loaders/studio/studioWorkerLoader.worker.js.map +1 -1
- package/package.json +10 -7
- package/dist/config/__tests__/cliToken.test.js +0 -74
- package/dist/config/__tests__/cliToken.test.js.map +0 -1
- package/dist/config/__tests__/cliUserConfig.test.js +0 -131
- package/dist/config/__tests__/cliUserConfig.test.js.map +0 -1
- package/dist/config/__tests__/findProjectRoot.test.js +0 -159
- package/dist/config/__tests__/findProjectRoot.test.js.map +0 -1
- package/dist/config/__tests__/findProjectRootSync.test.js +0 -112
- package/dist/config/__tests__/findProjectRootSync.test.js.map +0 -1
- package/dist/config/__tests__/getCliConfigSync.test.js +0 -31
- package/dist/config/__tests__/getCliConfigSync.test.js.map +0 -1
- package/dist/util/__tests__/createExpiringConfig.test.js +0 -400
- package/dist/util/__tests__/createExpiringConfig.test.js.map +0 -1
- package/dist/util/__tests__/parseStringFlag.test.js +0 -43
- package/dist/util/__tests__/parseStringFlag.test.js.map +0 -1
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { createExpiringConfig } from '../createExpiringConfig.js';
|
|
3
|
-
describe('createExpiringConfig', ()=>{
|
|
4
|
-
let mockStore;
|
|
5
|
-
let fetchValue;
|
|
6
|
-
let onCacheHit;
|
|
7
|
-
let onFetch;
|
|
8
|
-
let onRevalidate;
|
|
9
|
-
beforeEach(()=>{
|
|
10
|
-
// Mock ConfigStore
|
|
11
|
-
mockStore = {
|
|
12
|
-
delete: vi.fn(),
|
|
13
|
-
get: vi.fn(),
|
|
14
|
-
set: vi.fn()
|
|
15
|
-
};
|
|
16
|
-
// Reset all mocks
|
|
17
|
-
fetchValue = vi.fn();
|
|
18
|
-
onCacheHit = vi.fn();
|
|
19
|
-
onFetch = vi.fn();
|
|
20
|
-
onRevalidate = vi.fn();
|
|
21
|
-
});
|
|
22
|
-
test('returns fetched value when cache is empty', async ()=>{
|
|
23
|
-
const testValue = 'test-value';
|
|
24
|
-
const config = createExpiringConfig({
|
|
25
|
-
fetchValue: fetchValue.mockResolvedValue(testValue),
|
|
26
|
-
key: 'test-key',
|
|
27
|
-
onCacheHit,
|
|
28
|
-
onFetch,
|
|
29
|
-
onRevalidate,
|
|
30
|
-
store: mockStore,
|
|
31
|
-
ttl: 5000
|
|
32
|
-
});
|
|
33
|
-
// Mock empty cache
|
|
34
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
35
|
-
const result = await config.get();
|
|
36
|
-
expect(result).toBe(testValue);
|
|
37
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
38
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
39
|
-
expect(onCacheHit).not.toHaveBeenCalled();
|
|
40
|
-
expect(onRevalidate).not.toHaveBeenCalled();
|
|
41
|
-
expect(mockStore.set).toHaveBeenCalledWith('test-key', {
|
|
42
|
-
updatedAt: expect.any(Number),
|
|
43
|
-
value: testValue
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
test('returns cached value when it has not expired', async ()=>{
|
|
47
|
-
const cachedValue = 'cached-value';
|
|
48
|
-
const ttl = 5000;
|
|
49
|
-
const updatedAt = Date.now() - 1000 // 1 second ago (not expired)
|
|
50
|
-
;
|
|
51
|
-
const config = createExpiringConfig({
|
|
52
|
-
fetchValue,
|
|
53
|
-
key: 'test-key',
|
|
54
|
-
onCacheHit,
|
|
55
|
-
onFetch,
|
|
56
|
-
onRevalidate,
|
|
57
|
-
store: mockStore,
|
|
58
|
-
ttl
|
|
59
|
-
});
|
|
60
|
-
// Mock cached value that hasn't expired
|
|
61
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
62
|
-
updatedAt,
|
|
63
|
-
value: cachedValue
|
|
64
|
-
});
|
|
65
|
-
const result = await config.get();
|
|
66
|
-
expect(result).toBe(cachedValue);
|
|
67
|
-
expect(fetchValue).not.toHaveBeenCalled();
|
|
68
|
-
expect(onCacheHit).toHaveBeenCalledOnce();
|
|
69
|
-
expect(onFetch).not.toHaveBeenCalled();
|
|
70
|
-
expect(onRevalidate).not.toHaveBeenCalled();
|
|
71
|
-
expect(mockStore.set).not.toHaveBeenCalled();
|
|
72
|
-
});
|
|
73
|
-
test('fetches new value when cached value has expired', async ()=>{
|
|
74
|
-
const newValue = 'new-value';
|
|
75
|
-
const ttl = 1000;
|
|
76
|
-
const updatedAt = Date.now() - 2000 // 2 seconds ago (expired)
|
|
77
|
-
;
|
|
78
|
-
const config = createExpiringConfig({
|
|
79
|
-
fetchValue: fetchValue.mockResolvedValue(newValue),
|
|
80
|
-
key: 'test-key',
|
|
81
|
-
onCacheHit,
|
|
82
|
-
onFetch,
|
|
83
|
-
onRevalidate,
|
|
84
|
-
store: mockStore,
|
|
85
|
-
ttl
|
|
86
|
-
});
|
|
87
|
-
// Mock expired cached value
|
|
88
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
89
|
-
updatedAt,
|
|
90
|
-
value: 'old-value'
|
|
91
|
-
});
|
|
92
|
-
const result = await config.get();
|
|
93
|
-
expect(result).toBe(newValue);
|
|
94
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
95
|
-
expect(onRevalidate).toHaveBeenCalledOnce();
|
|
96
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
97
|
-
expect(onCacheHit).not.toHaveBeenCalled();
|
|
98
|
-
expect(mockStore.set).toHaveBeenCalledWith('test-key', {
|
|
99
|
-
updatedAt: expect.any(Number),
|
|
100
|
-
value: newValue
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
test('deletes cached value from store', ()=>{
|
|
104
|
-
const config = createExpiringConfig({
|
|
105
|
-
fetchValue,
|
|
106
|
-
key: 'test-key',
|
|
107
|
-
store: mockStore,
|
|
108
|
-
ttl: 5000
|
|
109
|
-
});
|
|
110
|
-
config.delete();
|
|
111
|
-
expect(mockStore.delete).toHaveBeenCalledWith('test-key');
|
|
112
|
-
});
|
|
113
|
-
test('handles concurrent get() calls correctly', async ()=>{
|
|
114
|
-
const testValue = 'test-value';
|
|
115
|
-
let resolvePromise;
|
|
116
|
-
const delayedFetch = new Promise((resolve)=>{
|
|
117
|
-
resolvePromise = resolve;
|
|
118
|
-
});
|
|
119
|
-
const config = createExpiringConfig({
|
|
120
|
-
fetchValue: fetchValue.mockReturnValue(delayedFetch),
|
|
121
|
-
key: 'test-key',
|
|
122
|
-
onFetch,
|
|
123
|
-
store: mockStore,
|
|
124
|
-
ttl: 5000
|
|
125
|
-
});
|
|
126
|
-
// Mock empty cache
|
|
127
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
128
|
-
// Start multiple concurrent get() calls
|
|
129
|
-
const promise1 = config.get();
|
|
130
|
-
const promise2 = config.get();
|
|
131
|
-
const promise3 = config.get();
|
|
132
|
-
// Resolve the fetch
|
|
133
|
-
resolvePromise(testValue);
|
|
134
|
-
const [result1, result2, result3] = await Promise.all([
|
|
135
|
-
promise1,
|
|
136
|
-
promise2,
|
|
137
|
-
promise3
|
|
138
|
-
]);
|
|
139
|
-
expect(result1).toBe(testValue);
|
|
140
|
-
expect(result2).toBe(testValue);
|
|
141
|
-
expect(result3).toBe(testValue);
|
|
142
|
-
expect(fetchValue).toHaveBeenCalledOnce(); // Only one fetch should happen
|
|
143
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
144
|
-
});
|
|
145
|
-
test('handles synchronous fetchValue function', async ()=>{
|
|
146
|
-
const testValue = 'sync-value';
|
|
147
|
-
const syncFetchValue = vi.fn().mockReturnValue(testValue);
|
|
148
|
-
const config = createExpiringConfig({
|
|
149
|
-
fetchValue: syncFetchValue,
|
|
150
|
-
key: 'test-key',
|
|
151
|
-
store: mockStore,
|
|
152
|
-
ttl: 5000
|
|
153
|
-
});
|
|
154
|
-
// Mock empty cache
|
|
155
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
156
|
-
const result = await config.get();
|
|
157
|
-
expect(result).toBe(testValue);
|
|
158
|
-
expect(syncFetchValue).toHaveBeenCalledOnce();
|
|
159
|
-
});
|
|
160
|
-
test('handles fetchValue throwing an error', async ()=>{
|
|
161
|
-
const error = new Error('Fetch failed');
|
|
162
|
-
const config = createExpiringConfig({
|
|
163
|
-
fetchValue: fetchValue.mockRejectedValue(error),
|
|
164
|
-
key: 'test-key',
|
|
165
|
-
store: mockStore,
|
|
166
|
-
ttl: 5000
|
|
167
|
-
});
|
|
168
|
-
// Mock empty cache
|
|
169
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
170
|
-
await expect(config.get()).rejects.toThrow('Fetch failed');
|
|
171
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
172
|
-
expect(mockStore.set).not.toHaveBeenCalled();
|
|
173
|
-
});
|
|
174
|
-
test('handles different data types as cached values', async ()=>{
|
|
175
|
-
const objectValue = {
|
|
176
|
-
key: 'value',
|
|
177
|
-
number: 42
|
|
178
|
-
};
|
|
179
|
-
const config = createExpiringConfig({
|
|
180
|
-
fetchValue: fetchValue.mockResolvedValue(objectValue),
|
|
181
|
-
key: 'test-key',
|
|
182
|
-
store: mockStore,
|
|
183
|
-
ttl: 5000
|
|
184
|
-
});
|
|
185
|
-
// Mock empty cache
|
|
186
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
187
|
-
const result = await config.get();
|
|
188
|
-
expect(result).toEqual(objectValue);
|
|
189
|
-
expect(mockStore.set).toHaveBeenCalledWith('test-key', {
|
|
190
|
-
updatedAt: expect.any(Number),
|
|
191
|
-
value: objectValue
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
test('works with TTL of 0 (immediate expiration)', async ()=>{
|
|
195
|
-
const testValue = 'test-value';
|
|
196
|
-
const config = createExpiringConfig({
|
|
197
|
-
fetchValue: fetchValue.mockResolvedValue(testValue),
|
|
198
|
-
key: 'test-key',
|
|
199
|
-
onRevalidate,
|
|
200
|
-
store: mockStore,
|
|
201
|
-
ttl: 0
|
|
202
|
-
});
|
|
203
|
-
// Mock cached value that would be immediately expired
|
|
204
|
-
// Use a timestamp from 1ms ago to ensure it's > ttl (0)
|
|
205
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
206
|
-
updatedAt: Date.now() - 1,
|
|
207
|
-
value: 'old-value'
|
|
208
|
-
});
|
|
209
|
-
const result = await config.get();
|
|
210
|
-
expect(result).toBe(testValue);
|
|
211
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
212
|
-
expect(onRevalidate).toHaveBeenCalledOnce();
|
|
213
|
-
});
|
|
214
|
-
test('works without optional callback functions', async ()=>{
|
|
215
|
-
const testValue = 'test-value';
|
|
216
|
-
const config = createExpiringConfig({
|
|
217
|
-
fetchValue: fetchValue.mockResolvedValue(testValue),
|
|
218
|
-
key: 'test-key',
|
|
219
|
-
store: mockStore,
|
|
220
|
-
ttl: 5000
|
|
221
|
-
});
|
|
222
|
-
// Mock empty cache
|
|
223
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
224
|
-
const result = await config.get();
|
|
225
|
-
expect(result).toBe(testValue);
|
|
226
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
227
|
-
});
|
|
228
|
-
test('handles cached value without updatedAt timestamp', async ()=>{
|
|
229
|
-
const newValue = 'new-value';
|
|
230
|
-
const config = createExpiringConfig({
|
|
231
|
-
fetchValue: fetchValue.mockResolvedValue(newValue),
|
|
232
|
-
key: 'test-key',
|
|
233
|
-
onFetch,
|
|
234
|
-
store: mockStore,
|
|
235
|
-
ttl: 5000
|
|
236
|
-
});
|
|
237
|
-
// Mock cached value without updatedAt (invalid cache entry)
|
|
238
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
239
|
-
value: 'old-value'
|
|
240
|
-
});
|
|
241
|
-
const result = await config.get();
|
|
242
|
-
expect(result).toBe(newValue);
|
|
243
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
244
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
245
|
-
});
|
|
246
|
-
test('handles cached value without value property', async ()=>{
|
|
247
|
-
const newValue = 'new-value';
|
|
248
|
-
const config = createExpiringConfig({
|
|
249
|
-
fetchValue: fetchValue.mockResolvedValue(newValue),
|
|
250
|
-
key: 'test-key',
|
|
251
|
-
onFetch,
|
|
252
|
-
store: mockStore,
|
|
253
|
-
ttl: 5000
|
|
254
|
-
});
|
|
255
|
-
// Mock cached entry without value property
|
|
256
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
257
|
-
updatedAt: Date.now()
|
|
258
|
-
});
|
|
259
|
-
const result = await config.get();
|
|
260
|
-
expect(result).toBe(newValue);
|
|
261
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
262
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
263
|
-
});
|
|
264
|
-
test('stores timestamp correctly when caching new values', async ()=>{
|
|
265
|
-
const testValue = 'test-value';
|
|
266
|
-
const config = createExpiringConfig({
|
|
267
|
-
fetchValue: fetchValue.mockResolvedValue(testValue),
|
|
268
|
-
key: 'test-key',
|
|
269
|
-
store: mockStore,
|
|
270
|
-
ttl: 5000
|
|
271
|
-
});
|
|
272
|
-
// Mock empty cache
|
|
273
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
274
|
-
await config.get();
|
|
275
|
-
expect(mockStore.set).toHaveBeenCalledWith('test-key', {
|
|
276
|
-
updatedAt: expect.any(Number),
|
|
277
|
-
value: testValue
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
test('subsequent requests after cache is populated use cached value', async ()=>{
|
|
281
|
-
const testValue = 'test-value';
|
|
282
|
-
const config = createExpiringConfig({
|
|
283
|
-
fetchValue: fetchValue.mockResolvedValue(testValue),
|
|
284
|
-
key: 'test-key',
|
|
285
|
-
onCacheHit,
|
|
286
|
-
onFetch,
|
|
287
|
-
store: mockStore,
|
|
288
|
-
ttl: 5000
|
|
289
|
-
});
|
|
290
|
-
// Mock empty cache for first request
|
|
291
|
-
vi.mocked(mockStore.get).mockReturnValueOnce(undefined);
|
|
292
|
-
// First request should fetch
|
|
293
|
-
const result1 = await config.get();
|
|
294
|
-
// Mock cache populated for subsequent request
|
|
295
|
-
vi.mocked(mockStore.get).mockReturnValueOnce({
|
|
296
|
-
updatedAt: Date.now(),
|
|
297
|
-
value: testValue
|
|
298
|
-
});
|
|
299
|
-
// Second request should hit cache
|
|
300
|
-
const result2 = await config.get();
|
|
301
|
-
expect(result1).toBe(testValue);
|
|
302
|
-
expect(result2).toBe(testValue);
|
|
303
|
-
expect(fetchValue).toHaveBeenCalledOnce();
|
|
304
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
305
|
-
expect(onCacheHit).toHaveBeenCalledOnce();
|
|
306
|
-
});
|
|
307
|
-
test('throws when cached value fails validateValue', async ()=>{
|
|
308
|
-
const invalidCached = 123;
|
|
309
|
-
const ttl = 10_000;
|
|
310
|
-
const validateValue = vi.fn((v)=>typeof v === 'string');
|
|
311
|
-
const config = createExpiringConfig({
|
|
312
|
-
fetchValue,
|
|
313
|
-
key: 'test-key',
|
|
314
|
-
onCacheHit,
|
|
315
|
-
onFetch,
|
|
316
|
-
onRevalidate,
|
|
317
|
-
store: mockStore,
|
|
318
|
-
ttl,
|
|
319
|
-
// @ts-expect-error vitest mocks don't jive with assertions
|
|
320
|
-
validateValue
|
|
321
|
-
});
|
|
322
|
-
// Cached entry that is not expired but invalid per validateValue
|
|
323
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
324
|
-
updatedAt: Date.now(),
|
|
325
|
-
value: invalidCached
|
|
326
|
-
});
|
|
327
|
-
await expect(config.get()).rejects.toThrow('Stored value is invalid');
|
|
328
|
-
expect(validateValue).toHaveBeenCalledOnce();
|
|
329
|
-
expect(onCacheHit).not.toHaveBeenCalled();
|
|
330
|
-
expect(onFetch).not.toHaveBeenCalled();
|
|
331
|
-
expect(onRevalidate).not.toHaveBeenCalled();
|
|
332
|
-
expect(mockStore.set).not.toHaveBeenCalled();
|
|
333
|
-
});
|
|
334
|
-
test('throws when fetched value fails validateValue (cache miss)', async ()=>{
|
|
335
|
-
const validateValue = vi.fn((v)=>typeof v === 'string');
|
|
336
|
-
const config = createExpiringConfig({
|
|
337
|
-
fetchValue: fetchValue.mockResolvedValue(42),
|
|
338
|
-
key: 'test-key',
|
|
339
|
-
onFetch,
|
|
340
|
-
store: mockStore,
|
|
341
|
-
ttl: 5000,
|
|
342
|
-
// @ts-expect-error vitest mocks don't jive with assertions
|
|
343
|
-
validateValue
|
|
344
|
-
});
|
|
345
|
-
// Empty cache
|
|
346
|
-
vi.mocked(mockStore.get).mockReturnValue(undefined);
|
|
347
|
-
await expect(config.get()).rejects.toThrow('Fetched value is invalid');
|
|
348
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
349
|
-
expect(validateValue).toHaveBeenCalledOnce();
|
|
350
|
-
expect(mockStore.set).not.toHaveBeenCalled();
|
|
351
|
-
});
|
|
352
|
-
test('returns cached value when validateValue accepts it', async ()=>{
|
|
353
|
-
const cachedValue = 'ok';
|
|
354
|
-
const validateValue = vi.fn((v)=>typeof v === 'string');
|
|
355
|
-
const config = createExpiringConfig({
|
|
356
|
-
fetchValue,
|
|
357
|
-
key: 'test-key',
|
|
358
|
-
onCacheHit,
|
|
359
|
-
store: mockStore,
|
|
360
|
-
ttl: 5000,
|
|
361
|
-
// @ts-expect-error vitest mocks don't jive with assertions
|
|
362
|
-
validateValue
|
|
363
|
-
});
|
|
364
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
365
|
-
updatedAt: Date.now(),
|
|
366
|
-
value: cachedValue
|
|
367
|
-
});
|
|
368
|
-
const result = await config.get();
|
|
369
|
-
expect(result).toBe(cachedValue);
|
|
370
|
-
expect(validateValue).toHaveBeenCalledOnce();
|
|
371
|
-
expect(onCacheHit).toHaveBeenCalledOnce();
|
|
372
|
-
expect(fetchValue).not.toHaveBeenCalled();
|
|
373
|
-
});
|
|
374
|
-
test('revalidation path validates fetched value and throws if invalid', async ()=>{
|
|
375
|
-
const validateValue = vi.fn((v)=>typeof v === 'string');
|
|
376
|
-
const config = createExpiringConfig({
|
|
377
|
-
fetchValue: fetchValue.mockResolvedValue(99),
|
|
378
|
-
key: 'test-key',
|
|
379
|
-
onFetch,
|
|
380
|
-
onRevalidate,
|
|
381
|
-
store: mockStore,
|
|
382
|
-
ttl: 1,
|
|
383
|
-
// @ts-expect-error vitest mocks don't jive with assertions
|
|
384
|
-
validateValue
|
|
385
|
-
});
|
|
386
|
-
// Cached value that has expired but is otherwise valid in shape and passes validate
|
|
387
|
-
vi.mocked(mockStore.get).mockReturnValue({
|
|
388
|
-
updatedAt: Date.now() - 10,
|
|
389
|
-
value: 'stale'
|
|
390
|
-
});
|
|
391
|
-
await expect(config.get()).rejects.toThrow('Fetched value is invalid');
|
|
392
|
-
expect(onRevalidate).toHaveBeenCalledOnce();
|
|
393
|
-
expect(onFetch).toHaveBeenCalledOnce();
|
|
394
|
-
// validateValue called for stored value and fetched value
|
|
395
|
-
expect(validateValue).toHaveBeenCalledTimes(2);
|
|
396
|
-
expect(mockStore.set).not.toHaveBeenCalled();
|
|
397
|
-
});
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
//# sourceMappingURL=createExpiringConfig.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/util/__tests__/createExpiringConfig.test.ts"],"sourcesContent":["import type ConfigStore from 'configstore'\n\nimport {beforeEach, describe, expect, test, vi} from 'vitest'\n\nimport {createExpiringConfig} from '../createExpiringConfig.js'\n\ndescribe('createExpiringConfig', () => {\n let mockStore: ConfigStore\n let fetchValue: ReturnType<typeof vi.fn>\n let onCacheHit: ReturnType<typeof vi.fn>\n let onFetch: ReturnType<typeof vi.fn>\n let onRevalidate: ReturnType<typeof vi.fn>\n\n beforeEach(() => {\n // Mock ConfigStore\n mockStore = {\n delete: vi.fn(),\n get: vi.fn(),\n set: vi.fn(),\n } as unknown as ConfigStore\n\n // Reset all mocks\n fetchValue = vi.fn()\n onCacheHit = vi.fn()\n onFetch = vi.fn()\n onRevalidate = vi.fn()\n })\n\n test('returns fetched value when cache is empty', async () => {\n const testValue = 'test-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(testValue),\n key: 'test-key',\n onCacheHit,\n onFetch,\n onRevalidate,\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n const result = await config.get()\n\n expect(result).toBe(testValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n expect(onCacheHit).not.toHaveBeenCalled()\n expect(onRevalidate).not.toHaveBeenCalled()\n expect(mockStore.set).toHaveBeenCalledWith('test-key', {\n updatedAt: expect.any(Number),\n value: testValue,\n })\n })\n\n test('returns cached value when it has not expired', async () => {\n const cachedValue = 'cached-value'\n const ttl = 5000\n const updatedAt = Date.now() - 1000 // 1 second ago (not expired)\n\n const config = createExpiringConfig({\n fetchValue,\n key: 'test-key',\n onCacheHit,\n onFetch,\n onRevalidate,\n store: mockStore,\n ttl,\n })\n\n // Mock cached value that hasn't expired\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt,\n value: cachedValue,\n })\n\n const result = await config.get()\n\n expect(result).toBe(cachedValue)\n expect(fetchValue).not.toHaveBeenCalled()\n expect(onCacheHit).toHaveBeenCalledOnce()\n expect(onFetch).not.toHaveBeenCalled()\n expect(onRevalidate).not.toHaveBeenCalled()\n expect(mockStore.set).not.toHaveBeenCalled()\n })\n\n test('fetches new value when cached value has expired', async () => {\n const newValue = 'new-value'\n const ttl = 1000\n const updatedAt = Date.now() - 2000 // 2 seconds ago (expired)\n\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(newValue),\n key: 'test-key',\n onCacheHit,\n onFetch,\n onRevalidate,\n store: mockStore,\n ttl,\n })\n\n // Mock expired cached value\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt,\n value: 'old-value',\n })\n\n const result = await config.get()\n\n expect(result).toBe(newValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onRevalidate).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n expect(onCacheHit).not.toHaveBeenCalled()\n expect(mockStore.set).toHaveBeenCalledWith('test-key', {\n updatedAt: expect.any(Number),\n value: newValue,\n })\n })\n\n test('deletes cached value from store', () => {\n const config = createExpiringConfig({\n fetchValue,\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n config.delete()\n\n expect(mockStore.delete).toHaveBeenCalledWith('test-key')\n })\n\n test('handles concurrent get() calls correctly', async () => {\n const testValue = 'test-value'\n let resolvePromise: (value: string) => void\n const delayedFetch = new Promise<string>((resolve) => {\n resolvePromise = resolve\n })\n\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockReturnValue(delayedFetch),\n key: 'test-key',\n onFetch,\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n // Start multiple concurrent get() calls\n const promise1 = config.get()\n const promise2 = config.get()\n const promise3 = config.get()\n\n // Resolve the fetch\n resolvePromise!(testValue)\n\n const [result1, result2, result3] = await Promise.all([promise1, promise2, promise3])\n\n expect(result1).toBe(testValue)\n expect(result2).toBe(testValue)\n expect(result3).toBe(testValue)\n expect(fetchValue).toHaveBeenCalledOnce() // Only one fetch should happen\n expect(onFetch).toHaveBeenCalledOnce()\n })\n\n test('handles synchronous fetchValue function', async () => {\n const testValue = 'sync-value'\n const syncFetchValue = vi.fn().mockReturnValue(testValue)\n\n const config = createExpiringConfig({\n fetchValue: syncFetchValue,\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n const result = await config.get()\n\n expect(result).toBe(testValue)\n expect(syncFetchValue).toHaveBeenCalledOnce()\n })\n\n test('handles fetchValue throwing an error', async () => {\n const error = new Error('Fetch failed')\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockRejectedValue(error),\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n await expect(config.get()).rejects.toThrow('Fetch failed')\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(mockStore.set).not.toHaveBeenCalled()\n })\n\n test('handles different data types as cached values', async () => {\n const objectValue = {key: 'value', number: 42}\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(objectValue),\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n const result = await config.get()\n\n expect(result).toEqual(objectValue)\n expect(mockStore.set).toHaveBeenCalledWith('test-key', {\n updatedAt: expect.any(Number),\n value: objectValue,\n })\n })\n\n test('works with TTL of 0 (immediate expiration)', async () => {\n const testValue = 'test-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(testValue),\n key: 'test-key',\n onRevalidate,\n store: mockStore,\n ttl: 0,\n })\n\n // Mock cached value that would be immediately expired\n // Use a timestamp from 1ms ago to ensure it's > ttl (0)\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt: Date.now() - 1,\n value: 'old-value',\n })\n\n const result = await config.get()\n\n expect(result).toBe(testValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onRevalidate).toHaveBeenCalledOnce()\n })\n\n test('works without optional callback functions', async () => {\n const testValue = 'test-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(testValue),\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n const result = await config.get()\n\n expect(result).toBe(testValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n })\n\n test('handles cached value without updatedAt timestamp', async () => {\n const newValue = 'new-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(newValue),\n key: 'test-key',\n onFetch,\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock cached value without updatedAt (invalid cache entry)\n vi.mocked(mockStore.get).mockReturnValue({\n value: 'old-value',\n // updatedAt is missing\n })\n\n const result = await config.get()\n\n expect(result).toBe(newValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n })\n\n test('handles cached value without value property', async () => {\n const newValue = 'new-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(newValue),\n key: 'test-key',\n onFetch,\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock cached entry without value property\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt: Date.now(),\n // value is missing\n })\n\n const result = await config.get()\n\n expect(result).toBe(newValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n })\n\n test('stores timestamp correctly when caching new values', async () => {\n const testValue = 'test-value'\n\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(testValue),\n key: 'test-key',\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n await config.get()\n\n expect(mockStore.set).toHaveBeenCalledWith('test-key', {\n updatedAt: expect.any(Number),\n value: testValue,\n })\n })\n\n test('subsequent requests after cache is populated use cached value', async () => {\n const testValue = 'test-value'\n const config = createExpiringConfig({\n fetchValue: fetchValue.mockResolvedValue(testValue),\n key: 'test-key',\n onCacheHit,\n onFetch,\n store: mockStore,\n ttl: 5000,\n })\n\n // Mock empty cache for first request\n vi.mocked(mockStore.get).mockReturnValueOnce(undefined)\n\n // First request should fetch\n const result1 = await config.get()\n\n // Mock cache populated for subsequent request\n vi.mocked(mockStore.get).mockReturnValueOnce({\n updatedAt: Date.now(),\n value: testValue,\n })\n\n // Second request should hit cache\n const result2 = await config.get()\n\n expect(result1).toBe(testValue)\n expect(result2).toBe(testValue)\n expect(fetchValue).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n expect(onCacheHit).toHaveBeenCalledOnce()\n })\n\n test('throws when cached value fails validateValue', async () => {\n const invalidCached = 123\n const ttl = 10_000\n\n const validateValue = vi.fn((v: unknown): v is string => typeof v === 'string')\n\n const config = createExpiringConfig<string>({\n fetchValue,\n key: 'test-key',\n onCacheHit,\n onFetch,\n onRevalidate,\n store: mockStore,\n ttl,\n // @ts-expect-error vitest mocks don't jive with assertions\n validateValue,\n })\n\n // Cached entry that is not expired but invalid per validateValue\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt: Date.now(),\n value: invalidCached,\n })\n\n await expect(config.get()).rejects.toThrow('Stored value is invalid')\n expect(validateValue).toHaveBeenCalledOnce()\n expect(onCacheHit).not.toHaveBeenCalled()\n expect(onFetch).not.toHaveBeenCalled()\n expect(onRevalidate).not.toHaveBeenCalled()\n expect(mockStore.set).not.toHaveBeenCalled()\n })\n\n test('throws when fetched value fails validateValue (cache miss)', async () => {\n const validateValue = vi.fn((v: unknown): v is string => typeof v === 'string')\n const config = createExpiringConfig<string>({\n fetchValue: fetchValue.mockResolvedValue(42 as unknown as string),\n key: 'test-key',\n onFetch,\n store: mockStore,\n ttl: 5000,\n // @ts-expect-error vitest mocks don't jive with assertions\n validateValue,\n })\n\n // Empty cache\n vi.mocked(mockStore.get).mockReturnValue(undefined)\n\n await expect(config.get()).rejects.toThrow('Fetched value is invalid')\n expect(onFetch).toHaveBeenCalledOnce()\n expect(validateValue).toHaveBeenCalledOnce()\n expect(mockStore.set).not.toHaveBeenCalled()\n })\n\n test('returns cached value when validateValue accepts it', async () => {\n const cachedValue = 'ok'\n const validateValue = vi.fn((v: unknown): v is string => typeof v === 'string')\n const config = createExpiringConfig<string>({\n fetchValue,\n key: 'test-key',\n onCacheHit,\n store: mockStore,\n ttl: 5000,\n // @ts-expect-error vitest mocks don't jive with assertions\n validateValue,\n })\n\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt: Date.now(),\n value: cachedValue,\n })\n\n const result = await config.get()\n\n expect(result).toBe(cachedValue)\n expect(validateValue).toHaveBeenCalledOnce()\n expect(onCacheHit).toHaveBeenCalledOnce()\n expect(fetchValue).not.toHaveBeenCalled()\n })\n\n test('revalidation path validates fetched value and throws if invalid', async () => {\n const validateValue = vi.fn((v: unknown): v is string => typeof v === 'string')\n const config = createExpiringConfig<string>({\n fetchValue: fetchValue.mockResolvedValue(99 as unknown as string),\n key: 'test-key',\n onFetch,\n onRevalidate,\n store: mockStore,\n ttl: 1, // ensure expiration\n // @ts-expect-error vitest mocks don't jive with assertions\n validateValue,\n })\n\n // Cached value that has expired but is otherwise valid in shape and passes validate\n vi.mocked(mockStore.get).mockReturnValue({\n updatedAt: Date.now() - 10,\n value: 'stale',\n })\n\n await expect(config.get()).rejects.toThrow('Fetched value is invalid')\n expect(onRevalidate).toHaveBeenCalledOnce()\n expect(onFetch).toHaveBeenCalledOnce()\n // validateValue called for stored value and fetched value\n expect(validateValue).toHaveBeenCalledTimes(2)\n expect(mockStore.set).not.toHaveBeenCalled()\n })\n})\n"],"names":["beforeEach","describe","expect","test","vi","createExpiringConfig","mockStore","fetchValue","onCacheHit","onFetch","onRevalidate","delete","fn","get","set","testValue","config","mockResolvedValue","key","store","ttl","mocked","mockReturnValue","undefined","result","toBe","toHaveBeenCalledOnce","not","toHaveBeenCalled","toHaveBeenCalledWith","updatedAt","any","Number","value","cachedValue","Date","now","newValue","resolvePromise","delayedFetch","Promise","resolve","promise1","promise2","promise3","result1","result2","result3","all","syncFetchValue","error","Error","mockRejectedValue","rejects","toThrow","objectValue","number","toEqual","mockReturnValueOnce","invalidCached","validateValue","v","toHaveBeenCalledTimes"],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { parseStringFlag } from '../parseStringFlag.js';
|
|
3
|
-
describe('parseStringFlag', ()=>{
|
|
4
|
-
test.each([
|
|
5
|
-
{
|
|
6
|
-
desc: 'returns undefined when input is undefined',
|
|
7
|
-
expected: undefined,
|
|
8
|
-
flagName: 'dataset',
|
|
9
|
-
input: undefined
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
desc: 'returns valid string when input is non-empty',
|
|
13
|
-
expected: 'my-workspace',
|
|
14
|
-
flagName: 'workspace',
|
|
15
|
-
input: 'my-workspace'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
desc: 'returns string with spaces',
|
|
19
|
-
expected: 'test value',
|
|
20
|
-
flagName: 'tag',
|
|
21
|
-
input: 'test value'
|
|
22
|
-
}
|
|
23
|
-
])('$desc', async ({ expected, flagName, input })=>{
|
|
24
|
-
const result = await parseStringFlag(flagName, input);
|
|
25
|
-
expect(result).toBe(expected);
|
|
26
|
-
});
|
|
27
|
-
test.each([
|
|
28
|
-
{
|
|
29
|
-
desc: 'empty string',
|
|
30
|
-
expectedError: 'dataset argument is empty',
|
|
31
|
-
flagName: 'dataset',
|
|
32
|
-
input: ''
|
|
33
|
-
}
|
|
34
|
-
])('throws error when $desc', async ({ expectedError, flagName, input })=>{
|
|
35
|
-
await expect(parseStringFlag(flagName, input)).rejects.toThrow(expectedError);
|
|
36
|
-
});
|
|
37
|
-
test('returns whitespace string as-is (no trimming)', async ()=>{
|
|
38
|
-
const result = await parseStringFlag('workspace', ' ');
|
|
39
|
-
expect(result).toBe(' ');
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
//# sourceMappingURL=parseStringFlag.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/util/__tests__/parseStringFlag.test.ts"],"sourcesContent":["import {describe, expect, test} from 'vitest'\n\nimport {parseStringFlag} from '../parseStringFlag.js'\n\ndescribe('parseStringFlag', () => {\n test.each([\n {\n desc: 'returns undefined when input is undefined',\n expected: undefined,\n flagName: 'dataset',\n input: undefined,\n },\n {\n desc: 'returns valid string when input is non-empty',\n expected: 'my-workspace',\n flagName: 'workspace',\n input: 'my-workspace',\n },\n {\n desc: 'returns string with spaces',\n expected: 'test value',\n flagName: 'tag',\n input: 'test value',\n },\n ])('$desc', async ({expected, flagName, input}) => {\n const result = await parseStringFlag(flagName, input)\n expect(result).toBe(expected)\n })\n\n test.each([\n {\n desc: 'empty string',\n expectedError: 'dataset argument is empty',\n flagName: 'dataset',\n input: '',\n },\n ])('throws error when $desc', async ({expectedError, flagName, input}) => {\n await expect(parseStringFlag(flagName, input)).rejects.toThrow(expectedError)\n })\n\n test('returns whitespace string as-is (no trimming)', async () => {\n const result = await parseStringFlag('workspace', ' ')\n expect(result).toBe(' ')\n })\n})\n"],"names":["describe","expect","test","parseStringFlag","each","desc","expected","undefined","flagName","input","result","toBe","expectedError","rejects","toThrow"],"mappings":"AAAA,SAAQA,QAAQ,EAAEC,MAAM,EAAEC,IAAI,QAAO,SAAQ;AAE7C,SAAQC,eAAe,QAAO,wBAAuB;AAErDH,SAAS,mBAAmB;IAC1BE,KAAKE,IAAI,CAAC;QACR;YACEC,MAAM;YACNC,UAAUC;YACVC,UAAU;YACVC,OAAOF;QACT;QACA;YACEF,MAAM;YACNC,UAAU;YACVE,UAAU;YACVC,OAAO;QACT;QACA;YACEJ,MAAM;YACNC,UAAU;YACVE,UAAU;YACVC,OAAO;QACT;KACD,EAAE,SAAS,OAAO,EAACH,QAAQ,EAAEE,QAAQ,EAAEC,KAAK,EAAC;QAC5C,MAAMC,SAAS,MAAMP,gBAAgBK,UAAUC;QAC/CR,OAAOS,QAAQC,IAAI,CAACL;IACtB;IAEAJ,KAAKE,IAAI,CAAC;QACR;YACEC,MAAM;YACNO,eAAe;YACfJ,UAAU;YACVC,OAAO;QACT;KACD,EAAE,2BAA2B,OAAO,EAACG,aAAa,EAAEJ,QAAQ,EAAEC,KAAK,EAAC;QACnE,MAAMR,OAAOE,gBAAgBK,UAAUC,QAAQI,OAAO,CAACC,OAAO,CAACF;IACjE;IAEAV,KAAK,iDAAiD;QACpD,MAAMQ,SAAS,MAAMP,gBAAgB,aAAa;QAClDF,OAAOS,QAAQC,IAAI,CAAC;IACtB;AACF"}
|