@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.
package/dist/index.cjs ADDED
@@ -0,0 +1,293 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var swr = require('swr');
5
+ var core = require('@demokit-ai/core');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var useSWRMutation = require('swr/mutation');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var useSWRMutation__default = /*#__PURE__*/_interopDefault(useSWRMutation);
12
+
13
+ // src/provider.tsx
14
+ var DemoSWRContext = react.createContext(void 0);
15
+ DemoSWRContext.displayName = "DemoSWRContext";
16
+ function normalizeKey(key) {
17
+ if (typeof key === "string") {
18
+ return [key];
19
+ }
20
+ return key.map((element) => {
21
+ if (element === null || element === void 0) {
22
+ return element;
23
+ }
24
+ if (typeof element === "object") {
25
+ return element;
26
+ }
27
+ return element;
28
+ });
29
+ }
30
+ function parsePatternString(pattern) {
31
+ if (pattern.startsWith("[")) {
32
+ try {
33
+ return JSON.parse(pattern);
34
+ } catch {
35
+ }
36
+ }
37
+ return [pattern];
38
+ }
39
+ function normalizeFixtureMap(fixtures) {
40
+ if (fixtures instanceof Map) {
41
+ return fixtures;
42
+ }
43
+ const map = /* @__PURE__ */ new Map();
44
+ for (const [pattern, handler] of Object.entries(fixtures)) {
45
+ map.set(parsePatternString(pattern), handler);
46
+ }
47
+ return map;
48
+ }
49
+ function findMatchingFixture(fixtures, key) {
50
+ const normalizedKey = normalizeKey(key);
51
+ const result = core.findMatchingQueryKeyPattern(fixtures, normalizedKey);
52
+ if (result) {
53
+ const [, handler, matchResult] = result;
54
+ return [handler, { params: matchResult.params, normalizedKey }];
55
+ }
56
+ return null;
57
+ }
58
+
59
+ // src/fetcher.ts
60
+ function createDemoFetcher(options) {
61
+ const { fixtures, isEnabled, delay = 0, fallbackFetcher } = options;
62
+ return async function demoFetcher(key) {
63
+ if (!isEnabled()) {
64
+ if (fallbackFetcher) {
65
+ return fallbackFetcher(key);
66
+ }
67
+ throw new Error(
68
+ `[DemoKit SWR] No fallback fetcher provided and demo mode is disabled. Key: ${JSON.stringify(key)}`
69
+ );
70
+ }
71
+ const match = findMatchingFixture(fixtures, key);
72
+ if (!match) {
73
+ if (fallbackFetcher) {
74
+ return fallbackFetcher(key);
75
+ }
76
+ throw new Error(`[DemoKit SWR] No fixture found for key: ${JSON.stringify(key)}`);
77
+ }
78
+ const [handler, { params, normalizedKey }] = match;
79
+ if (delay > 0) {
80
+ await new Promise((resolve) => setTimeout(resolve, delay));
81
+ }
82
+ const context = {
83
+ key,
84
+ normalizedKey,
85
+ params,
86
+ match: { matched: true, params }
87
+ };
88
+ if (typeof handler === "function") {
89
+ return handler(context);
90
+ }
91
+ return handler;
92
+ };
93
+ }
94
+ async function defaultFetcher(key) {
95
+ const url = typeof key === "string" ? key : String(key[0]);
96
+ const response = await fetch(url);
97
+ if (!response.ok) {
98
+ const error = new Error("An error occurred while fetching the data.");
99
+ throw error;
100
+ }
101
+ return response.json();
102
+ }
103
+
104
+ // src/middleware.ts
105
+ function createDemoMiddleware(options) {
106
+ const { fixtures, isEnabled, delay = 0 } = options;
107
+ const middleware = (useSWRNext) => (key, fetcher, config) => {
108
+ const extendedFetcher = fetcher === null ? null : async (...args) => {
109
+ const resolvedKey = typeof key === "function" ? key() : key;
110
+ if (resolvedKey === null || resolvedKey === void 0) {
111
+ return fetcher(...args);
112
+ }
113
+ if (!isEnabled()) {
114
+ return fetcher(...args);
115
+ }
116
+ const keyToMatch = typeof resolvedKey === "string" ? resolvedKey : resolvedKey;
117
+ const match = findMatchingFixture(fixtures, keyToMatch);
118
+ if (!match) {
119
+ return fetcher(...args);
120
+ }
121
+ const [handler, { params, normalizedKey }] = match;
122
+ if (delay > 0) {
123
+ await new Promise((resolve) => setTimeout(resolve, delay));
124
+ }
125
+ const context = {
126
+ key: resolvedKey,
127
+ normalizedKey,
128
+ params,
129
+ match: { matched: true, params }
130
+ };
131
+ if (typeof handler === "function") {
132
+ return handler(context);
133
+ }
134
+ return handler;
135
+ };
136
+ return useSWRNext(key, extendedFetcher, config);
137
+ };
138
+ return middleware;
139
+ }
140
+ function DemoSWRProvider({
141
+ children,
142
+ fixtures = /* @__PURE__ */ new Map(),
143
+ mutations = /* @__PURE__ */ new Map(),
144
+ enabled = false,
145
+ delay = 0,
146
+ fallback = {},
147
+ swrConfig = {}
148
+ }) {
149
+ const fixturesRef = react.useRef(normalizeFixtureMap(fixtures));
150
+ const mutationFixturesRef = react.useRef(
151
+ mutations instanceof Map ? mutations : new Map(Object.entries(mutations))
152
+ );
153
+ const isDemoMode = enabled;
154
+ const demoMiddleware = react.useMemo(
155
+ () => createDemoMiddleware({
156
+ fixtures: fixturesRef.current,
157
+ isEnabled: () => isDemoMode,
158
+ delay
159
+ }),
160
+ [isDemoMode, delay]
161
+ );
162
+ const demoFetcher = react.useMemo(
163
+ () => createDemoFetcher({
164
+ fixtures: fixturesRef.current,
165
+ isEnabled: () => isDemoMode,
166
+ delay,
167
+ fallbackFetcher: defaultFetcher
168
+ }),
169
+ [isDemoMode, delay]
170
+ );
171
+ const combinedFallback = react.useMemo(() => {
172
+ if (!isDemoMode) return swrConfig.fallback || {};
173
+ const staticFixtures = {};
174
+ for (const [pattern, handler] of fixturesRef.current) {
175
+ if (typeof handler !== "function") {
176
+ const key = pattern.length === 1 ? String(pattern[0]) : JSON.stringify(pattern);
177
+ staticFixtures[key] = handler;
178
+ }
179
+ }
180
+ return {
181
+ ...staticFixtures,
182
+ ...fallback,
183
+ ...swrConfig.fallback || {}
184
+ };
185
+ }, [isDemoMode, fallback, swrConfig.fallback]);
186
+ const config = react.useMemo(
187
+ () => ({
188
+ ...swrConfig,
189
+ use: [...swrConfig.use || [], demoMiddleware],
190
+ fallback: combinedFallback,
191
+ // In demo mode, don't retry and keep data fresh longer
192
+ ...isDemoMode ? {
193
+ revalidateOnFocus: false,
194
+ revalidateOnReconnect: false,
195
+ shouldRetryOnError: false
196
+ } : {}
197
+ }),
198
+ [swrConfig, demoMiddleware, combinedFallback, isDemoMode]
199
+ );
200
+ const getFetcher = react.useCallback(() => demoFetcher, [demoFetcher]);
201
+ const getMiddleware = react.useCallback(() => demoMiddleware, [demoMiddleware]);
202
+ const contextValue = react.useMemo(
203
+ () => ({
204
+ isDemoMode,
205
+ setFixture: (pattern, handler) => {
206
+ fixturesRef.current.set(pattern, handler);
207
+ },
208
+ removeFixture: (pattern) => {
209
+ fixturesRef.current.delete(pattern);
210
+ },
211
+ setMutationFixture: (name, handler) => {
212
+ mutationFixturesRef.current.set(name, handler);
213
+ },
214
+ removeMutationFixture: (name) => {
215
+ mutationFixturesRef.current.delete(name);
216
+ },
217
+ getFetcher,
218
+ getMiddleware
219
+ }),
220
+ [isDemoMode, getFetcher, getMiddleware]
221
+ );
222
+ return /* @__PURE__ */ jsxRuntime.jsx(DemoSWRContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(swr.SWRConfig, { value: config, children }) });
223
+ }
224
+ function useDemoSWR() {
225
+ const context = react.useContext(DemoSWRContext);
226
+ if (context === void 0) {
227
+ throw new Error(
228
+ "useDemoSWR must be used within a DemoSWRProvider. Make sure to wrap your app with <DemoSWRProvider>."
229
+ );
230
+ }
231
+ return context;
232
+ }
233
+ function useIsDemoSWRMode() {
234
+ return useDemoSWR().isDemoMode;
235
+ }
236
+ function useDemoSWRMutation(key, options) {
237
+ const { fetcher, demoFixture, demoDelay = 0, ...mutationOptions } = options;
238
+ const { mutate } = swr.useSWRConfig();
239
+ let isDemoMode = false;
240
+ try {
241
+ const demoState = useDemoSWR();
242
+ isDemoMode = demoState.isDemoMode;
243
+ } catch {
244
+ }
245
+ const demoAwareFetcher = react.useCallback(
246
+ async (mutationKey, { arg }) => {
247
+ if (!isDemoMode) {
248
+ return fetcher(mutationKey, { arg });
249
+ }
250
+ if (demoDelay > 0) {
251
+ await new Promise((resolve) => setTimeout(resolve, demoDelay));
252
+ }
253
+ if (demoFixture !== void 0) {
254
+ const context = {
255
+ key: mutationKey,
256
+ arg,
257
+ currentData: void 0,
258
+ // SWR mutation doesn't have direct access to current data
259
+ mutate
260
+ };
261
+ if (typeof demoFixture === "function") {
262
+ const fixtureFn = demoFixture;
263
+ return fixtureFn(context);
264
+ }
265
+ return demoFixture;
266
+ }
267
+ console.warn(
268
+ `[DemoKit SWR] No mutation fixture found for "${key}". Using real mutation function.`
269
+ );
270
+ return fetcher(mutationKey, { arg });
271
+ },
272
+ [isDemoMode, fetcher, demoFixture, demoDelay, key, mutate]
273
+ );
274
+ return useSWRMutation__default.default(key, demoAwareFetcher, mutationOptions);
275
+ }
276
+
277
+ Object.defineProperty(exports, "matchQueryKey", {
278
+ enumerable: true,
279
+ get: function () { return core.matchQueryKey; }
280
+ });
281
+ exports.DemoSWRProvider = DemoSWRProvider;
282
+ exports.createDemoFetcher = createDemoFetcher;
283
+ exports.createDemoMiddleware = createDemoMiddleware;
284
+ exports.defaultFetcher = defaultFetcher;
285
+ exports.findMatchingFixture = findMatchingFixture;
286
+ exports.normalizeFixtureMap = normalizeFixtureMap;
287
+ exports.normalizeKey = normalizeKey;
288
+ exports.parsePatternString = parsePatternString;
289
+ exports.useDemoSWR = useDemoSWR;
290
+ exports.useDemoSWRMutation = useDemoSWRMutation;
291
+ exports.useIsDemoSWRMode = useIsDemoSWRMode;
292
+ //# sourceMappingURL=index.cjs.map
293
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/matcher.ts","../src/fetcher.ts","../src/middleware.ts","../src/provider.tsx","../src/hooks.ts"],"names":["createContext","findMatchingQueryKeyPattern","useRef","useMemo","useCallback","jsx","SWRConfig","useContext","useSWRConfig","useSWRMutation"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client'\n\nimport { createContext } from 'react'\nimport type { DemoSWRState } from './types'\n\n/**\n * Context for DemoSWR state\n * @internal\n */\nexport const DemoSWRContext = createContext<DemoSWRState | undefined>(undefined)\n\nDemoSWRContext.displayName = 'DemoSWRContext'\n","import { matchQueryKey, findMatchingQueryKeyPattern } from '@demokit-ai/core'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { SWRFixtureHandler, SWRFixtureMap, SWRFixtureMapObject } from './types'\n\n/**\n * Normalize an SWR key to a QueryKey for matching\n *\n * SWR keys can be:\n * - Strings: '/api/users' -> ['/api/users']\n * - Arrays: ['/api/users', id] -> ['/api/users', id]\n * - Functions that return keys (not handled here)\n */\nexport function normalizeKey(key: string | unknown[]): QueryKey {\n if (typeof key === 'string') {\n return [key]\n }\n\n return key.map((element) => {\n if (element === null || element === undefined) {\n return element\n }\n if (typeof element === 'object') {\n return element as Record<string, unknown>\n }\n return element as string | number | boolean\n })\n}\n\n/**\n * Parse a JSON string pattern into a QueryKey\n * Handles both array notation and simple string patterns\n *\n * @example\n * parsePatternString('[\"/api/users\"]') // ['/api/users']\n * parsePatternString('[\"/api/users\", \":id\"]') // ['/api/users', ':id']\n * parsePatternString('/api/users') // ['/api/users']\n */\nexport function parsePatternString(pattern: string): QueryKey {\n // Try to parse as JSON array\n if (pattern.startsWith('[')) {\n try {\n return JSON.parse(pattern) as QueryKey\n } catch {\n // Fall through to simple string\n }\n }\n\n // Simple string becomes single-element array\n return [pattern]\n}\n\n/**\n * Convert object-based fixture map to Map-based fixture map\n */\nexport function normalizeFixtureMap(fixtures: SWRFixtureMapObject | SWRFixtureMap): SWRFixtureMap {\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const map = new Map<QueryKey, SWRFixtureHandler>()\n for (const [pattern, handler] of Object.entries(fixtures)) {\n map.set(parsePatternString(pattern), handler)\n }\n return map\n}\n\n/**\n * Find a matching fixture for an SWR key\n *\n * @param fixtures - Map of key patterns to handlers\n * @param key - The SWR key to match\n * @returns Tuple of [handler, match result] or null if no match\n */\nexport function findMatchingFixture(\n fixtures: SWRFixtureMap,\n key: string | unknown[]\n): [SWRFixtureHandler, { params: Record<string, unknown>; normalizedKey: QueryKey }] | null {\n const normalizedKey = normalizeKey(key)\n const result = findMatchingQueryKeyPattern(fixtures, normalizedKey)\n\n if (result) {\n const [, handler, matchResult] = result\n return [handler, { params: matchResult.params, normalizedKey }]\n }\n\n return null\n}\n\n/**\n * Re-export the matchQueryKey function for direct use\n */\nexport { matchQueryKey }","import type { QueryKey } from '@demokit-ai/core'\nimport type { SWRFixtureMap, SWRFixtureContext } from './types'\nimport { findMatchingFixture, normalizeKey } from './matcher'\n\n/**\n * Options for creating a demo-aware fetcher\n */\nexport interface CreateDemoFetcherOptions {\n /**\n * Map of key patterns to fixture handlers\n */\n fixtures: SWRFixtureMap\n\n /**\n * Function to check if demo mode is enabled\n */\n isEnabled: () => boolean\n\n /**\n * Delay in ms before returning fixture data\n * @default 0\n */\n delay?: number\n\n /**\n * Fallback fetcher to use when demo mode is disabled\n * or no fixture matches\n */\n fallbackFetcher?: <T>(key: string | unknown[]) => Promise<T>\n}\n\n/**\n * Create a demo-aware fetcher function for SWR\n *\n * This fetcher intercepts requests when demo mode is enabled\n * and returns fixture data instead of making real API calls.\n *\n * @example\n * const fixtures = new Map([\n * [['/api/users'], [{ id: '1', name: 'Demo User' }]],\n * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'User' })],\n * ])\n *\n * const fetcher = createDemoFetcher({\n * fixtures,\n * isEnabled: () => isDemoMode,\n * delay: 100,\n * })\n *\n * // Use with SWR\n * const { data } = useSWR('/api/users', fetcher)\n */\nexport function createDemoFetcher(options: CreateDemoFetcherOptions) {\n const { fixtures, isEnabled, delay = 0, fallbackFetcher } = options\n\n return async function demoFetcher<TData = unknown>(key: string | unknown[]): Promise<TData> {\n // If demo mode is not enabled, use fallback\n if (!isEnabled()) {\n if (fallbackFetcher) {\n return fallbackFetcher<TData>(key)\n }\n throw new Error(\n `[DemoKit SWR] No fallback fetcher provided and demo mode is disabled. ` +\n `Key: ${JSON.stringify(key)}`\n )\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, key)\n\n if (!match) {\n // No fixture found, try fallback\n if (fallbackFetcher) {\n return fallbackFetcher<TData>(key)\n }\n throw new Error(`[DemoKit SWR] No fixture found for key: ${JSON.stringify(key)}`)\n }\n\n const [handler, { params, normalizedKey }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Build context\n const context: SWRFixtureContext = {\n key,\n normalizedKey,\n params,\n match: { matched: true, params },\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler(context) as TData\n }\n\n // Return static value\n return handler as TData\n }\n}\n\n/**\n * Default fetcher that uses fetch API\n * Used as fallback when demo mode is disabled\n */\nexport async function defaultFetcher<TData = unknown>(key: string | unknown[]): Promise<TData> {\n const url = typeof key === 'string' ? key : String(key[0])\n const response = await fetch(url)\n\n if (!response.ok) {\n const error = new Error('An error occurred while fetching the data.')\n throw error\n }\n\n return response.json()\n}\n","import type { Middleware } from 'swr'\nimport type { SWRFixtureMap, SWRFixtureContext } from './types'\nimport { findMatchingFixture } from './matcher'\n\n/**\n * Options for creating the demo middleware\n */\nexport interface CreateDemoMiddlewareOptions {\n /**\n * Map of key patterns to fixture handlers\n */\n fixtures: SWRFixtureMap\n\n /**\n * Function to check if demo mode is enabled\n */\n isEnabled: () => boolean\n\n /**\n * Delay in ms before returning fixture data\n * @default 0\n */\n delay?: number\n}\n\n/**\n * Create a demo-aware SWR middleware\n *\n * This middleware intercepts SWR requests when demo mode is enabled\n * and returns fixture data instead of using the original fetcher.\n *\n * @example\n * import { SWRConfig } from 'swr'\n * import { createDemoMiddleware } from '@demokit-ai/swr'\n *\n * const fixtures = new Map([\n * [['/api/users'], [{ id: '1', name: 'Demo User' }]],\n * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'User' })],\n * ])\n *\n * const demoMiddleware = createDemoMiddleware({\n * fixtures,\n * isEnabled: () => isDemoMode,\n * delay: 100,\n * })\n *\n * function App() {\n * return (\n * <SWRConfig value={{ use: [demoMiddleware] }}>\n * <YourApp />\n * </SWRConfig>\n * )\n * }\n */\nexport function createDemoMiddleware(options: CreateDemoMiddlewareOptions): Middleware {\n const { fixtures, isEnabled, delay = 0 } = options\n\n // Use the simpler middleware pattern that SWR expects\n const middleware: Middleware = (useSWRNext) => (key, fetcher, config) => {\n // Create an extended fetcher that checks for demo mode\n const extendedFetcher =\n fetcher === null\n ? null\n : async (...args: Parameters<typeof fetcher>) => {\n // Resolve the key if it's a function\n const resolvedKey = typeof key === 'function' ? key() : key\n\n // If no key, let SWR handle it\n if (resolvedKey === null || resolvedKey === undefined) {\n return fetcher(...args)\n }\n\n // If demo mode is not enabled, use original fetcher\n if (!isEnabled()) {\n return fetcher(...args)\n }\n\n // Normalize key for matching\n const keyToMatch =\n typeof resolvedKey === 'string' ? resolvedKey : (resolvedKey as unknown[])\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, keyToMatch)\n\n if (!match) {\n // No fixture found, use original fetcher\n return fetcher(...args)\n }\n\n const [handler, { params, normalizedKey }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Build context\n const context: SWRFixtureContext = {\n key: resolvedKey,\n normalizedKey,\n params,\n match: { matched: true, params },\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler(context)\n }\n\n // Return static value\n return handler\n }\n\n return useSWRNext(key, extendedFetcher, config)\n }\n\n return middleware\n}\n","'use client'\n\nimport { useMemo, useRef, useCallback } from 'react'\nimport { SWRConfig } from 'swr'\nimport type { QueryKey } from '@demokit-ai/core'\nimport { DemoSWRContext } from './context'\nimport { createDemoFetcher, defaultFetcher } from './fetcher'\nimport { createDemoMiddleware } from './middleware'\nimport { normalizeFixtureMap } from './matcher'\nimport type {\n DemoSWRProviderProps,\n SWRFixtureHandler,\n SWRFixtureMap,\n SWRMutationFixtureHandler,\n SWRMutationFixtureMap,\n DemoSWRState,\n} from './types'\n\n/**\n * Provider component for DemoKit SWR integration\n *\n * Wraps SWRConfig and intercepts fetches when demo mode is enabled.\n * Uses SWR's middleware pattern for maximum flexibility.\n *\n * @example\n * // With object-based fixtures\n * <DemoSWRProvider\n * enabled={true}\n * fixtures={{\n * '/api/users': [{ id: '1', name: 'Demo User' }],\n * '[\"/api/users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * '[\"/api/projects\", { status: \":status\" }]': ({ params }) => [\n * { id: '1', name: 'Project', status: params.status },\n * ],\n * }}\n * delay={100}\n * >\n * <App />\n * </DemoSWRProvider>\n *\n * @example\n * // With Map-based fixtures\n * const fixtures = new Map([\n * [['/api/users'], [{ id: '1', name: 'Demo User' }]],\n * [['/api/users', ':id'], ({ params }) => ({ id: params.id, name: 'Demo User' })],\n * ])\n *\n * <DemoSWRProvider enabled={true} fixtures={fixtures}>\n * <App />\n * </DemoSWRProvider>\n *\n * @example\n * // With cache seeding via fallback\n * <DemoSWRProvider\n * enabled={true}\n * fixtures={fixtures}\n * fallback={{\n * '/api/users': [{ id: '1', name: 'Pre-loaded User' }],\n * }}\n * >\n * <App />\n * </DemoSWRProvider>\n */\nexport function DemoSWRProvider({\n children,\n fixtures = new Map(),\n mutations = new Map(),\n enabled = false,\n delay = 0,\n fallback = {},\n swrConfig = {},\n}: DemoSWRProviderProps) {\n // Normalize fixtures\n const fixturesRef = useRef<SWRFixtureMap>(normalizeFixtureMap(fixtures))\n const mutationFixturesRef = useRef<SWRMutationFixtureMap>(\n mutations instanceof Map ? mutations : new Map(Object.entries(mutations))\n )\n\n const isDemoMode = enabled\n\n // Create demo middleware\n const demoMiddleware = useMemo(\n () =>\n createDemoMiddleware({\n fixtures: fixturesRef.current,\n isEnabled: () => isDemoMode,\n delay,\n }),\n [isDemoMode, delay]\n )\n\n // Create demo fetcher (for direct use)\n const demoFetcher = useMemo(\n () =>\n createDemoFetcher({\n fixtures: fixturesRef.current,\n isEnabled: () => isDemoMode,\n delay,\n fallbackFetcher: defaultFetcher,\n }),\n [isDemoMode, delay]\n )\n\n // Build fallback data from static fixtures + provided fallback\n const combinedFallback = useMemo(() => {\n if (!isDemoMode) return swrConfig.fallback || {}\n\n const staticFixtures: Record<string, unknown> = {}\n\n // Add static fixture values to fallback\n for (const [pattern, handler] of fixturesRef.current) {\n if (typeof handler !== 'function') {\n // Use the pattern as key for static fixtures\n const key = pattern.length === 1 ? String(pattern[0]) : JSON.stringify(pattern)\n staticFixtures[key] = handler\n }\n }\n\n return {\n ...staticFixtures,\n ...fallback,\n ...(swrConfig.fallback || {}),\n }\n }, [isDemoMode, fallback, swrConfig.fallback])\n\n // Build SWR config\n const config = useMemo(\n () => ({\n ...swrConfig,\n use: [...(swrConfig.use || []), demoMiddleware],\n fallback: combinedFallback,\n // In demo mode, don't retry and keep data fresh longer\n ...(isDemoMode\n ? {\n revalidateOnFocus: false,\n revalidateOnReconnect: false,\n shouldRetryOnError: false,\n }\n : {}),\n }),\n [swrConfig, demoMiddleware, combinedFallback, isDemoMode]\n )\n\n // Context value with manipulation methods\n const getFetcher = useCallback(() => demoFetcher, [demoFetcher])\n const getMiddleware = useCallback(() => demoMiddleware, [demoMiddleware])\n\n const contextValue = useMemo<DemoSWRState>(\n () => ({\n isDemoMode,\n\n setFixture: (pattern: QueryKey, handler: SWRFixtureHandler) => {\n fixturesRef.current.set(pattern, handler)\n },\n\n removeFixture: (pattern: QueryKey) => {\n fixturesRef.current.delete(pattern)\n },\n\n setMutationFixture: (name: string, handler: SWRMutationFixtureHandler) => {\n mutationFixturesRef.current.set(name, handler)\n },\n\n removeMutationFixture: (name: string) => {\n mutationFixturesRef.current.delete(name)\n },\n\n getFetcher,\n getMiddleware,\n }),\n [isDemoMode, getFetcher, getMiddleware]\n )\n\n return (\n <DemoSWRContext.Provider value={contextValue}>\n <SWRConfig value={config}>{children}</SWRConfig>\n </DemoSWRContext.Provider>\n )\n}\n","'use client'\n\nimport { useContext, useCallback } from 'react'\nimport useSWRMutation, { type SWRMutationConfiguration, type SWRMutationResponse } from 'swr/mutation'\nimport { useSWRConfig } from 'swr'\nimport { DemoSWRContext } from './context'\nimport type { DemoSWRState, SWRMutationFixtureContext, SWRMutationFixtureHandler } from './types'\n\n/**\n * Hook to access DemoSWR state and controls\n *\n * @returns DemoSWR context value\n * @throws Error if used outside of DemoSWRProvider\n *\n * @example\n * function MyComponent() {\n * const { isDemoMode, setFixture } = useDemoSWR()\n *\n * // Dynamically add a fixture\n * const handleAddFixture = () => {\n * setFixture(['/api/users', 'custom'], { id: 'custom', name: 'Custom User' })\n * }\n *\n * return (\n * <button onClick={handleAddFixture}>Add Custom Fixture</button>\n * )\n * }\n */\nexport function useDemoSWR(): DemoSWRState {\n const context = useContext(DemoSWRContext)\n\n if (context === undefined) {\n throw new Error(\n 'useDemoSWR must be used within a DemoSWRProvider. ' +\n 'Make sure to wrap your app with <DemoSWRProvider>.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to check if demo mode is enabled\n * Shorthand for useDemoSWR().isDemoMode\n *\n * @example\n * function MyComponent() {\n * const isDemoMode = useIsDemoSWRMode()\n *\n * return isDemoMode ? <DemoBadge /> : null\n * }\n */\nexport function useIsDemoSWRMode(): boolean {\n return useDemoSWR().isDemoMode\n}\n\n/**\n * Options for useDemoSWRMutation hook\n */\nexport interface UseDemoSWRMutationOptions<TData, TError, TArg>\n extends Omit<SWRMutationConfiguration<TData, TError, string, TArg>, 'fetcher'> {\n /**\n * The real mutation function to use when demo mode is disabled\n */\n fetcher: (key: string, options: { arg: TArg }) => Promise<TData>\n\n /**\n * Demo fixture handler for this mutation\n */\n demoFixture?: SWRMutationFixtureHandler<TData, TArg>\n\n /**\n * Delay in ms before returning demo data\n * @default 0\n */\n demoDelay?: number\n}\n\n/**\n * A mutation hook that automatically uses demo fixtures when demo mode is enabled\n *\n * Works with useSWRMutation from swr/mutation.\n *\n * @example\n * const { trigger: createUser, isMutating } = useDemoSWRMutation('/api/users', {\n * fetcher: async (key, { arg }) => api.createUser(arg),\n * demoFixture: ({ arg, mutate }) => {\n * // Create demo user\n * const newUser = { id: crypto.randomUUID(), ...arg }\n *\n * // Update the users cache\n * mutate('/api/users', (current: User[] = []) => [...current, newUser])\n *\n * return newUser\n * },\n * onSuccess: (data) => {\n * console.log('Created user:', data)\n * },\n * })\n *\n * // Use like normal useSWRMutation\n * createUser({ name: 'New User', email: 'user@example.com' })\n */\nexport function useDemoSWRMutation<TData = unknown, TError = unknown, TArg = unknown>(\n key: string,\n options: UseDemoSWRMutationOptions<TData, TError, TArg>\n): SWRMutationResponse<TData, TError, string, TArg> {\n const { fetcher, demoFixture, demoDelay = 0, ...mutationOptions } = options\n\n const { mutate } = useSWRConfig()\n\n // Try to get demo state - may not be in DemoSWRProvider context\n let isDemoMode = false\n try {\n const demoState = useDemoSWR()\n isDemoMode = demoState.isDemoMode\n } catch {\n // Not in DemoSWRProvider context, use real mutation\n }\n\n // Create the demo-aware mutation function\n const demoAwareFetcher = useCallback(\n async (mutationKey: string, { arg }: { arg: TArg }): Promise<TData> => {\n // If not in demo mode, use real mutation\n if (!isDemoMode) {\n return fetcher(mutationKey, { arg })\n }\n\n // Apply delay if configured\n if (demoDelay > 0) {\n await new Promise((resolve) => setTimeout(resolve, demoDelay))\n }\n\n // If a demo fixture is provided, use it\n if (demoFixture !== undefined) {\n const context: SWRMutationFixtureContext<TData, TArg> = {\n key: mutationKey,\n arg,\n currentData: undefined, // SWR mutation doesn't have direct access to current data\n mutate: mutate as SWRMutationFixtureContext<TData, TArg>['mutate'],\n }\n\n if (typeof demoFixture === 'function') {\n const fixtureFn = demoFixture as (\n context: SWRMutationFixtureContext<TData, TArg>\n ) => TData | Promise<TData>\n return fixtureFn(context)\n }\n return demoFixture as TData\n }\n\n // No fixture found, fall back to real mutation\n console.warn(\n `[DemoKit SWR] No mutation fixture found for \"${key}\". Using real mutation function.`\n )\n return fetcher(mutationKey, { arg })\n },\n [isDemoMode, fetcher, demoFixture, demoDelay, key, mutate]\n )\n\n return useSWRMutation(key, demoAwareFetcher, mutationOptions)\n}\n"]}