@demokit-ai/swr 0.3.0 → 0.4.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 CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  DemoSWRProvider: () => DemoSWRProvider,
34
34
  createDemoFetcher: () => createDemoFetcher,
35
35
  createDemoMiddleware: () => createDemoMiddleware,
36
+ createRemoteSource: () => createRemoteSource,
36
37
  defaultFetcher: () => defaultFetcher,
37
38
  findMatchingFixture: () => findMatchingFixture,
38
39
  matchQueryKey: () => import_core.matchQueryKey,
@@ -268,6 +269,16 @@ function DemoSWRProvider({
268
269
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DemoSWRContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_swr.SWRConfig, { value: config, children }) });
269
270
  }
270
271
 
272
+ // src/config.ts
273
+ function createRemoteSource(config) {
274
+ return {
275
+ timeout: 1e4,
276
+ retry: true,
277
+ maxRetries: 3,
278
+ ...config
279
+ };
280
+ }
281
+
271
282
  // src/hooks.ts
272
283
  var import_react3 = require("react");
273
284
  var import_mutation = __toESM(require("swr/mutation"), 1);
@@ -329,6 +340,7 @@ function useDemoSWRMutation(key, options) {
329
340
  DemoSWRProvider,
330
341
  createDemoFetcher,
331
342
  createDemoMiddleware,
343
+ createRemoteSource,
332
344
  defaultFetcher,
333
345
  findMatchingFixture,
334
346
  matchQueryKey,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.ts","../src/matcher.ts","../src/fetcher.ts","../src/middleware.ts","../src/hooks.ts"],"sourcesContent":["/**\n * @demokit-ai/swr\n *\n * SWR adapter for DemoKit.\n * Mock fetches and mutations when demo mode is enabled using SWR's middleware pattern.\n *\n * @example\n * import { DemoSWRProvider } from '@demokit-ai/swr'\n *\n * // Define fixtures\n * const fixtures = {\n * '/api/users': [\n * { id: '1', name: 'Demo User' },\n * { id: '2', name: 'Another User' },\n * ],\n * '[\"/api/users\", \":id\"]': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * '[\"/api/projects\", { status: \":status\" }]': ({ params }) => [\n * { id: '1', name: 'Project', status: params.status },\n * ],\n * }\n *\n * // Wrap your app\n * <DemoSWRProvider fixtures={fixtures} enabled={true}>\n * <App />\n * </DemoSWRProvider>\n *\n * @packageDocumentation\n */\n\n// Provider\nexport { DemoSWRProvider } from './provider'\n\n// Hooks\nexport { useDemoSWR, useIsDemoSWRMode, useDemoSWRMutation } from './hooks'\nexport type { UseDemoSWRMutationOptions } from './hooks'\n\n// Fetcher utilities\nexport { createDemoFetcher, defaultFetcher } from './fetcher'\nexport type { CreateDemoFetcherOptions } from './fetcher'\n\n// Middleware\nexport { createDemoMiddleware } from './middleware'\nexport type { CreateDemoMiddlewareOptions } from './middleware'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n normalizeKey,\n normalizeFixtureMap,\n parsePatternString,\n matchQueryKey,\n} from './matcher'\n\n// Types\nexport type {\n SWRFixtureContext,\n SWRFixtureHandler,\n SWRFixtureMap,\n SWRFixtureMapObject,\n SWRMutationFixtureContext,\n SWRMutationFixtureHandler,\n SWRMutationFixtureMap,\n SWRMutationFixtureMapObject,\n DemoSWRProviderConfig,\n DemoSWRProviderProps,\n DemoSWRState,\n} from './types'\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 { 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 { 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAAA,gBAA6C;AAC7C,iBAA0B;;;ACD1B,mBAA8B;AAOvB,IAAM,qBAAiB,4BAAwC,MAAS;AAE/E,eAAe,cAAc;;;ACX7B,kBAA2D;AAYpD,SAAS,aAAa,KAAmC;AAC9D,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,CAAC,GAAG;AAAA,EACb;AAEA,SAAO,IAAI,IAAI,CAAC,YAAY;AAC1B,QAAI,YAAY,QAAQ,YAAY,QAAW;AAC7C,aAAO;AAAA,IACT;AACA,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAWO,SAAS,mBAAmB,SAA2B;AAE5D,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,SAAO,CAAC,OAAO;AACjB;AAKO,SAAS,oBAAoB,UAA8D;AAChG,MAAI,oBAAoB,KAAK;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,oBAAI,IAAiC;AACjD,aAAW,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACzD,QAAI,IAAI,mBAAmB,OAAO,GAAG,OAAO;AAAA,EAC9C;AACA,SAAO;AACT;AASO,SAAS,oBACd,UACA,KAC0F;AAC1F,QAAM,gBAAgB,aAAa,GAAG;AACtC,QAAM,aAAS,yCAA4B,UAAU,aAAa;AAElE,MAAI,QAAQ;AACV,UAAM,CAAC,EAAE,SAAS,WAAW,IAAI;AACjC,WAAO,CAAC,SAAS,EAAE,QAAQ,YAAY,QAAQ,cAAc,CAAC;AAAA,EAChE;AAEA,SAAO;AACT;;;AClCO,SAAS,kBAAkB,SAAmC;AACnE,QAAM,EAAE,UAAU,WAAW,QAAQ,GAAG,gBAAgB,IAAI;AAE5D,SAAO,eAAe,YAA6B,KAAyC;AAE1F,QAAI,CAAC,UAAU,GAAG;AAChB,UAAI,iBAAiB;AACnB,eAAO,gBAAuB,GAAG;AAAA,MACnC;AACA,YAAM,IAAI;AAAA,QACR,8EACU,KAAK,UAAU,GAAG,CAAC;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,QAAQ,oBAAoB,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,iBAAiB;AACnB,eAAO,gBAAuB,GAAG;AAAA,MACnC;AACA,YAAM,IAAI,MAAM,2CAA2C,KAAK,UAAU,GAAG,CAAC,EAAE;AAAA,IAClF;AAEA,UAAM,CAAC,SAAS,EAAE,QAAQ,cAAc,CAAC,IAAI;AAG7C,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAGA,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,SAAS,MAAM,OAAO;AAAA,IACjC;AAGA,QAAI,OAAO,YAAY,YAAY;AACjC,aAAO,QAAQ,OAAO;AAAA,IACxB;AAGA,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,eAAgC,KAAyC;AAC7F,QAAM,MAAM,OAAO,QAAQ,WAAW,MAAM,OAAO,IAAI,CAAC,CAAC;AACzD,QAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,QAAQ,IAAI,MAAM,4CAA4C;AACpE,UAAM;AAAA,EACR;AAEA,SAAO,SAAS,KAAK;AACvB;;;AC/DO,SAAS,qBAAqB,SAAkD;AACrF,QAAM,EAAE,UAAU,WAAW,QAAQ,EAAE,IAAI;AAG3C,QAAM,aAAyB,CAAC,eAAe,CAAC,KAAK,SAAS,WAAW;AAEvE,UAAM,kBACJ,YAAY,OACR,OACA,UAAU,SAAqC;AAE7C,YAAM,cAAc,OAAO,QAAQ,aAAa,IAAI,IAAI;AAGxD,UAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,eAAO,QAAQ,GAAG,IAAI;AAAA,MACxB;AAGA,UAAI,CAAC,UAAU,GAAG;AAChB,eAAO,QAAQ,GAAG,IAAI;AAAA,MACxB;AAGA,YAAM,aACJ,OAAO,gBAAgB,WAAW,cAAe;AAGnD,YAAM,QAAQ,oBAAoB,UAAU,UAAU;AAEtD,UAAI,CAAC,OAAO;AAEV,eAAO,QAAQ,GAAG,IAAI;AAAA,MACxB;AAEA,YAAM,CAAC,SAAS,EAAE,QAAQ,cAAc,CAAC,IAAI;AAG7C,UAAI,QAAQ,GAAG;AACb,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,MAC3D;AAGA,YAAM,UAA6B;AAAA,QACjC,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA,OAAO,EAAE,SAAS,MAAM,OAAO;AAAA,MACjC;AAGA,UAAI,OAAO,YAAY,YAAY;AACjC,eAAO,QAAQ,OAAO;AAAA,MACxB;AAGA,aAAO;AAAA,IACT;AAEN,WAAO,WAAW,KAAK,iBAAiB,MAAM;AAAA,EAChD;AAEA,SAAO;AACT;;;AJ0DM;AAhHC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,WAAW,oBAAI,IAAI;AAAA,EACnB,YAAY,oBAAI,IAAI;AAAA,EACpB,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW,CAAC;AAAA,EACZ,YAAY,CAAC;AACf,GAAyB;AAEvB,QAAM,kBAAc,sBAAsB,oBAAoB,QAAQ,CAAC;AACvE,QAAM,0BAAsB;AAAA,IAC1B,qBAAqB,MAAM,YAAY,IAAI,IAAI,OAAO,QAAQ,SAAS,CAAC;AAAA,EAC1E;AAEA,QAAM,aAAa;AAGnB,QAAM,qBAAiB;AAAA,IACrB,MACE,qBAAqB;AAAA,MACnB,UAAU,YAAY;AAAA,MACtB,WAAW,MAAM;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,IACH,CAAC,YAAY,KAAK;AAAA,EACpB;AAGA,QAAM,kBAAc;AAAA,IAClB,MACE,kBAAkB;AAAA,MAChB,UAAU,YAAY;AAAA,MACtB,WAAW,MAAM;AAAA,MACjB;AAAA,MACA,iBAAiB;AAAA,IACnB,CAAC;AAAA,IACH,CAAC,YAAY,KAAK;AAAA,EACpB;AAGA,QAAM,uBAAmB,uBAAQ,MAAM;AACrC,QAAI,CAAC,WAAY,QAAO,UAAU,YAAY,CAAC;AAE/C,UAAM,iBAA0C,CAAC;AAGjD,eAAW,CAAC,SAAS,OAAO,KAAK,YAAY,SAAS;AACpD,UAAI,OAAO,YAAY,YAAY;AAEjC,cAAM,MAAM,QAAQ,WAAW,IAAI,OAAO,QAAQ,CAAC,CAAC,IAAI,KAAK,UAAU,OAAO;AAC9E,uBAAe,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAI,UAAU,YAAY,CAAC;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,YAAY,UAAU,UAAU,QAAQ,CAAC;AAG7C,QAAM,aAAS;AAAA,IACb,OAAO;AAAA,MACL,GAAG;AAAA,MACH,KAAK,CAAC,GAAI,UAAU,OAAO,CAAC,GAAI,cAAc;AAAA,MAC9C,UAAU;AAAA;AAAA,MAEV,GAAI,aACA;AAAA,QACE,mBAAmB;AAAA,QACnB,uBAAuB;AAAA,QACvB,oBAAoB;AAAA,MACtB,IACA,CAAC;AAAA,IACP;AAAA,IACA,CAAC,WAAW,gBAAgB,kBAAkB,UAAU;AAAA,EAC1D;AAGA,QAAM,iBAAa,2BAAY,MAAM,aAAa,CAAC,WAAW,CAAC;AAC/D,QAAM,oBAAgB,2BAAY,MAAM,gBAAgB,CAAC,cAAc,CAAC;AAExE,QAAM,mBAAe;AAAA,IACnB,OAAO;AAAA,MACL;AAAA,MAEA,YAAY,CAAC,SAAmB,YAA+B;AAC7D,oBAAY,QAAQ,IAAI,SAAS,OAAO;AAAA,MAC1C;AAAA,MAEA,eAAe,CAAC,YAAsB;AACpC,oBAAY,QAAQ,OAAO,OAAO;AAAA,MACpC;AAAA,MAEA,oBAAoB,CAAC,MAAc,YAAuC;AACxE,4BAAoB,QAAQ,IAAI,MAAM,OAAO;AAAA,MAC/C;AAAA,MAEA,uBAAuB,CAAC,SAAiB;AACvC,4BAAoB,QAAQ,OAAO,IAAI;AAAA,MACzC;AAAA,MAEA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,YAAY,YAAY,aAAa;AAAA,EACxC;AAEA,SACE,4CAAC,eAAe,UAAf,EAAwB,OAAO,cAC9B,sDAAC,wBAAU,OAAO,QAAS,UAAS,GACtC;AAEJ;;;AKhLA,IAAAC,gBAAwC;AACxC,sBAAwF;AACxF,IAAAC,cAA6B;AAwBtB,SAAS,aAA2B;AACzC,QAAM,cAAU,0BAAW,cAAc;AAEzC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;AAaO,SAAS,mBAA4B;AAC1C,SAAO,WAAW,EAAE;AACtB;AAiDO,SAAS,mBACd,KACA,SACkD;AAClD,QAAM,EAAE,SAAS,aAAa,YAAY,GAAG,GAAG,gBAAgB,IAAI;AAEpE,QAAM,EAAE,OAAO,QAAI,0BAAa;AAGhC,MAAI,aAAa;AACjB,MAAI;AACF,UAAM,YAAY,WAAW;AAC7B,iBAAa,UAAU;AAAA,EACzB,QAAQ;AAAA,EAER;AAGA,QAAM,uBAAmB;AAAA,IACvB,OAAO,aAAqB,EAAE,IAAI,MAAqC;AAErE,UAAI,CAAC,YAAY;AACf,eAAO,QAAQ,aAAa,EAAE,IAAI,CAAC;AAAA,MACrC;AAGA,UAAI,YAAY,GAAG;AACjB,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS,CAAC;AAAA,MAC/D;AAGA,UAAI,gBAAgB,QAAW;AAC7B,cAAM,UAAkD;AAAA,UACtD,KAAK;AAAA,UACL;AAAA,UACA,aAAa;AAAA;AAAA,UACb;AAAA,QACF;AAEA,YAAI,OAAO,gBAAgB,YAAY;AACrC,gBAAM,YAAY;AAGlB,iBAAO,UAAU,OAAO;AAAA,QAC1B;AACA,eAAO;AAAA,MACT;AAGA,cAAQ;AAAA,QACN,gDAAgD,GAAG;AAAA,MACrD;AACA,aAAO,QAAQ,aAAa,EAAE,IAAI,CAAC;AAAA,IACrC;AAAA,IACA,CAAC,YAAY,SAAS,aAAa,WAAW,KAAK,MAAM;AAAA,EAC3D;AAEA,aAAO,gBAAAC,SAAe,KAAK,kBAAkB,eAAe;AAC9D;","names":["import_react","import_react","import_swr","useSWRMutation"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.ts","../src/matcher.ts","../src/fetcher.ts","../src/middleware.ts","../src/config.ts","../src/hooks.ts"],"sourcesContent":["/**\n * @demokit-ai/swr\n *\n * SWR adapter for DemoKit.\n * Mock fetches and mutations when demo mode is enabled using SWR's middleware pattern.\n *\n * @example\n * import { DemoSWRProvider } from '@demokit-ai/swr'\n *\n * // Define fixtures\n * const fixtures = {\n * '/api/users': [\n * { id: '1', name: 'Demo User' },\n * { id: '2', name: 'Another User' },\n * ],\n * '[\"/api/users\", \":id\"]': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * '[\"/api/projects\", { status: \":status\" }]': ({ params }) => [\n * { id: '1', name: 'Project', status: params.status },\n * ],\n * }\n *\n * // Wrap your app\n * <DemoSWRProvider fixtures={fixtures} enabled={true}>\n * <App />\n * </DemoSWRProvider>\n *\n * @packageDocumentation\n */\n\n// Provider\nexport { DemoSWRProvider } from './provider'\n\n// Config helpers\nexport { createRemoteSource } from './config'\n\n// Hooks\nexport { useDemoSWR, useIsDemoSWRMode, useDemoSWRMutation } from './hooks'\nexport type { UseDemoSWRMutationOptions } from './hooks'\n\n// Fetcher utilities\nexport { createDemoFetcher, defaultFetcher } from './fetcher'\nexport type { CreateDemoFetcherOptions } from './fetcher'\n\n// Middleware\nexport { createDemoMiddleware } from './middleware'\nexport type { CreateDemoMiddlewareOptions } from './middleware'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n normalizeKey,\n normalizeFixtureMap,\n parsePatternString,\n matchQueryKey,\n} from './matcher'\n\n// Types\nexport type {\n SWRFixtureContext,\n SWRFixtureHandler,\n SWRFixtureMap,\n SWRFixtureMapObject,\n SWRMutationFixtureContext,\n SWRMutationFixtureHandler,\n SWRMutationFixtureMap,\n SWRMutationFixtureMapObject,\n DemoSWRProviderConfig,\n DemoSWRProviderProps,\n DemoSWRState,\n RemoteSourceConfig,\n} from './types'\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 { 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","import type { RemoteSourceConfig } from './types'\n\n/**\n * Create a remote source configuration for fetching fixtures from DemoKit Cloud\n *\n * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.\n *\n * @example\n * ```typescript\n * // lib/demokit-config.ts\n * import { createRemoteSource } from '@demokit-ai/swr'\n *\n * // .env:\n * // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // VITE_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,\n * apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,\n * })\n *\n * // Then in your app:\n * import { demokitSource } from './lib/demokit-config'\n *\n * <DemoSWRProvider source={demokitSource}>\n * <SWRConfig>\n * <App />\n * </SWRConfig>\n * </DemoSWRProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\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"],"mappings":"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","names":["import_react","import_react","import_swr","useSWRMutation"]}
package/dist/index.d.cts CHANGED
@@ -149,6 +149,38 @@ interface DemoSWRState {
149
149
  */
150
150
  getMiddleware: () => Middleware;
151
151
  }
152
+ /**
153
+ * Configuration for remote fixture source (DemoKit Cloud)
154
+ */
155
+ interface RemoteSourceConfig {
156
+ /**
157
+ * DemoKit Cloud API URL (versioned base URL)
158
+ * The SDK will append `/fixtures` to this URL.
159
+ * @example 'https://demokit-cloud.kasava.dev/api'
160
+ * @default 'https://api.demokit.cloud/api'
161
+ */
162
+ apiUrl: string;
163
+ /**
164
+ * DemoKit Cloud API key
165
+ * Format: dk_live_xxx
166
+ */
167
+ apiKey: string;
168
+ /**
169
+ * Request timeout in milliseconds
170
+ * @default 10000
171
+ */
172
+ timeout?: number;
173
+ /**
174
+ * Whether to retry failed requests
175
+ * @default true
176
+ */
177
+ retry?: boolean;
178
+ /**
179
+ * Maximum number of retries
180
+ * @default 3
181
+ */
182
+ maxRetries?: number;
183
+ }
152
184
 
153
185
  /**
154
186
  * Provider component for DemoKit SWR integration
@@ -197,6 +229,37 @@ interface DemoSWRState {
197
229
  */
198
230
  declare function DemoSWRProvider({ children, fixtures, mutations, enabled, delay, fallback, swrConfig, }: DemoSWRProviderProps): react_jsx_runtime.JSX.Element;
199
231
 
232
+ /**
233
+ * Create a remote source configuration for fetching fixtures from DemoKit Cloud
234
+ *
235
+ * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * // lib/demokit-config.ts
240
+ * import { createRemoteSource } from '@demokit-ai/swr'
241
+ *
242
+ * // .env:
243
+ * // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
244
+ * // VITE_DEMOKIT_API_KEY=dk_live_xxxx
245
+ *
246
+ * export const demokitSource = createRemoteSource({
247
+ * apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,
248
+ * apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,
249
+ * })
250
+ *
251
+ * // Then in your app:
252
+ * import { demokitSource } from './lib/demokit-config'
253
+ *
254
+ * <DemoSWRProvider source={demokitSource}>
255
+ * <SWRConfig>
256
+ * <App />
257
+ * </SWRConfig>
258
+ * </DemoSWRProvider>
259
+ * ```
260
+ */
261
+ declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
262
+
200
263
  /**
201
264
  * Hook to access DemoSWR state and controls
202
265
  *
@@ -412,4 +475,4 @@ declare function findMatchingFixture(fixtures: SWRFixtureMap, key: string | unkn
412
475
  normalizedKey: QueryKey;
413
476
  }] | null;
414
477
 
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 };
478
+ export { type CreateDemoFetcherOptions, type CreateDemoMiddlewareOptions, DemoSWRProvider, type DemoSWRProviderConfig, type DemoSWRProviderProps, type DemoSWRState, type RemoteSourceConfig, type SWRFixtureContext, type SWRFixtureHandler, type SWRFixtureMap, type SWRFixtureMapObject, type SWRMutationFixtureContext, type SWRMutationFixtureHandler, type SWRMutationFixtureMap, type SWRMutationFixtureMapObject, type UseDemoSWRMutationOptions, createDemoFetcher, createDemoMiddleware, createRemoteSource, defaultFetcher, findMatchingFixture, normalizeFixtureMap, normalizeKey, parsePatternString, useDemoSWR, useDemoSWRMutation, useIsDemoSWRMode };
package/dist/index.d.ts CHANGED
@@ -149,6 +149,38 @@ interface DemoSWRState {
149
149
  */
150
150
  getMiddleware: () => Middleware;
151
151
  }
152
+ /**
153
+ * Configuration for remote fixture source (DemoKit Cloud)
154
+ */
155
+ interface RemoteSourceConfig {
156
+ /**
157
+ * DemoKit Cloud API URL (versioned base URL)
158
+ * The SDK will append `/fixtures` to this URL.
159
+ * @example 'https://demokit-cloud.kasava.dev/api'
160
+ * @default 'https://api.demokit.cloud/api'
161
+ */
162
+ apiUrl: string;
163
+ /**
164
+ * DemoKit Cloud API key
165
+ * Format: dk_live_xxx
166
+ */
167
+ apiKey: string;
168
+ /**
169
+ * Request timeout in milliseconds
170
+ * @default 10000
171
+ */
172
+ timeout?: number;
173
+ /**
174
+ * Whether to retry failed requests
175
+ * @default true
176
+ */
177
+ retry?: boolean;
178
+ /**
179
+ * Maximum number of retries
180
+ * @default 3
181
+ */
182
+ maxRetries?: number;
183
+ }
152
184
 
153
185
  /**
154
186
  * Provider component for DemoKit SWR integration
@@ -197,6 +229,37 @@ interface DemoSWRState {
197
229
  */
198
230
  declare function DemoSWRProvider({ children, fixtures, mutations, enabled, delay, fallback, swrConfig, }: DemoSWRProviderProps): react_jsx_runtime.JSX.Element;
199
231
 
232
+ /**
233
+ * Create a remote source configuration for fetching fixtures from DemoKit Cloud
234
+ *
235
+ * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * // lib/demokit-config.ts
240
+ * import { createRemoteSource } from '@demokit-ai/swr'
241
+ *
242
+ * // .env:
243
+ * // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
244
+ * // VITE_DEMOKIT_API_KEY=dk_live_xxxx
245
+ *
246
+ * export const demokitSource = createRemoteSource({
247
+ * apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,
248
+ * apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,
249
+ * })
250
+ *
251
+ * // Then in your app:
252
+ * import { demokitSource } from './lib/demokit-config'
253
+ *
254
+ * <DemoSWRProvider source={demokitSource}>
255
+ * <SWRConfig>
256
+ * <App />
257
+ * </SWRConfig>
258
+ * </DemoSWRProvider>
259
+ * ```
260
+ */
261
+ declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
262
+
200
263
  /**
201
264
  * Hook to access DemoSWR state and controls
202
265
  *
@@ -412,4 +475,4 @@ declare function findMatchingFixture(fixtures: SWRFixtureMap, key: string | unkn
412
475
  normalizedKey: QueryKey;
413
476
  }] | null;
414
477
 
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 };
478
+ export { type CreateDemoFetcherOptions, type CreateDemoMiddlewareOptions, DemoSWRProvider, type DemoSWRProviderConfig, type DemoSWRProviderProps, type DemoSWRState, type RemoteSourceConfig, type SWRFixtureContext, type SWRFixtureHandler, type SWRFixtureMap, type SWRFixtureMapObject, type SWRMutationFixtureContext, type SWRMutationFixtureHandler, type SWRMutationFixtureMap, type SWRMutationFixtureMapObject, type UseDemoSWRMutationOptions, createDemoFetcher, createDemoMiddleware, createRemoteSource, defaultFetcher, findMatchingFixture, normalizeFixtureMap, normalizeKey, parsePatternString, useDemoSWR, useDemoSWRMutation, useIsDemoSWRMode };
package/dist/index.js CHANGED
@@ -221,6 +221,16 @@ function DemoSWRProvider({
221
221
  return /* @__PURE__ */ jsx(DemoSWRContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(SWRConfig, { value: config, children }) });
222
222
  }
223
223
 
224
+ // src/config.ts
225
+ function createRemoteSource(config) {
226
+ return {
227
+ timeout: 1e4,
228
+ retry: true,
229
+ maxRetries: 3,
230
+ ...config
231
+ };
232
+ }
233
+
224
234
  // src/hooks.ts
225
235
  import { useContext, useCallback as useCallback2 } from "react";
226
236
  import useSWRMutation from "swr/mutation";
@@ -281,6 +291,7 @@ export {
281
291
  DemoSWRProvider,
282
292
  createDemoFetcher,
283
293
  createDemoMiddleware,
294
+ createRemoteSource,
284
295
  defaultFetcher,
285
296
  findMatchingFixture,
286
297
  matchQueryKey,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/matcher.ts","../src/fetcher.ts","../src/middleware.ts","../src/hooks.ts"],"sourcesContent":["'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 { 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 { 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"],"mappings":"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","names":["useCallback","useCallback"]}
1
+ {"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/matcher.ts","../src/fetcher.ts","../src/middleware.ts","../src/config.ts","../src/hooks.ts"],"sourcesContent":["'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 { 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","import type { RemoteSourceConfig } from './types'\n\n/**\n * Create a remote source configuration for fetching fixtures from DemoKit Cloud\n *\n * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.\n *\n * @example\n * ```typescript\n * // lib/demokit-config.ts\n * import { createRemoteSource } from '@demokit-ai/swr'\n *\n * // .env:\n * // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // VITE_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,\n * apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,\n * })\n *\n * // Then in your app:\n * import { demokitSource } from './lib/demokit-config'\n *\n * <DemoSWRProvider source={demokitSource}>\n * <SWRConfig>\n * <App />\n * </SWRConfig>\n * </DemoSWRProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\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"],"mappings":"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","names":["useCallback","useCallback"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@demokit-ai/swr",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "SWR integration for DemoKit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -22,10 +22,11 @@
22
22
  "dist"
23
23
  ],
24
24
  "dependencies": {
25
- "@demokit-ai/core": "0.3.0",
26
- "@demokit-ai/react": "0.3.0"
25
+ "@demokit-ai/core": "0.4.2",
26
+ "@demokit-ai/react": "0.4.1"
27
27
  },
28
28
  "devDependencies": {
29
+ "@types/node": "^22.0.0",
29
30
  "@types/react": "^19.0.0",
30
31
  "swr": "^2.2.5",
31
32
  "tsup": "^8.3.5",