@demokit-ai/swr 0.0.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.
@@ -0,0 +1,415 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { MutatorCallback, MutatorOptions, SWRConfiguration, Middleware } from 'swr';
3
+ import { QueryKey, QueryKeyMatchResult } from '@demokit-ai/core';
4
+ export { matchQueryKey } from '@demokit-ai/core';
5
+ import { ReactNode } from 'react';
6
+ import { SWRMutationConfiguration, SWRMutationResponse } from 'swr/mutation';
7
+
8
+ /**
9
+ * Context provided to SWR fixture handlers
10
+ */
11
+ interface SWRFixtureContext {
12
+ /**
13
+ * The SWR key (can be string, array, or object)
14
+ */
15
+ key: string | unknown[];
16
+ /**
17
+ * Normalized key as QueryKey for pattern matching
18
+ */
19
+ normalizedKey: QueryKey;
20
+ /**
21
+ * Extracted parameters from pattern matching
22
+ */
23
+ params: Record<string, unknown>;
24
+ /**
25
+ * The match result from pattern matching
26
+ */
27
+ match: QueryKeyMatchResult;
28
+ }
29
+ /**
30
+ * A fixture handler can be:
31
+ * - A static value (object, array, primitive)
32
+ * - A function that receives context and returns data
33
+ * - An async function for dynamic fixtures
34
+ */
35
+ type SWRFixtureHandler<TData = unknown> = TData | ((context: SWRFixtureContext) => TData) | ((context: SWRFixtureContext) => Promise<TData>);
36
+ /**
37
+ * Map of key patterns to fixture handlers
38
+ */
39
+ type SWRFixtureMap = Map<QueryKey, SWRFixtureHandler>;
40
+ /**
41
+ * Object-based fixture map (easier to define)
42
+ * Keys are JSON-stringified key patterns or simple strings
43
+ */
44
+ type SWRFixtureMapObject = Record<string, SWRFixtureHandler>;
45
+ /**
46
+ * Context provided to mutation fixture handlers
47
+ */
48
+ interface SWRMutationFixtureContext<TData = unknown, TArg = unknown> {
49
+ /**
50
+ * The mutation key
51
+ */
52
+ key: string | unknown[];
53
+ /**
54
+ * The argument passed to the mutation
55
+ */
56
+ arg: TArg;
57
+ /**
58
+ * Current data in the cache
59
+ */
60
+ currentData: TData | undefined;
61
+ /**
62
+ * Function to mutate other SWR keys
63
+ */
64
+ mutate: <T>(key: string | unknown[], data?: T | Promise<T> | MutatorCallback<T>, opts?: boolean | MutatorOptions<T>) => Promise<T | undefined>;
65
+ }
66
+ /**
67
+ * A mutation fixture handler
68
+ */
69
+ type SWRMutationFixtureHandler<TData = unknown, TArg = unknown> = TData | ((context: SWRMutationFixtureContext<TData, TArg>) => TData) | ((context: SWRMutationFixtureContext<TData, TArg>) => Promise<TData>);
70
+ /**
71
+ * Map of mutation keys to fixture handlers
72
+ */
73
+ type SWRMutationFixtureMap = Map<string, SWRMutationFixtureHandler>;
74
+ /**
75
+ * Object-based mutation fixture map
76
+ */
77
+ type SWRMutationFixtureMapObject = Record<string, SWRMutationFixtureHandler>;
78
+ /**
79
+ * Configuration for DemoSWRProvider
80
+ */
81
+ interface DemoSWRProviderConfig {
82
+ /**
83
+ * Fixtures - map of key patterns to handlers
84
+ */
85
+ fixtures?: SWRFixtureMap | SWRFixtureMapObject;
86
+ /**
87
+ * Mutation fixtures - map of mutation names to handlers
88
+ */
89
+ mutations?: SWRMutationFixtureMap | SWRMutationFixtureMapObject;
90
+ /**
91
+ * Whether demo mode is enabled
92
+ * @default false
93
+ */
94
+ enabled?: boolean;
95
+ /**
96
+ * Delay in ms before returning fixture data (simulates network latency)
97
+ * @default 0
98
+ */
99
+ delay?: number;
100
+ /**
101
+ * Fallback data to use for SWR's fallback option
102
+ * Will be merged with any static fixture values
103
+ */
104
+ fallback?: Record<string, unknown>;
105
+ /**
106
+ * Additional SWR configuration to merge
107
+ */
108
+ swrConfig?: SWRConfiguration;
109
+ }
110
+ /**
111
+ * Props for DemoSWRProvider
112
+ */
113
+ interface DemoSWRProviderProps extends DemoSWRProviderConfig {
114
+ /**
115
+ * Child components
116
+ */
117
+ children: ReactNode;
118
+ }
119
+ /**
120
+ * Return type of useDemoSWR hook
121
+ */
122
+ interface DemoSWRState {
123
+ /**
124
+ * Whether demo mode is enabled
125
+ */
126
+ isDemoMode: boolean;
127
+ /**
128
+ * Add or update a fixture
129
+ */
130
+ setFixture: (pattern: QueryKey, handler: SWRFixtureHandler) => void;
131
+ /**
132
+ * Remove a fixture
133
+ */
134
+ removeFixture: (pattern: QueryKey) => void;
135
+ /**
136
+ * Add or update a mutation fixture
137
+ */
138
+ setMutationFixture: (name: string, handler: SWRMutationFixtureHandler) => void;
139
+ /**
140
+ * Remove a mutation fixture
141
+ */
142
+ removeMutationFixture: (name: string) => void;
143
+ /**
144
+ * Get the demo-aware fetcher function
145
+ */
146
+ getFetcher: () => <T>(key: string | unknown[]) => Promise<T>;
147
+ /**
148
+ * Get the demo middleware
149
+ */
150
+ getMiddleware: () => Middleware;
151
+ }
152
+
153
+ /**
154
+ * Provider component for DemoKit SWR integration
155
+ *
156
+ * Wraps SWRConfig and intercepts fetches when demo mode is enabled.
157
+ * Uses SWR's middleware pattern for maximum flexibility.
158
+ *
159
+ * @example
160
+ * // With object-based fixtures
161
+ * <DemoSWRProvider
162
+ * enabled={true}
163
+ * fixtures={{
164
+ * '/api/users': [{ id: '1', name: 'Demo User' }],
165
+ * '["/api/users", ":id"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),
166
+ * '["/api/projects", { status: ":status" }]': ({ params }) => [
167
+ * { id: '1', name: 'Project', status: params.status },
168
+ * ],
169
+ * }}
170
+ * delay={100}
171
+ * >
172
+ * <App />
173
+ * </DemoSWRProvider>
174
+ *
175
+ * @example
176
+ * // With Map-based fixtures
177
+ * const fixtures = new Map([
178
+ * [['/api/users'], [{ id: '1', name: 'Demo User' }]],
179
+ * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'Demo User' })],
180
+ * ])
181
+ *
182
+ * <DemoSWRProvider enabled={true} fixtures={fixtures}>
183
+ * <App />
184
+ * </DemoSWRProvider>
185
+ *
186
+ * @example
187
+ * // With cache seeding via fallback
188
+ * <DemoSWRProvider
189
+ * enabled={true}
190
+ * fixtures={fixtures}
191
+ * fallback={{
192
+ * '/api/users': [{ id: '1', name: 'Pre-loaded User' }],
193
+ * }}
194
+ * >
195
+ * <App />
196
+ * </DemoSWRProvider>
197
+ */
198
+ declare function DemoSWRProvider({ children, fixtures, mutations, enabled, delay, fallback, swrConfig, }: DemoSWRProviderProps): react_jsx_runtime.JSX.Element;
199
+
200
+ /**
201
+ * Hook to access DemoSWR state and controls
202
+ *
203
+ * @returns DemoSWR context value
204
+ * @throws Error if used outside of DemoSWRProvider
205
+ *
206
+ * @example
207
+ * function MyComponent() {
208
+ * const { isDemoMode, setFixture } = useDemoSWR()
209
+ *
210
+ * // Dynamically add a fixture
211
+ * const handleAddFixture = () => {
212
+ * setFixture(['/api/users', 'custom'], { id: 'custom', name: 'Custom User' })
213
+ * }
214
+ *
215
+ * return (
216
+ * <button onClick={handleAddFixture}>Add Custom Fixture</button>
217
+ * )
218
+ * }
219
+ */
220
+ declare function useDemoSWR(): DemoSWRState;
221
+ /**
222
+ * Hook to check if demo mode is enabled
223
+ * Shorthand for useDemoSWR().isDemoMode
224
+ *
225
+ * @example
226
+ * function MyComponent() {
227
+ * const isDemoMode = useIsDemoSWRMode()
228
+ *
229
+ * return isDemoMode ? <DemoBadge /> : null
230
+ * }
231
+ */
232
+ declare function useIsDemoSWRMode(): boolean;
233
+ /**
234
+ * Options for useDemoSWRMutation hook
235
+ */
236
+ interface UseDemoSWRMutationOptions<TData, TError, TArg> extends Omit<SWRMutationConfiguration<TData, TError, string, TArg>, 'fetcher'> {
237
+ /**
238
+ * The real mutation function to use when demo mode is disabled
239
+ */
240
+ fetcher: (key: string, options: {
241
+ arg: TArg;
242
+ }) => Promise<TData>;
243
+ /**
244
+ * Demo fixture handler for this mutation
245
+ */
246
+ demoFixture?: SWRMutationFixtureHandler<TData, TArg>;
247
+ /**
248
+ * Delay in ms before returning demo data
249
+ * @default 0
250
+ */
251
+ demoDelay?: number;
252
+ }
253
+ /**
254
+ * A mutation hook that automatically uses demo fixtures when demo mode is enabled
255
+ *
256
+ * Works with useSWRMutation from swr/mutation.
257
+ *
258
+ * @example
259
+ * const { trigger: createUser, isMutating } = useDemoSWRMutation('/api/users', {
260
+ * fetcher: async (key, { arg }) => api.createUser(arg),
261
+ * demoFixture: ({ arg, mutate }) => {
262
+ * // Create demo user
263
+ * const newUser = { id: crypto.randomUUID(), ...arg }
264
+ *
265
+ * // Update the users cache
266
+ * mutate('/api/users', (current: User[] = []) => [...current, newUser])
267
+ *
268
+ * return newUser
269
+ * },
270
+ * onSuccess: (data) => {
271
+ * console.log('Created user:', data)
272
+ * },
273
+ * })
274
+ *
275
+ * // Use like normal useSWRMutation
276
+ * createUser({ name: 'New User', email: 'user@example.com' })
277
+ */
278
+ declare function useDemoSWRMutation<TData = unknown, TError = unknown, TArg = unknown>(key: string, options: UseDemoSWRMutationOptions<TData, TError, TArg>): SWRMutationResponse<TData, TError, string, TArg>;
279
+
280
+ /**
281
+ * Options for creating a demo-aware fetcher
282
+ */
283
+ interface CreateDemoFetcherOptions {
284
+ /**
285
+ * Map of key patterns to fixture handlers
286
+ */
287
+ fixtures: SWRFixtureMap;
288
+ /**
289
+ * Function to check if demo mode is enabled
290
+ */
291
+ isEnabled: () => boolean;
292
+ /**
293
+ * Delay in ms before returning fixture data
294
+ * @default 0
295
+ */
296
+ delay?: number;
297
+ /**
298
+ * Fallback fetcher to use when demo mode is disabled
299
+ * or no fixture matches
300
+ */
301
+ fallbackFetcher?: <T>(key: string | unknown[]) => Promise<T>;
302
+ }
303
+ /**
304
+ * Create a demo-aware fetcher function for SWR
305
+ *
306
+ * This fetcher intercepts requests when demo mode is enabled
307
+ * and returns fixture data instead of making real API calls.
308
+ *
309
+ * @example
310
+ * const fixtures = new Map([
311
+ * [['/api/users'], [{ id: '1', name: 'Demo User' }]],
312
+ * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'User' })],
313
+ * ])
314
+ *
315
+ * const fetcher = createDemoFetcher({
316
+ * fixtures,
317
+ * isEnabled: () => isDemoMode,
318
+ * delay: 100,
319
+ * })
320
+ *
321
+ * // Use with SWR
322
+ * const { data } = useSWR('/api/users', fetcher)
323
+ */
324
+ declare function createDemoFetcher(options: CreateDemoFetcherOptions): <TData = unknown>(key: string | unknown[]) => Promise<TData>;
325
+ /**
326
+ * Default fetcher that uses fetch API
327
+ * Used as fallback when demo mode is disabled
328
+ */
329
+ declare function defaultFetcher<TData = unknown>(key: string | unknown[]): Promise<TData>;
330
+
331
+ /**
332
+ * Options for creating the demo middleware
333
+ */
334
+ interface CreateDemoMiddlewareOptions {
335
+ /**
336
+ * Map of key patterns to fixture handlers
337
+ */
338
+ fixtures: SWRFixtureMap;
339
+ /**
340
+ * Function to check if demo mode is enabled
341
+ */
342
+ isEnabled: () => boolean;
343
+ /**
344
+ * Delay in ms before returning fixture data
345
+ * @default 0
346
+ */
347
+ delay?: number;
348
+ }
349
+ /**
350
+ * Create a demo-aware SWR middleware
351
+ *
352
+ * This middleware intercepts SWR requests when demo mode is enabled
353
+ * and returns fixture data instead of using the original fetcher.
354
+ *
355
+ * @example
356
+ * import { SWRConfig } from 'swr'
357
+ * import { createDemoMiddleware } from '@demokit-ai/swr'
358
+ *
359
+ * const fixtures = new Map([
360
+ * [['/api/users'], [{ id: '1', name: 'Demo User' }]],
361
+ * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'User' })],
362
+ * ])
363
+ *
364
+ * const demoMiddleware = createDemoMiddleware({
365
+ * fixtures,
366
+ * isEnabled: () => isDemoMode,
367
+ * delay: 100,
368
+ * })
369
+ *
370
+ * function App() {
371
+ * return (
372
+ * <SWRConfig value={{ use: [demoMiddleware] }}>
373
+ * <YourApp />
374
+ * </SWRConfig>
375
+ * )
376
+ * }
377
+ */
378
+ declare function createDemoMiddleware(options: CreateDemoMiddlewareOptions): Middleware;
379
+
380
+ /**
381
+ * Normalize an SWR key to a QueryKey for matching
382
+ *
383
+ * SWR keys can be:
384
+ * - Strings: '/api/users' -> ['/api/users']
385
+ * - Arrays: ['/api/users', id] -> ['/api/users', id]
386
+ * - Functions that return keys (not handled here)
387
+ */
388
+ declare function normalizeKey(key: string | unknown[]): QueryKey;
389
+ /**
390
+ * Parse a JSON string pattern into a QueryKey
391
+ * Handles both array notation and simple string patterns
392
+ *
393
+ * @example
394
+ * parsePatternString('["/api/users"]') // ['/api/users']
395
+ * parsePatternString('["/api/users", ":id"]') // ['/api/users', ':id']
396
+ * parsePatternString('/api/users') // ['/api/users']
397
+ */
398
+ declare function parsePatternString(pattern: string): QueryKey;
399
+ /**
400
+ * Convert object-based fixture map to Map-based fixture map
401
+ */
402
+ declare function normalizeFixtureMap(fixtures: SWRFixtureMapObject | SWRFixtureMap): SWRFixtureMap;
403
+ /**
404
+ * Find a matching fixture for an SWR key
405
+ *
406
+ * @param fixtures - Map of key patterns to handlers
407
+ * @param key - The SWR key to match
408
+ * @returns Tuple of [handler, match result] or null if no match
409
+ */
410
+ declare function findMatchingFixture(fixtures: SWRFixtureMap, key: string | unknown[]): [SWRFixtureHandler, {
411
+ params: Record<string, unknown>;
412
+ normalizedKey: QueryKey;
413
+ }] | null;
414
+
415
+ export { type CreateDemoFetcherOptions, type CreateDemoMiddlewareOptions, DemoSWRProvider, type DemoSWRProviderConfig, type DemoSWRProviderProps, type DemoSWRState, type SWRFixtureContext, type SWRFixtureHandler, type SWRFixtureMap, type SWRFixtureMapObject, type SWRMutationFixtureContext, type SWRMutationFixtureHandler, type SWRMutationFixtureMap, type SWRMutationFixtureMapObject, type UseDemoSWRMutationOptions, createDemoFetcher, createDemoMiddleware, defaultFetcher, findMatchingFixture, normalizeFixtureMap, normalizeKey, parsePatternString, useDemoSWR, useDemoSWRMutation, useIsDemoSWRMode };