@demokit-ai/tanstack-query 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 +12 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
createDemoQueryClient: () => createDemoQueryClient,
|
|
25
25
|
createDemoQueryFn: () => createDemoQueryFn,
|
|
26
26
|
createMutationOptions: () => createMutationOptions,
|
|
27
|
+
createRemoteSource: () => createRemoteSource,
|
|
27
28
|
findMatchingFixture: () => findMatchingFixture,
|
|
28
29
|
matchQueryKey: () => import_core.matchQueryKey,
|
|
29
30
|
normalizeFixtureMap: () => normalizeFixtureMap,
|
|
@@ -313,6 +314,16 @@ function DemoQueryProvider({
|
|
|
313
314
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_query2.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DemoQueryProviderInner, { ...config, children }) });
|
|
314
315
|
}
|
|
315
316
|
|
|
317
|
+
// src/config.ts
|
|
318
|
+
function createRemoteSource(config) {
|
|
319
|
+
return {
|
|
320
|
+
timeout: 1e4,
|
|
321
|
+
retry: true,
|
|
322
|
+
maxRetries: 3,
|
|
323
|
+
...config
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
316
327
|
// src/hooks.ts
|
|
317
328
|
var import_react3 = require("react");
|
|
318
329
|
function useDemoQuery() {
|
|
@@ -385,6 +396,7 @@ function createMutationOptions(config) {
|
|
|
385
396
|
createDemoQueryClient,
|
|
386
397
|
createDemoQueryFn,
|
|
387
398
|
createMutationOptions,
|
|
399
|
+
createRemoteSource,
|
|
388
400
|
findMatchingFixture,
|
|
389
401
|
matchQueryKey,
|
|
390
402
|
normalizeFixtureMap,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.ts","../src/client.ts","../src/matcher.ts","../src/hooks.ts","../src/mutation.ts"],"sourcesContent":["/**\n * @demokit-ai/tanstack-query\n *\n * TanStack Query v5 adapter for DemoKit.\n * Mock queries and mutations when demo mode is enabled.\n *\n * @example\n * import { DemoQueryProvider } from '@demokit-ai/tanstack-query'\n *\n * // Define query fixtures\n * const queryFixtures = {\n * '[\"users\"]': [\n * { id: '1', name: 'Demo User' },\n * { id: '2', name: 'Another User' },\n * ],\n * '[\"users\", \":id\"]': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * '[\"projects\", { status: \":status\" }]': ({ params }) => [\n * { id: '1', name: 'Project', status: params.status },\n * ],\n * }\n *\n * // Wrap your app\n * <DemoQueryProvider queries={queryFixtures} enabled={true}>\n * <App />\n * </DemoQueryProvider>\n *\n * @packageDocumentation\n */\n\n// Provider\nexport { DemoQueryProvider } from './provider'\n\n// Hooks\nexport { useDemoQuery, useIsDemoQueryMode } from './hooks'\nexport { useDemoMutation, createMutationOptions } from './mutation'\nexport type { UseDemoMutationOptions, DemoMutationConfig } from './mutation'\n\n// Client utilities\nexport { createDemoQueryClient, createDemoQueryFn, type DemoQueryClient } from './client'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n normalizeQueryKey,\n normalizeFixtureMap,\n parsePatternString,\n matchQueryKey,\n} from './matcher'\n\n// Types\nexport type {\n QueryFixtureContext,\n QueryFixtureHandler,\n QueryFixtureMap,\n QueryFixtureMapObject,\n MutationFixtureContext,\n MutationFixtureHandler,\n MutationFixtureMap,\n MutationFixtureMapObject,\n DemoQueryProviderConfig,\n DemoQueryProviderProps,\n DemoQueryState,\n} from './types'\n","'use client'\n\nimport { useMemo, useRef, useEffect } from 'react'\nimport { QueryClientProvider, useQueryClient } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport { DemoQueryContext } from './context'\nimport { createDemoQueryFn, createDemoQueryClient } from './client'\nimport { normalizeFixtureMap } from './matcher'\nimport type {\n DemoQueryProviderProps,\n QueryFixtureHandler,\n QueryFixtureMap,\n MutationFixtureHandler,\n MutationFixtureMap,\n DemoQueryState,\n} from './types'\n\n/**\n * Internal provider component that wraps existing QueryClient\n */\nfunction DemoQueryProviderInner({\n children,\n queries = new Map(),\n mutations = new Map(),\n enabled: enabledProp,\n delay = 0,\n staleTime = Infinity,\n}: Omit<DemoQueryProviderProps, 'client'>) {\n const queryClient = useQueryClient()\n const fixturesRef = useRef<QueryFixtureMap>(normalizeFixtureMap(queries))\n const mutationFixturesRef = useRef<MutationFixtureMap>(\n mutations instanceof Map ? mutations : new Map(Object.entries(mutations))\n )\n\n // Use enabled prop directly - demo mode is controlled by parent\n const isDemoMode = enabledProp ?? false\n\n // Create demo-aware query function\n const demoQueryFn = useMemo(\n () =>\n createDemoQueryFn({\n fixtures: fixturesRef.current,\n delay,\n isEnabled: () => isDemoMode,\n }),\n [delay, isDemoMode]\n )\n\n // Update query client defaults when demo mode changes\n useEffect(() => {\n if (isDemoMode) {\n queryClient.setDefaultOptions({\n ...queryClient.getDefaultOptions(),\n queries: {\n ...queryClient.getDefaultOptions().queries,\n queryFn: demoQueryFn,\n staleTime,\n retry: false,\n },\n })\n }\n }, [isDemoMode, demoQueryFn, queryClient, staleTime])\n\n // Create context value\n const contextValue = useMemo<DemoQueryState>(\n () => ({\n isDemoMode,\n\n setQueryFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixturesRef.current.set(pattern, handler)\n },\n\n removeQueryFixture: (pattern: QueryKey) => {\n fixturesRef.current.delete(pattern)\n },\n\n setMutationFixture: (name: string, handler: MutationFixtureHandler) => {\n mutationFixturesRef.current.set(name, handler)\n },\n\n removeMutationFixture: (name: string) => {\n mutationFixturesRef.current.delete(name)\n },\n\n invalidateAll: () => {\n queryClient.invalidateQueries()\n },\n\n resetCache: () => {\n queryClient.clear()\n },\n }),\n [isDemoMode, queryClient]\n )\n\n return (\n <DemoQueryContext.Provider value={contextValue}>\n {children}\n </DemoQueryContext.Provider>\n )\n}\n\n/**\n * Provider component for DemoKit TanStack Query integration\n *\n * Wraps QueryClientProvider and intercepts queries when demo mode is enabled.\n *\n * @example\n * // With new QueryClient\n * <DemoQueryProvider\n * queries={{\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * }}\n * >\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With existing QueryClient\n * const queryClient = new QueryClient()\n *\n * <DemoQueryProvider client={queryClient} queries={...}>\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With DemoKitProvider (auto-detects demo mode)\n * <DemoKitProvider fixtures={...}>\n * <DemoQueryProvider queries={...}>\n * <App />\n * </DemoQueryProvider>\n * </DemoKitProvider>\n */\nexport function DemoQueryProvider({\n children,\n client,\n ...config\n}: DemoQueryProviderProps) {\n // If no client provided, create one\n const { client: demoClient } = useMemo(() => {\n if (client) {\n return { client }\n }\n return createDemoQueryClient(config)\n }, [client, config.enabled])\n\n const queryClient = client ?? demoClient\n\n return (\n <QueryClientProvider client={queryClient}>\n <DemoQueryProviderInner {...config}>{children}</DemoQueryProviderInner>\n </QueryClientProvider>\n )\n}\n","'use client'\n\nimport { createContext } from 'react'\nimport type { DemoQueryState } from './types'\n\n/**\n * Context for DemoQuery state\n * @internal\n */\nexport const DemoQueryContext = createContext<DemoQueryState | undefined>(undefined)\n\nDemoQueryContext.displayName = 'DemoQueryContext'\n","import { QueryClient, type QueryClientConfig } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryFixtureMap, DemoQueryProviderConfig, QueryFixtureHandler } from './types'\nimport { findMatchingFixture, normalizeFixtureMap } from './matcher'\n\n/**\n * Configuration for creating a demo-aware QueryClient\n */\nexport interface DemoQueryClientConfig extends DemoQueryProviderConfig {\n /**\n * Base QueryClient config to extend\n */\n queryClientConfig?: QueryClientConfig\n}\n\n/**\n * Create a demo-aware query function\n *\n * This wraps the default query function to intercept demo queries\n * and return fixture data when demo mode is enabled.\n */\nexport function createDemoQueryFn(config: {\n fixtures: QueryFixtureMap\n delay?: number\n fallbackQueryFn?: DemoQueryProviderConfig['fallbackQueryFn']\n isEnabled: () => boolean\n}) {\n const { fixtures, delay = 0, fallbackQueryFn, isEnabled } = config\n\n return async function demoQueryFn({\n queryKey,\n signal,\n }: {\n queryKey: readonly unknown[]\n signal?: AbortSignal\n }) {\n // If demo mode is not enabled, use fallback\n if (!isEnabled()) {\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fallback query function provided and demo mode is disabled. ` +\n `Query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, queryKey as unknown[])\n\n if (!match) {\n // No fixture found, try fallback\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fixture found for query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n const [handler, { params }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler({\n queryKey: queryKey as unknown[],\n params,\n match: { matched: true, params },\n signal,\n })\n }\n\n // Return static value\n return handler\n }\n}\n\n/**\n * Create a demo-aware QueryClient\n *\n * This creates a QueryClient configured to intercept queries when demo mode\n * is enabled and return fixture data instead of making real API calls.\n *\n * @example\n * const { client, enable, disable, isEnabled } = createDemoQueryClient({\n * queries: {\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * },\n * delay: 100, // Simulate 100ms latency\n * })\n *\n * // Use with QueryClientProvider\n * <QueryClientProvider client={client}>\n * <App />\n * </QueryClientProvider>\n */\nexport function createDemoQueryClient(config: DemoQueryClientConfig = {}) {\n const {\n queries = new Map(),\n delay = 0,\n staleTime = Infinity,\n fallbackQueryFn,\n queryClientConfig = {},\n prepopulateCache = false,\n } = config\n\n let enabled = config.enabled ?? false\n const fixtures = normalizeFixtureMap(queries)\n\n const isEnabled = () => enabled\n\n const demoQueryFn = createDemoQueryFn({\n fixtures,\n delay,\n fallbackQueryFn,\n isEnabled,\n })\n\n const client = new QueryClient({\n ...queryClientConfig,\n defaultOptions: {\n ...queryClientConfig.defaultOptions,\n queries: {\n ...queryClientConfig.defaultOptions?.queries,\n queryFn: demoQueryFn,\n staleTime: enabled ? staleTime : queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: enabled ? false : queryClientConfig.defaultOptions?.queries?.retry,\n },\n },\n })\n\n // Pre-populate cache if configured\n const prepopulate = () => {\n if (!prepopulateCache || !enabled) return\n\n for (const [pattern, handler] of fixtures) {\n // Only pre-populate static values (not functions)\n if (typeof handler !== 'function') {\n // Use pattern as query key for static fixtures\n client.setQueryData(pattern, handler)\n }\n }\n }\n\n return {\n /**\n * The QueryClient instance\n */\n client,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime,\n retry: false,\n },\n })\n prepopulate()\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime: queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: queryClientConfig.defaultOptions?.queries?.retry,\n },\n })\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled,\n\n /**\n * Get the fixture map\n */\n getFixtures: () => fixtures,\n\n /**\n * Add or update a fixture\n */\n setFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixtures.set(pattern, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (pattern: QueryKey) => {\n fixtures.delete(pattern)\n },\n\n /**\n * Clear all query cache\n */\n clearCache: () => {\n client.clear()\n },\n\n /**\n * Invalidate all queries\n */\n invalidateAll: () => {\n client.invalidateQueries()\n },\n }\n}\n\nexport type DemoQueryClient = ReturnType<typeof createDemoQueryClient>\n","import { matchQueryKey, findMatchingQueryKeyPattern } from '@demokit-ai/core'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryKey as TanStackQueryKey } from '@tanstack/react-query'\nimport type { QueryFixtureHandler, QueryFixtureMap, QueryFixtureMapObject } from './types'\n\n/**\n * Convert TanStack Query key to DemoKit QueryKey\n * TanStack Query keys can contain any value, so we normalize them\n */\nexport function normalizeQueryKey(queryKey: TanStackQueryKey): QueryKey {\n return queryKey.map((element) => {\n if (element === null || element === undefined) {\n return element\n }\n if (typeof element === 'object') {\n // Keep objects as-is for matching\n return element as Record<string, unknown>\n }\n // Primitives are kept as-is\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('[\"users\"]') // ['users']\n * parsePatternString('[\"users\", \":id\"]') // ['users', ':id']\n * parsePatternString('users') // ['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: QueryFixtureMapObject | QueryFixtureMap): QueryFixtureMap {\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const map = new Map<QueryKey, QueryFixtureHandler>()\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 a query key\n *\n * @param fixtures - Map of query key patterns to handlers\n * @param queryKey - The query key to match\n * @returns Tuple of [handler, match result] or null if no match\n */\nexport function findMatchingFixture(\n fixtures: QueryFixtureMap,\n queryKey: TanStackQueryKey\n): [QueryFixtureHandler, { params: Record<string, unknown> }] | null {\n const normalizedKey = normalizeQueryKey(queryKey)\n const result = findMatchingQueryKeyPattern(fixtures, normalizedKey)\n\n if (result) {\n const [, handler, matchResult] = result\n return [handler, { params: matchResult.params }]\n }\n\n return null\n}\n\n/**\n * Re-export the matchQueryKey function for direct use\n */\nexport { matchQueryKey }\n","'use client'\n\nimport { useContext } from 'react'\nimport { DemoQueryContext } from './context'\nimport type { DemoQueryState } from './types'\n\n/**\n * Hook to access DemoQuery state and controls\n *\n * @returns DemoQuery context value\n * @throws Error if used outside of DemoQueryProvider\n *\n * @example\n * function MyComponent() {\n * const { isDemoMode, setQueryFixture, invalidateAll } = useDemoQuery()\n *\n * // Dynamically add a fixture\n * const handleAddFixture = () => {\n * setQueryFixture(['users', 'custom'], { id: 'custom', name: 'Custom User' })\n * invalidateAll() // Trigger refetch\n * }\n *\n * return (\n * <button onClick={handleAddFixture}>Add Custom Fixture</button>\n * )\n * }\n */\nexport function useDemoQuery(): DemoQueryState {\n const context = useContext(DemoQueryContext)\n\n if (context === undefined) {\n throw new Error(\n 'useDemoQuery must be used within a DemoQueryProvider. ' +\n 'Make sure to wrap your app with <DemoQueryProvider>.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to check if demo mode is enabled\n * Shorthand for useDemoQuery().isDemoMode\n *\n * @example\n * function MyComponent() {\n * const isDemoMode = useIsDemoQueryMode()\n *\n * return isDemoMode ? <DemoBadge /> : null\n * }\n */\nexport function useIsDemoQueryMode(): boolean {\n return useDemoQuery().isDemoMode\n}\n","'use client'\n\nimport { useMutation, useQueryClient, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport type { MutationFixtureContext, MutationFixtureHandler } from './types'\nimport { useDemoQuery } from './hooks'\n\n/**\n * Options for useDemoMutation hook\n */\nexport interface UseDemoMutationOptions<TData, TError, TVariables, TContext>\n extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {\n /**\n * The real mutation function to use when demo mode is disabled\n */\n mutationFn: (variables: TVariables) => Promise<TData>\n\n /**\n * Name used to look up the demo fixture\n * If not provided, uses mutationKey as string\n */\n demoName?: string\n\n /**\n * Demo fixture handler for this mutation\n * If provided, overrides the fixture from DemoQueryProvider\n */\n demoFixture?: MutationFixtureHandler<TData, TVariables>\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 * @example\n * const createUser = useDemoMutation({\n * mutationFn: async (data) => api.createUser(data),\n * demoName: 'createUser',\n * demoFixture: ({ variables, queryClient }) => {\n * // Create demo user\n * const newUser = { id: crypto.randomUUID(), ...variables }\n *\n * // Update the users query cache\n * queryClient.setQueryData(['users'], (old: User[] = []) => [...old, newUser])\n *\n * return newUser\n * },\n * onSuccess: (data) => {\n * console.log('Created user:', data)\n * },\n * })\n *\n * // Use like normal useMutation\n * createUser.mutate({ name: 'New User', email: 'user@example.com' })\n */\nexport function useDemoMutation<\n TData = unknown,\n TError = unknown,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseDemoMutationOptions<TData, TError, TVariables, TContext>\n): UseMutationResult<TData, TError, TVariables, TContext> {\n const { mutationFn, demoName, demoFixture, demoDelay = 0, ...mutationOptions } = options\n\n const queryClient = useQueryClient()\n\n // Try to get demo state - may not be in DemoQueryProvider context\n let isDemoMode = false\n try {\n const demoState = useDemoQuery()\n isDemoMode = demoState.isDemoMode\n } catch {\n // Not in DemoQueryProvider context, use real mutation\n }\n\n // Create the demo-aware mutation function\n const demoAwareMutationFn = useCallback(\n async (variables: TVariables): Promise<TData> => {\n // If not in demo mode, use real mutation\n if (!isDemoMode) {\n return mutationFn(variables)\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: MutationFixtureContext<TVariables> = {\n mutationKey: mutationOptions.mutationKey,\n variables,\n queryClient,\n }\n\n if (typeof demoFixture === 'function') {\n // Cast to the function type to help TypeScript understand\n const fixtureFn = demoFixture as (context: MutationFixtureContext<TVariables>) => 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] No mutation fixture found for \"${demoName || mutationOptions.mutationKey?.join('/') || 'unknown'}\". ` +\n 'Using real mutation function.'\n )\n return mutationFn(variables)\n },\n [isDemoMode, mutationFn, demoFixture, demoDelay, demoName, mutationOptions.mutationKey, queryClient]\n )\n\n return useMutation({\n ...mutationOptions,\n mutationFn: demoAwareMutationFn,\n })\n}\n\n/**\n * Create a set of demo mutations with fixtures\n *\n * @example\n * const mutations = createDemoMutations({\n * createUser: {\n * mutationFn: api.createUser,\n * fixture: ({ variables, queryClient }) => {\n * const newUser = { id: 'demo-1', ...variables }\n * queryClient.setQueryData(['users'], (old = []) => [...old, newUser])\n * return newUser\n * },\n * },\n * deleteUser: {\n * mutationFn: api.deleteUser,\n * fixture: ({ variables, queryClient }) => {\n * queryClient.setQueryData(['users'], (old: User[] = []) =>\n * old.filter(u => u.id !== variables.id)\n * )\n * return { success: true }\n * },\n * },\n * })\n *\n * // Use in components\n * const { createUser, deleteUser } = mutations\n */\nexport type DemoMutationConfig<TData, TVariables> = {\n mutationFn: (variables: TVariables) => Promise<TData>\n fixture: MutationFixtureHandler<TData, TVariables>\n delay?: number\n}\n\n/**\n * Helper to create mutation options with demo fixture\n */\nexport function createMutationOptions<TData, TVariables>(\n config: DemoMutationConfig<TData, TVariables>\n): Pick<UseDemoMutationOptions<TData, unknown, TVariables, unknown>, 'mutationFn' | 'demoFixture' | 'demoDelay'> {\n return {\n mutationFn: config.mutationFn,\n demoFixture: config.fixture,\n demoDelay: config.delay,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAAA,gBAA2C;AAC3C,IAAAC,sBAAoD;;;ACDpD,mBAA8B;AAOvB,IAAM,uBAAmB,4BAA0C,MAAS;AAEnF,iBAAiB,cAAc;;;ACX/B,yBAAoD;;;ACApD,kBAA2D;AASpD,SAAS,kBAAkB,UAAsC;AACtE,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,QAAI,YAAY,QAAQ,YAAY,QAAW;AAC7C,aAAO;AAAA,IACT;AACA,QAAI,OAAO,YAAY,UAAU;AAE/B,aAAO;AAAA,IACT;AAEA,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,UAAoE;AACtG,MAAI,oBAAoB,KAAK;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,oBAAI,IAAmC;AACnD,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,UACmE;AACnE,QAAM,gBAAgB,kBAAkB,QAAQ;AAChD,QAAM,aAAS,yCAA4B,UAAU,aAAa;AAElE,MAAI,QAAQ;AACV,UAAM,CAAC,EAAE,SAAS,WAAW,IAAI;AACjC,WAAO,CAAC,SAAS,EAAE,QAAQ,YAAY,OAAO,CAAC;AAAA,EACjD;AAEA,SAAO;AACT;;;AD5DO,SAAS,kBAAkB,QAK/B;AACD,QAAM,EAAE,UAAU,QAAQ,GAAG,iBAAiB,UAAU,IAAI;AAE5D,SAAO,eAAe,YAAY;AAAA,IAChC;AAAA,IACA;AAAA,EACF,GAGG;AAED,QAAI,CAAC,UAAU,GAAG;AAChB,UAAI,iBAAiB;AACnB,eAAO,gBAAgB,EAAE,UAAU,OAAO,CAAC;AAAA,MAC7C;AACA,YAAM,IAAI;AAAA,QACR,uFACgB,KAAK,UAAU,QAAQ,CAAC;AAAA,MAC1C;AAAA,IACF;AAGA,UAAM,QAAQ,oBAAoB,UAAU,QAAqB;AAEjE,QAAI,CAAC,OAAO;AAEV,UAAI,iBAAiB;AACnB,eAAO,gBAAgB,EAAE,UAAU,OAAO,CAAC;AAAA,MAC7C;AACA,YAAM,IAAI;AAAA,QACR,6CAA6C,KAAK,UAAU,QAAQ,CAAC;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI;AAG9B,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAGA,QAAI,OAAO,YAAY,YAAY;AACjC,aAAO,QAAQ;AAAA,QACb;AAAA,QACA;AAAA,QACA,OAAO,EAAE,SAAS,MAAM,OAAO;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAGA,WAAO;AAAA,EACT;AACF;AAsBO,SAAS,sBAAsB,SAAgC,CAAC,GAAG;AACxE,QAAM;AAAA,IACJ,UAAU,oBAAI,IAAI;AAAA,IAClB,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ;AAAA,IACA,oBAAoB,CAAC;AAAA,IACrB,mBAAmB;AAAA,EACrB,IAAI;AAEJ,MAAI,UAAU,OAAO,WAAW;AAChC,QAAM,WAAW,oBAAoB,OAAO;AAE5C,QAAM,YAAY,MAAM;AAExB,QAAM,cAAc,kBAAkB;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,SAAS,IAAI,+BAAY;AAAA,IAC7B,GAAG;AAAA,IACH,gBAAgB;AAAA,MACd,GAAG,kBAAkB;AAAA,MACrB,SAAS;AAAA,QACP,GAAG,kBAAkB,gBAAgB;AAAA,QACrC,SAAS;AAAA,QACT,WAAW,UAAU,YAAY,kBAAkB,gBAAgB,SAAS;AAAA,QAC5E,OAAO,UAAU,QAAQ,kBAAkB,gBAAgB,SAAS;AAAA,MACtE;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,cAAc,MAAM;AACxB,QAAI,CAAC,oBAAoB,CAAC,QAAS;AAEnC,eAAW,CAAC,SAAS,OAAO,KAAK,UAAU;AAEzC,UAAI,OAAO,YAAY,YAAY;AAEjC,eAAO,aAAa,SAAS,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL;AAAA;AAAA;AAAA;AAAA,IAKA,QAAQ,MAAM;AACZ,gBAAU;AACV,aAAO,kBAAkB;AAAA,QACvB,GAAG,OAAO,kBAAkB;AAAA,QAC5B,SAAS;AAAA,UACP,GAAG,OAAO,kBAAkB,EAAE;AAAA,UAC9B;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,kBAAY;AAAA,IACd;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS,MAAM;AACb,gBAAU;AACV,aAAO,kBAAkB;AAAA,QACvB,GAAG,OAAO,kBAAkB;AAAA,QAC5B,SAAS;AAAA,UACP,GAAG,OAAO,kBAAkB,EAAE;AAAA,UAC9B,WAAW,kBAAkB,gBAAgB,SAAS;AAAA,UACtD,OAAO,kBAAkB,gBAAgB,SAAS;AAAA,QACpD;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA,IAKA;AAAA;AAAA;AAAA;AAAA,IAKA,aAAa,MAAM;AAAA;AAAA;AAAA;AAAA,IAKnB,YAAY,CAAC,SAAmB,YAAiC;AAC/D,eAAS,IAAI,SAAS,OAAO;AAAA,IAC/B;AAAA;AAAA;AAAA;AAAA,IAKA,eAAe,CAAC,YAAsB;AACpC,eAAS,OAAO,OAAO;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA,IAKA,YAAY,MAAM;AAChB,aAAO,MAAM;AAAA,IACf;AAAA;AAAA;AAAA;AAAA,IAKA,eAAe,MAAM;AACnB,aAAO,kBAAkB;AAAA,IAC3B;AAAA,EACF;AACF;;;AFjII;AA5EJ,SAAS,uBAAuB;AAAA,EAC9B;AAAA,EACA,UAAU,oBAAI,IAAI;AAAA,EAClB,YAAY,oBAAI,IAAI;AAAA,EACpB,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,YAAY;AACd,GAA2C;AACzC,QAAM,kBAAc,oCAAe;AACnC,QAAM,kBAAc,sBAAwB,oBAAoB,OAAO,CAAC;AACxE,QAAM,0BAAsB;AAAA,IAC1B,qBAAqB,MAAM,YAAY,IAAI,IAAI,OAAO,QAAQ,SAAS,CAAC;AAAA,EAC1E;AAGA,QAAM,aAAa,eAAe;AAGlC,QAAM,kBAAc;AAAA,IAClB,MACE,kBAAkB;AAAA,MAChB,UAAU,YAAY;AAAA,MACtB;AAAA,MACA,WAAW,MAAM;AAAA,IACnB,CAAC;AAAA,IACH,CAAC,OAAO,UAAU;AAAA,EACpB;AAGA,+BAAU,MAAM;AACd,QAAI,YAAY;AACd,kBAAY,kBAAkB;AAAA,QAC5B,GAAG,YAAY,kBAAkB;AAAA,QACjC,SAAS;AAAA,UACP,GAAG,YAAY,kBAAkB,EAAE;AAAA,UACnC,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,YAAY,aAAa,aAAa,SAAS,CAAC;AAGpD,QAAM,mBAAe;AAAA,IACnB,OAAO;AAAA,MACL;AAAA,MAEA,iBAAiB,CAAC,SAAmB,YAAiC;AACpE,oBAAY,QAAQ,IAAI,SAAS,OAAO;AAAA,MAC1C;AAAA,MAEA,oBAAoB,CAAC,YAAsB;AACzC,oBAAY,QAAQ,OAAO,OAAO;AAAA,MACpC;AAAA,MAEA,oBAAoB,CAAC,MAAc,YAAoC;AACrE,4BAAoB,QAAQ,IAAI,MAAM,OAAO;AAAA,MAC/C;AAAA,MAEA,uBAAuB,CAAC,SAAiB;AACvC,4BAAoB,QAAQ,OAAO,IAAI;AAAA,MACzC;AAAA,MAEA,eAAe,MAAM;AACnB,oBAAY,kBAAkB;AAAA,MAChC;AAAA,MAEA,YAAY,MAAM;AAChB,oBAAY,MAAM;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAAC,YAAY,WAAW;AAAA,EAC1B;AAEA,SACE,4CAAC,iBAAiB,UAAjB,EAA0B,OAAO,cAC/B,UACH;AAEJ;AAkCO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA2B;AAEzB,QAAM,EAAE,QAAQ,WAAW,QAAI,uBAAQ,MAAM;AAC3C,QAAI,QAAQ;AACV,aAAO,EAAE,OAAO;AAAA,IAClB;AACA,WAAO,sBAAsB,MAAM;AAAA,EACrC,GAAG,CAAC,QAAQ,OAAO,OAAO,CAAC;AAE3B,QAAM,cAAc,UAAU;AAE9B,SACE,4CAAC,2CAAoB,QAAQ,aAC3B,sDAAC,0BAAwB,GAAG,QAAS,UAAS,GAChD;AAEJ;;;AIxJA,IAAAC,gBAA2B;AAyBpB,SAAS,eAA+B;AAC7C,QAAM,cAAU,0BAAW,gBAAgB;AAE3C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;AAaO,SAAS,qBAA8B;AAC5C,SAAO,aAAa,EAAE;AACxB;;;ACnDA,IAAAC,sBAA6F;AAC7F,IAAAC,gBAA4B;AAyDrB,SAAS,gBAMd,SACwD;AACxD,QAAM,EAAE,YAAY,UAAU,aAAa,YAAY,GAAG,GAAG,gBAAgB,IAAI;AAEjF,QAAM,kBAAc,oCAAe;AAGnC,MAAI,aAAa;AACjB,MAAI;AACF,UAAM,YAAY,aAAa;AAC/B,iBAAa,UAAU;AAAA,EACzB,QAAQ;AAAA,EAER;AAGA,QAAM,0BAAsB;AAAA,IAC1B,OAAO,cAA0C;AAE/C,UAAI,CAAC,YAAY;AACf,eAAO,WAAW,SAAS;AAAA,MAC7B;AAGA,UAAI,YAAY,GAAG;AACjB,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS,CAAC;AAAA,MAC/D;AAGA,UAAI,gBAAgB,QAAW;AAC7B,cAAM,UAA8C;AAAA,UAClD,aAAa,gBAAgB;AAAA,UAC7B;AAAA,UACA;AAAA,QACF;AAEA,YAAI,OAAO,gBAAgB,YAAY;AAErC,gBAAM,YAAY;AAClB,iBAAO,UAAU,OAAO;AAAA,QAC1B;AACA,eAAO;AAAA,MACT;AAGA,cAAQ;AAAA,QACN,4CAA4C,YAAY,gBAAgB,aAAa,KAAK,GAAG,KAAK,SAAS;AAAA,MAE7G;AACA,aAAO,WAAW,SAAS;AAAA,IAC7B;AAAA,IACA,CAAC,YAAY,YAAY,aAAa,WAAW,UAAU,gBAAgB,aAAa,WAAW;AAAA,EACrG;AAEA,aAAO,iCAAY;AAAA,IACjB,GAAG;AAAA,IACH,YAAY;AAAA,EACd,CAAC;AACH;AAsCO,SAAS,sBACd,QAC+G;AAC/G,SAAO;AAAA,IACL,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,WAAW,OAAO;AAAA,EACpB;AACF;","names":["import_react","import_react_query","import_react","import_react_query","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.ts","../src/client.ts","../src/matcher.ts","../src/config.ts","../src/hooks.ts","../src/mutation.ts"],"sourcesContent":["/**\n * @demokit-ai/tanstack-query\n *\n * TanStack Query v5 adapter for DemoKit.\n * Mock queries and mutations when demo mode is enabled.\n *\n * @example\n * import { DemoQueryProvider } from '@demokit-ai/tanstack-query'\n *\n * // Define query fixtures\n * const queryFixtures = {\n * '[\"users\"]': [\n * { id: '1', name: 'Demo User' },\n * { id: '2', name: 'Another User' },\n * ],\n * '[\"users\", \":id\"]': ({ params }) => ({\n * id: params.id,\n * name: `User ${params.id}`,\n * }),\n * '[\"projects\", { status: \":status\" }]': ({ params }) => [\n * { id: '1', name: 'Project', status: params.status },\n * ],\n * }\n *\n * // Wrap your app\n * <DemoQueryProvider queries={queryFixtures} enabled={true}>\n * <App />\n * </DemoQueryProvider>\n *\n * @packageDocumentation\n */\n\n// Provider\nexport { DemoQueryProvider } from './provider'\n\n// Config helpers\nexport { createRemoteSource } from './config'\n\n// Hooks\nexport { useDemoQuery, useIsDemoQueryMode } from './hooks'\nexport { useDemoMutation, createMutationOptions } from './mutation'\nexport type { UseDemoMutationOptions, DemoMutationConfig } from './mutation'\n\n// Client utilities\nexport { createDemoQueryClient, createDemoQueryFn, type DemoQueryClient } from './client'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n normalizeQueryKey,\n normalizeFixtureMap,\n parsePatternString,\n matchQueryKey,\n} from './matcher'\n\n// Types\nexport type {\n QueryFixtureContext,\n QueryFixtureHandler,\n QueryFixtureMap,\n QueryFixtureMapObject,\n MutationFixtureContext,\n MutationFixtureHandler,\n MutationFixtureMap,\n MutationFixtureMapObject,\n DemoQueryProviderConfig,\n DemoQueryProviderProps,\n DemoQueryState,\n RemoteSourceConfig,\n} from './types'\n","'use client'\n\nimport { useMemo, useRef, useEffect } from 'react'\nimport { QueryClientProvider, useQueryClient } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport { DemoQueryContext } from './context'\nimport { createDemoQueryFn, createDemoQueryClient } from './client'\nimport { normalizeFixtureMap } from './matcher'\nimport type {\n DemoQueryProviderProps,\n QueryFixtureHandler,\n QueryFixtureMap,\n MutationFixtureHandler,\n MutationFixtureMap,\n DemoQueryState,\n} from './types'\n\n/**\n * Internal provider component that wraps existing QueryClient\n */\nfunction DemoQueryProviderInner({\n children,\n queries = new Map(),\n mutations = new Map(),\n enabled: enabledProp,\n delay = 0,\n staleTime = Infinity,\n}: Omit<DemoQueryProviderProps, 'client'>) {\n const queryClient = useQueryClient()\n const fixturesRef = useRef<QueryFixtureMap>(normalizeFixtureMap(queries))\n const mutationFixturesRef = useRef<MutationFixtureMap>(\n mutations instanceof Map ? mutations : new Map(Object.entries(mutations))\n )\n\n // Use enabled prop directly - demo mode is controlled by parent\n const isDemoMode = enabledProp ?? false\n\n // Create demo-aware query function\n const demoQueryFn = useMemo(\n () =>\n createDemoQueryFn({\n fixtures: fixturesRef.current,\n delay,\n isEnabled: () => isDemoMode,\n }),\n [delay, isDemoMode]\n )\n\n // Update query client defaults when demo mode changes\n useEffect(() => {\n if (isDemoMode) {\n queryClient.setDefaultOptions({\n ...queryClient.getDefaultOptions(),\n queries: {\n ...queryClient.getDefaultOptions().queries,\n queryFn: demoQueryFn,\n staleTime,\n retry: false,\n },\n })\n }\n }, [isDemoMode, demoQueryFn, queryClient, staleTime])\n\n // Create context value\n const contextValue = useMemo<DemoQueryState>(\n () => ({\n isDemoMode,\n\n setQueryFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixturesRef.current.set(pattern, handler)\n },\n\n removeQueryFixture: (pattern: QueryKey) => {\n fixturesRef.current.delete(pattern)\n },\n\n setMutationFixture: (name: string, handler: MutationFixtureHandler) => {\n mutationFixturesRef.current.set(name, handler)\n },\n\n removeMutationFixture: (name: string) => {\n mutationFixturesRef.current.delete(name)\n },\n\n invalidateAll: () => {\n queryClient.invalidateQueries()\n },\n\n resetCache: () => {\n queryClient.clear()\n },\n }),\n [isDemoMode, queryClient]\n )\n\n return (\n <DemoQueryContext.Provider value={contextValue}>\n {children}\n </DemoQueryContext.Provider>\n )\n}\n\n/**\n * Provider component for DemoKit TanStack Query integration\n *\n * Wraps QueryClientProvider and intercepts queries when demo mode is enabled.\n *\n * @example\n * // With new QueryClient\n * <DemoQueryProvider\n * queries={{\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * }}\n * >\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With existing QueryClient\n * const queryClient = new QueryClient()\n *\n * <DemoQueryProvider client={queryClient} queries={...}>\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With DemoKitProvider (auto-detects demo mode)\n * <DemoKitProvider fixtures={...}>\n * <DemoQueryProvider queries={...}>\n * <App />\n * </DemoQueryProvider>\n * </DemoKitProvider>\n */\nexport function DemoQueryProvider({\n children,\n client,\n ...config\n}: DemoQueryProviderProps) {\n // If no client provided, create one\n const { client: demoClient } = useMemo(() => {\n if (client) {\n return { client }\n }\n return createDemoQueryClient(config)\n }, [client, config.enabled])\n\n const queryClient = client ?? demoClient\n\n return (\n <QueryClientProvider client={queryClient}>\n <DemoQueryProviderInner {...config}>{children}</DemoQueryProviderInner>\n </QueryClientProvider>\n )\n}\n","'use client'\n\nimport { createContext } from 'react'\nimport type { DemoQueryState } from './types'\n\n/**\n * Context for DemoQuery state\n * @internal\n */\nexport const DemoQueryContext = createContext<DemoQueryState | undefined>(undefined)\n\nDemoQueryContext.displayName = 'DemoQueryContext'\n","import { QueryClient, type QueryClientConfig } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryFixtureMap, DemoQueryProviderConfig, QueryFixtureHandler } from './types'\nimport { findMatchingFixture, normalizeFixtureMap } from './matcher'\n\n/**\n * Configuration for creating a demo-aware QueryClient\n */\nexport interface DemoQueryClientConfig extends DemoQueryProviderConfig {\n /**\n * Base QueryClient config to extend\n */\n queryClientConfig?: QueryClientConfig\n}\n\n/**\n * Create a demo-aware query function\n *\n * This wraps the default query function to intercept demo queries\n * and return fixture data when demo mode is enabled.\n */\nexport function createDemoQueryFn(config: {\n fixtures: QueryFixtureMap\n delay?: number\n fallbackQueryFn?: DemoQueryProviderConfig['fallbackQueryFn']\n isEnabled: () => boolean\n}) {\n const { fixtures, delay = 0, fallbackQueryFn, isEnabled } = config\n\n return async function demoQueryFn({\n queryKey,\n signal,\n }: {\n queryKey: readonly unknown[]\n signal?: AbortSignal\n }) {\n // If demo mode is not enabled, use fallback\n if (!isEnabled()) {\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fallback query function provided and demo mode is disabled. ` +\n `Query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, queryKey as unknown[])\n\n if (!match) {\n // No fixture found, try fallback\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fixture found for query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n const [handler, { params }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler({\n queryKey: queryKey as unknown[],\n params,\n match: { matched: true, params },\n signal,\n })\n }\n\n // Return static value\n return handler\n }\n}\n\n/**\n * Create a demo-aware QueryClient\n *\n * This creates a QueryClient configured to intercept queries when demo mode\n * is enabled and return fixture data instead of making real API calls.\n *\n * @example\n * const { client, enable, disable, isEnabled } = createDemoQueryClient({\n * queries: {\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * },\n * delay: 100, // Simulate 100ms latency\n * })\n *\n * // Use with QueryClientProvider\n * <QueryClientProvider client={client}>\n * <App />\n * </QueryClientProvider>\n */\nexport function createDemoQueryClient(config: DemoQueryClientConfig = {}) {\n const {\n queries = new Map(),\n delay = 0,\n staleTime = Infinity,\n fallbackQueryFn,\n queryClientConfig = {},\n prepopulateCache = false,\n } = config\n\n let enabled = config.enabled ?? false\n const fixtures = normalizeFixtureMap(queries)\n\n const isEnabled = () => enabled\n\n const demoQueryFn = createDemoQueryFn({\n fixtures,\n delay,\n fallbackQueryFn,\n isEnabled,\n })\n\n const client = new QueryClient({\n ...queryClientConfig,\n defaultOptions: {\n ...queryClientConfig.defaultOptions,\n queries: {\n ...queryClientConfig.defaultOptions?.queries,\n queryFn: demoQueryFn,\n staleTime: enabled ? staleTime : queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: enabled ? false : queryClientConfig.defaultOptions?.queries?.retry,\n },\n },\n })\n\n // Pre-populate cache if configured\n const prepopulate = () => {\n if (!prepopulateCache || !enabled) return\n\n for (const [pattern, handler] of fixtures) {\n // Only pre-populate static values (not functions)\n if (typeof handler !== 'function') {\n // Use pattern as query key for static fixtures\n client.setQueryData(pattern, handler)\n }\n }\n }\n\n return {\n /**\n * The QueryClient instance\n */\n client,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime,\n retry: false,\n },\n })\n prepopulate()\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime: queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: queryClientConfig.defaultOptions?.queries?.retry,\n },\n })\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled,\n\n /**\n * Get the fixture map\n */\n getFixtures: () => fixtures,\n\n /**\n * Add or update a fixture\n */\n setFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixtures.set(pattern, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (pattern: QueryKey) => {\n fixtures.delete(pattern)\n },\n\n /**\n * Clear all query cache\n */\n clearCache: () => {\n client.clear()\n },\n\n /**\n * Invalidate all queries\n */\n invalidateAll: () => {\n client.invalidateQueries()\n },\n }\n}\n\nexport type DemoQueryClient = ReturnType<typeof createDemoQueryClient>\n","import { matchQueryKey, findMatchingQueryKeyPattern } from '@demokit-ai/core'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryKey as TanStackQueryKey } from '@tanstack/react-query'\nimport type { QueryFixtureHandler, QueryFixtureMap, QueryFixtureMapObject } from './types'\n\n/**\n * Convert TanStack Query key to DemoKit QueryKey\n * TanStack Query keys can contain any value, so we normalize them\n */\nexport function normalizeQueryKey(queryKey: TanStackQueryKey): QueryKey {\n return queryKey.map((element) => {\n if (element === null || element === undefined) {\n return element\n }\n if (typeof element === 'object') {\n // Keep objects as-is for matching\n return element as Record<string, unknown>\n }\n // Primitives are kept as-is\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('[\"users\"]') // ['users']\n * parsePatternString('[\"users\", \":id\"]') // ['users', ':id']\n * parsePatternString('users') // ['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: QueryFixtureMapObject | QueryFixtureMap): QueryFixtureMap {\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const map = new Map<QueryKey, QueryFixtureHandler>()\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 a query key\n *\n * @param fixtures - Map of query key patterns to handlers\n * @param queryKey - The query key to match\n * @returns Tuple of [handler, match result] or null if no match\n */\nexport function findMatchingFixture(\n fixtures: QueryFixtureMap,\n queryKey: TanStackQueryKey\n): [QueryFixtureHandler, { params: Record<string, unknown> }] | null {\n const normalizedKey = normalizeQueryKey(queryKey)\n const result = findMatchingQueryKeyPattern(fixtures, normalizedKey)\n\n if (result) {\n const [, handler, matchResult] = result\n return [handler, { params: matchResult.params }]\n }\n\n return null\n}\n\n/**\n * Re-export the matchQueryKey function for direct use\n */\nexport { matchQueryKey }\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/tanstack-query'\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 * <DemoQueryProvider source={demokitSource}>\n * <QueryClientProvider client={queryClient}>\n * <App />\n * </QueryClientProvider>\n * </DemoQueryProvider>\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 } from 'react'\nimport { DemoQueryContext } from './context'\nimport type { DemoQueryState } from './types'\n\n/**\n * Hook to access DemoQuery state and controls\n *\n * @returns DemoQuery context value\n * @throws Error if used outside of DemoQueryProvider\n *\n * @example\n * function MyComponent() {\n * const { isDemoMode, setQueryFixture, invalidateAll } = useDemoQuery()\n *\n * // Dynamically add a fixture\n * const handleAddFixture = () => {\n * setQueryFixture(['users', 'custom'], { id: 'custom', name: 'Custom User' })\n * invalidateAll() // Trigger refetch\n * }\n *\n * return (\n * <button onClick={handleAddFixture}>Add Custom Fixture</button>\n * )\n * }\n */\nexport function useDemoQuery(): DemoQueryState {\n const context = useContext(DemoQueryContext)\n\n if (context === undefined) {\n throw new Error(\n 'useDemoQuery must be used within a DemoQueryProvider. ' +\n 'Make sure to wrap your app with <DemoQueryProvider>.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to check if demo mode is enabled\n * Shorthand for useDemoQuery().isDemoMode\n *\n * @example\n * function MyComponent() {\n * const isDemoMode = useIsDemoQueryMode()\n *\n * return isDemoMode ? <DemoBadge /> : null\n * }\n */\nexport function useIsDemoQueryMode(): boolean {\n return useDemoQuery().isDemoMode\n}\n","'use client'\n\nimport { useMutation, useQueryClient, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport type { MutationFixtureContext, MutationFixtureHandler } from './types'\nimport { useDemoQuery } from './hooks'\n\n/**\n * Options for useDemoMutation hook\n */\nexport interface UseDemoMutationOptions<TData, TError, TVariables, TContext>\n extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {\n /**\n * The real mutation function to use when demo mode is disabled\n */\n mutationFn: (variables: TVariables) => Promise<TData>\n\n /**\n * Name used to look up the demo fixture\n * If not provided, uses mutationKey as string\n */\n demoName?: string\n\n /**\n * Demo fixture handler for this mutation\n * If provided, overrides the fixture from DemoQueryProvider\n */\n demoFixture?: MutationFixtureHandler<TData, TVariables>\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 * @example\n * const createUser = useDemoMutation({\n * mutationFn: async (data) => api.createUser(data),\n * demoName: 'createUser',\n * demoFixture: ({ variables, queryClient }) => {\n * // Create demo user\n * const newUser = { id: crypto.randomUUID(), ...variables }\n *\n * // Update the users query cache\n * queryClient.setQueryData(['users'], (old: User[] = []) => [...old, newUser])\n *\n * return newUser\n * },\n * onSuccess: (data) => {\n * console.log('Created user:', data)\n * },\n * })\n *\n * // Use like normal useMutation\n * createUser.mutate({ name: 'New User', email: 'user@example.com' })\n */\nexport function useDemoMutation<\n TData = unknown,\n TError = unknown,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseDemoMutationOptions<TData, TError, TVariables, TContext>\n): UseMutationResult<TData, TError, TVariables, TContext> {\n const { mutationFn, demoName, demoFixture, demoDelay = 0, ...mutationOptions } = options\n\n const queryClient = useQueryClient()\n\n // Try to get demo state - may not be in DemoQueryProvider context\n let isDemoMode = false\n try {\n const demoState = useDemoQuery()\n isDemoMode = demoState.isDemoMode\n } catch {\n // Not in DemoQueryProvider context, use real mutation\n }\n\n // Create the demo-aware mutation function\n const demoAwareMutationFn = useCallback(\n async (variables: TVariables): Promise<TData> => {\n // If not in demo mode, use real mutation\n if (!isDemoMode) {\n return mutationFn(variables)\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: MutationFixtureContext<TVariables> = {\n mutationKey: mutationOptions.mutationKey,\n variables,\n queryClient,\n }\n\n if (typeof demoFixture === 'function') {\n // Cast to the function type to help TypeScript understand\n const fixtureFn = demoFixture as (context: MutationFixtureContext<TVariables>) => 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] No mutation fixture found for \"${demoName || mutationOptions.mutationKey?.join('/') || 'unknown'}\". ` +\n 'Using real mutation function.'\n )\n return mutationFn(variables)\n },\n [isDemoMode, mutationFn, demoFixture, demoDelay, demoName, mutationOptions.mutationKey, queryClient]\n )\n\n return useMutation({\n ...mutationOptions,\n mutationFn: demoAwareMutationFn,\n })\n}\n\n/**\n * Create a set of demo mutations with fixtures\n *\n * @example\n * const mutations = createDemoMutations({\n * createUser: {\n * mutationFn: api.createUser,\n * fixture: ({ variables, queryClient }) => {\n * const newUser = { id: 'demo-1', ...variables }\n * queryClient.setQueryData(['users'], (old = []) => [...old, newUser])\n * return newUser\n * },\n * },\n * deleteUser: {\n * mutationFn: api.deleteUser,\n * fixture: ({ variables, queryClient }) => {\n * queryClient.setQueryData(['users'], (old: User[] = []) =>\n * old.filter(u => u.id !== variables.id)\n * )\n * return { success: true }\n * },\n * },\n * })\n *\n * // Use in components\n * const { createUser, deleteUser } = mutations\n */\nexport type DemoMutationConfig<TData, TVariables> = {\n mutationFn: (variables: TVariables) => Promise<TData>\n fixture: MutationFixtureHandler<TData, TVariables>\n delay?: number\n}\n\n/**\n * Helper to create mutation options with demo fixture\n */\nexport function createMutationOptions<TData, TVariables>(\n config: DemoMutationConfig<TData, TVariables>\n): Pick<UseDemoMutationOptions<TData, unknown, TVariables, unknown>, 'mutationFn' | 'demoFixture' | 'demoDelay'> {\n return {\n mutationFn: config.mutationFn,\n demoFixture: config.fixture,\n demoDelay: config.delay,\n }\n}\n"],"mappings":"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","names":["import_react","import_react_query","import_react","import_react_query","import_react"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -159,6 +159,38 @@ interface DemoQueryState {
|
|
|
159
159
|
*/
|
|
160
160
|
resetCache: () => void;
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Configuration for remote fixture source (DemoKit Cloud)
|
|
164
|
+
*/
|
|
165
|
+
interface RemoteSourceConfig {
|
|
166
|
+
/**
|
|
167
|
+
* DemoKit Cloud API URL (versioned base URL)
|
|
168
|
+
* The SDK will append `/fixtures` to this URL.
|
|
169
|
+
* @example 'https://demokit-cloud.kasava.dev/api'
|
|
170
|
+
* @default 'https://api.demokit.cloud/api'
|
|
171
|
+
*/
|
|
172
|
+
apiUrl: string;
|
|
173
|
+
/**
|
|
174
|
+
* DemoKit Cloud API key
|
|
175
|
+
* Format: dk_live_xxx
|
|
176
|
+
*/
|
|
177
|
+
apiKey: string;
|
|
178
|
+
/**
|
|
179
|
+
* Request timeout in milliseconds
|
|
180
|
+
* @default 10000
|
|
181
|
+
*/
|
|
182
|
+
timeout?: number;
|
|
183
|
+
/**
|
|
184
|
+
* Whether to retry failed requests
|
|
185
|
+
* @default true
|
|
186
|
+
*/
|
|
187
|
+
retry?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Maximum number of retries
|
|
190
|
+
* @default 3
|
|
191
|
+
*/
|
|
192
|
+
maxRetries?: number;
|
|
193
|
+
}
|
|
162
194
|
|
|
163
195
|
/**
|
|
164
196
|
* Provider component for DemoKit TanStack Query integration
|
|
@@ -194,6 +226,37 @@ interface DemoQueryState {
|
|
|
194
226
|
*/
|
|
195
227
|
declare function DemoQueryProvider({ children, client, ...config }: DemoQueryProviderProps): react_jsx_runtime.JSX.Element;
|
|
196
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Create a remote source configuration for fetching fixtures from DemoKit Cloud
|
|
231
|
+
*
|
|
232
|
+
* The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // lib/demokit-config.ts
|
|
237
|
+
* import { createRemoteSource } from '@demokit-ai/tanstack-query'
|
|
238
|
+
*
|
|
239
|
+
* // .env:
|
|
240
|
+
* // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
|
|
241
|
+
* // VITE_DEMOKIT_API_KEY=dk_live_xxxx
|
|
242
|
+
*
|
|
243
|
+
* export const demokitSource = createRemoteSource({
|
|
244
|
+
* apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,
|
|
245
|
+
* apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,
|
|
246
|
+
* })
|
|
247
|
+
*
|
|
248
|
+
* // Then in your app:
|
|
249
|
+
* import { demokitSource } from './lib/demokit-config'
|
|
250
|
+
*
|
|
251
|
+
* <DemoQueryProvider source={demokitSource}>
|
|
252
|
+
* <QueryClientProvider client={queryClient}>
|
|
253
|
+
* <App />
|
|
254
|
+
* </QueryClientProvider>
|
|
255
|
+
* </DemoQueryProvider>
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
|
|
259
|
+
|
|
197
260
|
/**
|
|
198
261
|
* Hook to access DemoQuery state and controls
|
|
199
262
|
*
|
|
@@ -429,4 +492,4 @@ declare function findMatchingFixture(fixtures: QueryFixtureMap, queryKey: QueryK
|
|
|
429
492
|
params: Record<string, unknown>;
|
|
430
493
|
}] | null;
|
|
431
494
|
|
|
432
|
-
export { type DemoMutationConfig, type DemoQueryClient, DemoQueryProvider, type DemoQueryProviderConfig, type DemoQueryProviderProps, type DemoQueryState, type MutationFixtureContext, type MutationFixtureHandler, type MutationFixtureMap, type MutationFixtureMapObject, type QueryFixtureContext, type QueryFixtureHandler, type QueryFixtureMap, type QueryFixtureMapObject, type UseDemoMutationOptions, createDemoQueryClient, createDemoQueryFn, createMutationOptions, findMatchingFixture, normalizeFixtureMap, normalizeQueryKey, parsePatternString, useDemoMutation, useDemoQuery, useIsDemoQueryMode };
|
|
495
|
+
export { type DemoMutationConfig, type DemoQueryClient, DemoQueryProvider, type DemoQueryProviderConfig, type DemoQueryProviderProps, type DemoQueryState, type MutationFixtureContext, type MutationFixtureHandler, type MutationFixtureMap, type MutationFixtureMapObject, type QueryFixtureContext, type QueryFixtureHandler, type QueryFixtureMap, type QueryFixtureMapObject, type RemoteSourceConfig, type UseDemoMutationOptions, createDemoQueryClient, createDemoQueryFn, createMutationOptions, createRemoteSource, findMatchingFixture, normalizeFixtureMap, normalizeQueryKey, parsePatternString, useDemoMutation, useDemoQuery, useIsDemoQueryMode };
|
package/dist/index.d.ts
CHANGED
|
@@ -159,6 +159,38 @@ interface DemoQueryState {
|
|
|
159
159
|
*/
|
|
160
160
|
resetCache: () => void;
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Configuration for remote fixture source (DemoKit Cloud)
|
|
164
|
+
*/
|
|
165
|
+
interface RemoteSourceConfig {
|
|
166
|
+
/**
|
|
167
|
+
* DemoKit Cloud API URL (versioned base URL)
|
|
168
|
+
* The SDK will append `/fixtures` to this URL.
|
|
169
|
+
* @example 'https://demokit-cloud.kasava.dev/api'
|
|
170
|
+
* @default 'https://api.demokit.cloud/api'
|
|
171
|
+
*/
|
|
172
|
+
apiUrl: string;
|
|
173
|
+
/**
|
|
174
|
+
* DemoKit Cloud API key
|
|
175
|
+
* Format: dk_live_xxx
|
|
176
|
+
*/
|
|
177
|
+
apiKey: string;
|
|
178
|
+
/**
|
|
179
|
+
* Request timeout in milliseconds
|
|
180
|
+
* @default 10000
|
|
181
|
+
*/
|
|
182
|
+
timeout?: number;
|
|
183
|
+
/**
|
|
184
|
+
* Whether to retry failed requests
|
|
185
|
+
* @default true
|
|
186
|
+
*/
|
|
187
|
+
retry?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Maximum number of retries
|
|
190
|
+
* @default 3
|
|
191
|
+
*/
|
|
192
|
+
maxRetries?: number;
|
|
193
|
+
}
|
|
162
194
|
|
|
163
195
|
/**
|
|
164
196
|
* Provider component for DemoKit TanStack Query integration
|
|
@@ -194,6 +226,37 @@ interface DemoQueryState {
|
|
|
194
226
|
*/
|
|
195
227
|
declare function DemoQueryProvider({ children, client, ...config }: DemoQueryProviderProps): react_jsx_runtime.JSX.Element;
|
|
196
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Create a remote source configuration for fetching fixtures from DemoKit Cloud
|
|
231
|
+
*
|
|
232
|
+
* The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // lib/demokit-config.ts
|
|
237
|
+
* import { createRemoteSource } from '@demokit-ai/tanstack-query'
|
|
238
|
+
*
|
|
239
|
+
* // .env:
|
|
240
|
+
* // VITE_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
|
|
241
|
+
* // VITE_DEMOKIT_API_KEY=dk_live_xxxx
|
|
242
|
+
*
|
|
243
|
+
* export const demokitSource = createRemoteSource({
|
|
244
|
+
* apiUrl: import.meta.env.VITE_DEMOKIT_API_URL,
|
|
245
|
+
* apiKey: import.meta.env.VITE_DEMOKIT_API_KEY,
|
|
246
|
+
* })
|
|
247
|
+
*
|
|
248
|
+
* // Then in your app:
|
|
249
|
+
* import { demokitSource } from './lib/demokit-config'
|
|
250
|
+
*
|
|
251
|
+
* <DemoQueryProvider source={demokitSource}>
|
|
252
|
+
* <QueryClientProvider client={queryClient}>
|
|
253
|
+
* <App />
|
|
254
|
+
* </QueryClientProvider>
|
|
255
|
+
* </DemoQueryProvider>
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
|
|
259
|
+
|
|
197
260
|
/**
|
|
198
261
|
* Hook to access DemoQuery state and controls
|
|
199
262
|
*
|
|
@@ -429,4 +492,4 @@ declare function findMatchingFixture(fixtures: QueryFixtureMap, queryKey: QueryK
|
|
|
429
492
|
params: Record<string, unknown>;
|
|
430
493
|
}] | null;
|
|
431
494
|
|
|
432
|
-
export { type DemoMutationConfig, type DemoQueryClient, DemoQueryProvider, type DemoQueryProviderConfig, type DemoQueryProviderProps, type DemoQueryState, type MutationFixtureContext, type MutationFixtureHandler, type MutationFixtureMap, type MutationFixtureMapObject, type QueryFixtureContext, type QueryFixtureHandler, type QueryFixtureMap, type QueryFixtureMapObject, type UseDemoMutationOptions, createDemoQueryClient, createDemoQueryFn, createMutationOptions, findMatchingFixture, normalizeFixtureMap, normalizeQueryKey, parsePatternString, useDemoMutation, useDemoQuery, useIsDemoQueryMode };
|
|
495
|
+
export { type DemoMutationConfig, type DemoQueryClient, DemoQueryProvider, type DemoQueryProviderConfig, type DemoQueryProviderProps, type DemoQueryState, type MutationFixtureContext, type MutationFixtureHandler, type MutationFixtureMap, type MutationFixtureMapObject, type QueryFixtureContext, type QueryFixtureHandler, type QueryFixtureMap, type QueryFixtureMapObject, type RemoteSourceConfig, type UseDemoMutationOptions, createDemoQueryClient, createDemoQueryFn, createMutationOptions, createRemoteSource, findMatchingFixture, normalizeFixtureMap, normalizeQueryKey, parsePatternString, useDemoMutation, useDemoQuery, useIsDemoQueryMode };
|
package/dist/index.js
CHANGED
|
@@ -276,6 +276,16 @@ function DemoQueryProvider({
|
|
|
276
276
|
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(DemoQueryProviderInner, { ...config, children }) });
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
// src/config.ts
|
|
280
|
+
function createRemoteSource(config) {
|
|
281
|
+
return {
|
|
282
|
+
timeout: 1e4,
|
|
283
|
+
retry: true,
|
|
284
|
+
maxRetries: 3,
|
|
285
|
+
...config
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
279
289
|
// src/hooks.ts
|
|
280
290
|
import { useContext } from "react";
|
|
281
291
|
function useDemoQuery() {
|
|
@@ -347,6 +357,7 @@ export {
|
|
|
347
357
|
createDemoQueryClient,
|
|
348
358
|
createDemoQueryFn,
|
|
349
359
|
createMutationOptions,
|
|
360
|
+
createRemoteSource,
|
|
350
361
|
findMatchingFixture,
|
|
351
362
|
matchQueryKey,
|
|
352
363
|
normalizeFixtureMap,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/client.ts","../src/matcher.ts","../src/hooks.ts","../src/mutation.ts"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useEffect } from 'react'\nimport { QueryClientProvider, useQueryClient } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport { DemoQueryContext } from './context'\nimport { createDemoQueryFn, createDemoQueryClient } from './client'\nimport { normalizeFixtureMap } from './matcher'\nimport type {\n DemoQueryProviderProps,\n QueryFixtureHandler,\n QueryFixtureMap,\n MutationFixtureHandler,\n MutationFixtureMap,\n DemoQueryState,\n} from './types'\n\n/**\n * Internal provider component that wraps existing QueryClient\n */\nfunction DemoQueryProviderInner({\n children,\n queries = new Map(),\n mutations = new Map(),\n enabled: enabledProp,\n delay = 0,\n staleTime = Infinity,\n}: Omit<DemoQueryProviderProps, 'client'>) {\n const queryClient = useQueryClient()\n const fixturesRef = useRef<QueryFixtureMap>(normalizeFixtureMap(queries))\n const mutationFixturesRef = useRef<MutationFixtureMap>(\n mutations instanceof Map ? mutations : new Map(Object.entries(mutations))\n )\n\n // Use enabled prop directly - demo mode is controlled by parent\n const isDemoMode = enabledProp ?? false\n\n // Create demo-aware query function\n const demoQueryFn = useMemo(\n () =>\n createDemoQueryFn({\n fixtures: fixturesRef.current,\n delay,\n isEnabled: () => isDemoMode,\n }),\n [delay, isDemoMode]\n )\n\n // Update query client defaults when demo mode changes\n useEffect(() => {\n if (isDemoMode) {\n queryClient.setDefaultOptions({\n ...queryClient.getDefaultOptions(),\n queries: {\n ...queryClient.getDefaultOptions().queries,\n queryFn: demoQueryFn,\n staleTime,\n retry: false,\n },\n })\n }\n }, [isDemoMode, demoQueryFn, queryClient, staleTime])\n\n // Create context value\n const contextValue = useMemo<DemoQueryState>(\n () => ({\n isDemoMode,\n\n setQueryFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixturesRef.current.set(pattern, handler)\n },\n\n removeQueryFixture: (pattern: QueryKey) => {\n fixturesRef.current.delete(pattern)\n },\n\n setMutationFixture: (name: string, handler: MutationFixtureHandler) => {\n mutationFixturesRef.current.set(name, handler)\n },\n\n removeMutationFixture: (name: string) => {\n mutationFixturesRef.current.delete(name)\n },\n\n invalidateAll: () => {\n queryClient.invalidateQueries()\n },\n\n resetCache: () => {\n queryClient.clear()\n },\n }),\n [isDemoMode, queryClient]\n )\n\n return (\n <DemoQueryContext.Provider value={contextValue}>\n {children}\n </DemoQueryContext.Provider>\n )\n}\n\n/**\n * Provider component for DemoKit TanStack Query integration\n *\n * Wraps QueryClientProvider and intercepts queries when demo mode is enabled.\n *\n * @example\n * // With new QueryClient\n * <DemoQueryProvider\n * queries={{\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * }}\n * >\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With existing QueryClient\n * const queryClient = new QueryClient()\n *\n * <DemoQueryProvider client={queryClient} queries={...}>\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With DemoKitProvider (auto-detects demo mode)\n * <DemoKitProvider fixtures={...}>\n * <DemoQueryProvider queries={...}>\n * <App />\n * </DemoQueryProvider>\n * </DemoKitProvider>\n */\nexport function DemoQueryProvider({\n children,\n client,\n ...config\n}: DemoQueryProviderProps) {\n // If no client provided, create one\n const { client: demoClient } = useMemo(() => {\n if (client) {\n return { client }\n }\n return createDemoQueryClient(config)\n }, [client, config.enabled])\n\n const queryClient = client ?? demoClient\n\n return (\n <QueryClientProvider client={queryClient}>\n <DemoQueryProviderInner {...config}>{children}</DemoQueryProviderInner>\n </QueryClientProvider>\n )\n}\n","'use client'\n\nimport { createContext } from 'react'\nimport type { DemoQueryState } from './types'\n\n/**\n * Context for DemoQuery state\n * @internal\n */\nexport const DemoQueryContext = createContext<DemoQueryState | undefined>(undefined)\n\nDemoQueryContext.displayName = 'DemoQueryContext'\n","import { QueryClient, type QueryClientConfig } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryFixtureMap, DemoQueryProviderConfig, QueryFixtureHandler } from './types'\nimport { findMatchingFixture, normalizeFixtureMap } from './matcher'\n\n/**\n * Configuration for creating a demo-aware QueryClient\n */\nexport interface DemoQueryClientConfig extends DemoQueryProviderConfig {\n /**\n * Base QueryClient config to extend\n */\n queryClientConfig?: QueryClientConfig\n}\n\n/**\n * Create a demo-aware query function\n *\n * This wraps the default query function to intercept demo queries\n * and return fixture data when demo mode is enabled.\n */\nexport function createDemoQueryFn(config: {\n fixtures: QueryFixtureMap\n delay?: number\n fallbackQueryFn?: DemoQueryProviderConfig['fallbackQueryFn']\n isEnabled: () => boolean\n}) {\n const { fixtures, delay = 0, fallbackQueryFn, isEnabled } = config\n\n return async function demoQueryFn({\n queryKey,\n signal,\n }: {\n queryKey: readonly unknown[]\n signal?: AbortSignal\n }) {\n // If demo mode is not enabled, use fallback\n if (!isEnabled()) {\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fallback query function provided and demo mode is disabled. ` +\n `Query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, queryKey as unknown[])\n\n if (!match) {\n // No fixture found, try fallback\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fixture found for query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n const [handler, { params }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler({\n queryKey: queryKey as unknown[],\n params,\n match: { matched: true, params },\n signal,\n })\n }\n\n // Return static value\n return handler\n }\n}\n\n/**\n * Create a demo-aware QueryClient\n *\n * This creates a QueryClient configured to intercept queries when demo mode\n * is enabled and return fixture data instead of making real API calls.\n *\n * @example\n * const { client, enable, disable, isEnabled } = createDemoQueryClient({\n * queries: {\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * },\n * delay: 100, // Simulate 100ms latency\n * })\n *\n * // Use with QueryClientProvider\n * <QueryClientProvider client={client}>\n * <App />\n * </QueryClientProvider>\n */\nexport function createDemoQueryClient(config: DemoQueryClientConfig = {}) {\n const {\n queries = new Map(),\n delay = 0,\n staleTime = Infinity,\n fallbackQueryFn,\n queryClientConfig = {},\n prepopulateCache = false,\n } = config\n\n let enabled = config.enabled ?? false\n const fixtures = normalizeFixtureMap(queries)\n\n const isEnabled = () => enabled\n\n const demoQueryFn = createDemoQueryFn({\n fixtures,\n delay,\n fallbackQueryFn,\n isEnabled,\n })\n\n const client = new QueryClient({\n ...queryClientConfig,\n defaultOptions: {\n ...queryClientConfig.defaultOptions,\n queries: {\n ...queryClientConfig.defaultOptions?.queries,\n queryFn: demoQueryFn,\n staleTime: enabled ? staleTime : queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: enabled ? false : queryClientConfig.defaultOptions?.queries?.retry,\n },\n },\n })\n\n // Pre-populate cache if configured\n const prepopulate = () => {\n if (!prepopulateCache || !enabled) return\n\n for (const [pattern, handler] of fixtures) {\n // Only pre-populate static values (not functions)\n if (typeof handler !== 'function') {\n // Use pattern as query key for static fixtures\n client.setQueryData(pattern, handler)\n }\n }\n }\n\n return {\n /**\n * The QueryClient instance\n */\n client,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime,\n retry: false,\n },\n })\n prepopulate()\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime: queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: queryClientConfig.defaultOptions?.queries?.retry,\n },\n })\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled,\n\n /**\n * Get the fixture map\n */\n getFixtures: () => fixtures,\n\n /**\n * Add or update a fixture\n */\n setFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixtures.set(pattern, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (pattern: QueryKey) => {\n fixtures.delete(pattern)\n },\n\n /**\n * Clear all query cache\n */\n clearCache: () => {\n client.clear()\n },\n\n /**\n * Invalidate all queries\n */\n invalidateAll: () => {\n client.invalidateQueries()\n },\n }\n}\n\nexport type DemoQueryClient = ReturnType<typeof createDemoQueryClient>\n","import { matchQueryKey, findMatchingQueryKeyPattern } from '@demokit-ai/core'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryKey as TanStackQueryKey } from '@tanstack/react-query'\nimport type { QueryFixtureHandler, QueryFixtureMap, QueryFixtureMapObject } from './types'\n\n/**\n * Convert TanStack Query key to DemoKit QueryKey\n * TanStack Query keys can contain any value, so we normalize them\n */\nexport function normalizeQueryKey(queryKey: TanStackQueryKey): QueryKey {\n return queryKey.map((element) => {\n if (element === null || element === undefined) {\n return element\n }\n if (typeof element === 'object') {\n // Keep objects as-is for matching\n return element as Record<string, unknown>\n }\n // Primitives are kept as-is\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('[\"users\"]') // ['users']\n * parsePatternString('[\"users\", \":id\"]') // ['users', ':id']\n * parsePatternString('users') // ['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: QueryFixtureMapObject | QueryFixtureMap): QueryFixtureMap {\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const map = new Map<QueryKey, QueryFixtureHandler>()\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 a query key\n *\n * @param fixtures - Map of query key patterns to handlers\n * @param queryKey - The query key to match\n * @returns Tuple of [handler, match result] or null if no match\n */\nexport function findMatchingFixture(\n fixtures: QueryFixtureMap,\n queryKey: TanStackQueryKey\n): [QueryFixtureHandler, { params: Record<string, unknown> }] | null {\n const normalizedKey = normalizeQueryKey(queryKey)\n const result = findMatchingQueryKeyPattern(fixtures, normalizedKey)\n\n if (result) {\n const [, handler, matchResult] = result\n return [handler, { params: matchResult.params }]\n }\n\n return null\n}\n\n/**\n * Re-export the matchQueryKey function for direct use\n */\nexport { matchQueryKey }\n","'use client'\n\nimport { useContext } from 'react'\nimport { DemoQueryContext } from './context'\nimport type { DemoQueryState } from './types'\n\n/**\n * Hook to access DemoQuery state and controls\n *\n * @returns DemoQuery context value\n * @throws Error if used outside of DemoQueryProvider\n *\n * @example\n * function MyComponent() {\n * const { isDemoMode, setQueryFixture, invalidateAll } = useDemoQuery()\n *\n * // Dynamically add a fixture\n * const handleAddFixture = () => {\n * setQueryFixture(['users', 'custom'], { id: 'custom', name: 'Custom User' })\n * invalidateAll() // Trigger refetch\n * }\n *\n * return (\n * <button onClick={handleAddFixture}>Add Custom Fixture</button>\n * )\n * }\n */\nexport function useDemoQuery(): DemoQueryState {\n const context = useContext(DemoQueryContext)\n\n if (context === undefined) {\n throw new Error(\n 'useDemoQuery must be used within a DemoQueryProvider. ' +\n 'Make sure to wrap your app with <DemoQueryProvider>.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to check if demo mode is enabled\n * Shorthand for useDemoQuery().isDemoMode\n *\n * @example\n * function MyComponent() {\n * const isDemoMode = useIsDemoQueryMode()\n *\n * return isDemoMode ? <DemoBadge /> : null\n * }\n */\nexport function useIsDemoQueryMode(): boolean {\n return useDemoQuery().isDemoMode\n}\n","'use client'\n\nimport { useMutation, useQueryClient, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport type { MutationFixtureContext, MutationFixtureHandler } from './types'\nimport { useDemoQuery } from './hooks'\n\n/**\n * Options for useDemoMutation hook\n */\nexport interface UseDemoMutationOptions<TData, TError, TVariables, TContext>\n extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {\n /**\n * The real mutation function to use when demo mode is disabled\n */\n mutationFn: (variables: TVariables) => Promise<TData>\n\n /**\n * Name used to look up the demo fixture\n * If not provided, uses mutationKey as string\n */\n demoName?: string\n\n /**\n * Demo fixture handler for this mutation\n * If provided, overrides the fixture from DemoQueryProvider\n */\n demoFixture?: MutationFixtureHandler<TData, TVariables>\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 * @example\n * const createUser = useDemoMutation({\n * mutationFn: async (data) => api.createUser(data),\n * demoName: 'createUser',\n * demoFixture: ({ variables, queryClient }) => {\n * // Create demo user\n * const newUser = { id: crypto.randomUUID(), ...variables }\n *\n * // Update the users query cache\n * queryClient.setQueryData(['users'], (old: User[] = []) => [...old, newUser])\n *\n * return newUser\n * },\n * onSuccess: (data) => {\n * console.log('Created user:', data)\n * },\n * })\n *\n * // Use like normal useMutation\n * createUser.mutate({ name: 'New User', email: 'user@example.com' })\n */\nexport function useDemoMutation<\n TData = unknown,\n TError = unknown,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseDemoMutationOptions<TData, TError, TVariables, TContext>\n): UseMutationResult<TData, TError, TVariables, TContext> {\n const { mutationFn, demoName, demoFixture, demoDelay = 0, ...mutationOptions } = options\n\n const queryClient = useQueryClient()\n\n // Try to get demo state - may not be in DemoQueryProvider context\n let isDemoMode = false\n try {\n const demoState = useDemoQuery()\n isDemoMode = demoState.isDemoMode\n } catch {\n // Not in DemoQueryProvider context, use real mutation\n }\n\n // Create the demo-aware mutation function\n const demoAwareMutationFn = useCallback(\n async (variables: TVariables): Promise<TData> => {\n // If not in demo mode, use real mutation\n if (!isDemoMode) {\n return mutationFn(variables)\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: MutationFixtureContext<TVariables> = {\n mutationKey: mutationOptions.mutationKey,\n variables,\n queryClient,\n }\n\n if (typeof demoFixture === 'function') {\n // Cast to the function type to help TypeScript understand\n const fixtureFn = demoFixture as (context: MutationFixtureContext<TVariables>) => 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] No mutation fixture found for \"${demoName || mutationOptions.mutationKey?.join('/') || 'unknown'}\". ` +\n 'Using real mutation function.'\n )\n return mutationFn(variables)\n },\n [isDemoMode, mutationFn, demoFixture, demoDelay, demoName, mutationOptions.mutationKey, queryClient]\n )\n\n return useMutation({\n ...mutationOptions,\n mutationFn: demoAwareMutationFn,\n })\n}\n\n/**\n * Create a set of demo mutations with fixtures\n *\n * @example\n * const mutations = createDemoMutations({\n * createUser: {\n * mutationFn: api.createUser,\n * fixture: ({ variables, queryClient }) => {\n * const newUser = { id: 'demo-1', ...variables }\n * queryClient.setQueryData(['users'], (old = []) => [...old, newUser])\n * return newUser\n * },\n * },\n * deleteUser: {\n * mutationFn: api.deleteUser,\n * fixture: ({ variables, queryClient }) => {\n * queryClient.setQueryData(['users'], (old: User[] = []) =>\n * old.filter(u => u.id !== variables.id)\n * )\n * return { success: true }\n * },\n * },\n * })\n *\n * // Use in components\n * const { createUser, deleteUser } = mutations\n */\nexport type DemoMutationConfig<TData, TVariables> = {\n mutationFn: (variables: TVariables) => Promise<TData>\n fixture: MutationFixtureHandler<TData, TVariables>\n delay?: number\n}\n\n/**\n * Helper to create mutation options with demo fixture\n */\nexport function createMutationOptions<TData, TVariables>(\n config: DemoMutationConfig<TData, TVariables>\n): Pick<UseDemoMutationOptions<TData, unknown, TVariables, unknown>, 'mutationFn' | 'demoFixture' | 'demoDelay'> {\n return {\n mutationFn: config.mutationFn,\n demoFixture: config.fixture,\n demoDelay: config.delay,\n }\n}\n"],"mappings":"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","names":["useQueryClient","useQueryClient"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/client.ts","../src/matcher.ts","../src/config.ts","../src/hooks.ts","../src/mutation.ts"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useEffect } from 'react'\nimport { QueryClientProvider, useQueryClient } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport { DemoQueryContext } from './context'\nimport { createDemoQueryFn, createDemoQueryClient } from './client'\nimport { normalizeFixtureMap } from './matcher'\nimport type {\n DemoQueryProviderProps,\n QueryFixtureHandler,\n QueryFixtureMap,\n MutationFixtureHandler,\n MutationFixtureMap,\n DemoQueryState,\n} from './types'\n\n/**\n * Internal provider component that wraps existing QueryClient\n */\nfunction DemoQueryProviderInner({\n children,\n queries = new Map(),\n mutations = new Map(),\n enabled: enabledProp,\n delay = 0,\n staleTime = Infinity,\n}: Omit<DemoQueryProviderProps, 'client'>) {\n const queryClient = useQueryClient()\n const fixturesRef = useRef<QueryFixtureMap>(normalizeFixtureMap(queries))\n const mutationFixturesRef = useRef<MutationFixtureMap>(\n mutations instanceof Map ? mutations : new Map(Object.entries(mutations))\n )\n\n // Use enabled prop directly - demo mode is controlled by parent\n const isDemoMode = enabledProp ?? false\n\n // Create demo-aware query function\n const demoQueryFn = useMemo(\n () =>\n createDemoQueryFn({\n fixtures: fixturesRef.current,\n delay,\n isEnabled: () => isDemoMode,\n }),\n [delay, isDemoMode]\n )\n\n // Update query client defaults when demo mode changes\n useEffect(() => {\n if (isDemoMode) {\n queryClient.setDefaultOptions({\n ...queryClient.getDefaultOptions(),\n queries: {\n ...queryClient.getDefaultOptions().queries,\n queryFn: demoQueryFn,\n staleTime,\n retry: false,\n },\n })\n }\n }, [isDemoMode, demoQueryFn, queryClient, staleTime])\n\n // Create context value\n const contextValue = useMemo<DemoQueryState>(\n () => ({\n isDemoMode,\n\n setQueryFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixturesRef.current.set(pattern, handler)\n },\n\n removeQueryFixture: (pattern: QueryKey) => {\n fixturesRef.current.delete(pattern)\n },\n\n setMutationFixture: (name: string, handler: MutationFixtureHandler) => {\n mutationFixturesRef.current.set(name, handler)\n },\n\n removeMutationFixture: (name: string) => {\n mutationFixturesRef.current.delete(name)\n },\n\n invalidateAll: () => {\n queryClient.invalidateQueries()\n },\n\n resetCache: () => {\n queryClient.clear()\n },\n }),\n [isDemoMode, queryClient]\n )\n\n return (\n <DemoQueryContext.Provider value={contextValue}>\n {children}\n </DemoQueryContext.Provider>\n )\n}\n\n/**\n * Provider component for DemoKit TanStack Query integration\n *\n * Wraps QueryClientProvider and intercepts queries when demo mode is enabled.\n *\n * @example\n * // With new QueryClient\n * <DemoQueryProvider\n * queries={{\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * }}\n * >\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With existing QueryClient\n * const queryClient = new QueryClient()\n *\n * <DemoQueryProvider client={queryClient} queries={...}>\n * <App />\n * </DemoQueryProvider>\n *\n * @example\n * // With DemoKitProvider (auto-detects demo mode)\n * <DemoKitProvider fixtures={...}>\n * <DemoQueryProvider queries={...}>\n * <App />\n * </DemoQueryProvider>\n * </DemoKitProvider>\n */\nexport function DemoQueryProvider({\n children,\n client,\n ...config\n}: DemoQueryProviderProps) {\n // If no client provided, create one\n const { client: demoClient } = useMemo(() => {\n if (client) {\n return { client }\n }\n return createDemoQueryClient(config)\n }, [client, config.enabled])\n\n const queryClient = client ?? demoClient\n\n return (\n <QueryClientProvider client={queryClient}>\n <DemoQueryProviderInner {...config}>{children}</DemoQueryProviderInner>\n </QueryClientProvider>\n )\n}\n","'use client'\n\nimport { createContext } from 'react'\nimport type { DemoQueryState } from './types'\n\n/**\n * Context for DemoQuery state\n * @internal\n */\nexport const DemoQueryContext = createContext<DemoQueryState | undefined>(undefined)\n\nDemoQueryContext.displayName = 'DemoQueryContext'\n","import { QueryClient, type QueryClientConfig } from '@tanstack/react-query'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryFixtureMap, DemoQueryProviderConfig, QueryFixtureHandler } from './types'\nimport { findMatchingFixture, normalizeFixtureMap } from './matcher'\n\n/**\n * Configuration for creating a demo-aware QueryClient\n */\nexport interface DemoQueryClientConfig extends DemoQueryProviderConfig {\n /**\n * Base QueryClient config to extend\n */\n queryClientConfig?: QueryClientConfig\n}\n\n/**\n * Create a demo-aware query function\n *\n * This wraps the default query function to intercept demo queries\n * and return fixture data when demo mode is enabled.\n */\nexport function createDemoQueryFn(config: {\n fixtures: QueryFixtureMap\n delay?: number\n fallbackQueryFn?: DemoQueryProviderConfig['fallbackQueryFn']\n isEnabled: () => boolean\n}) {\n const { fixtures, delay = 0, fallbackQueryFn, isEnabled } = config\n\n return async function demoQueryFn({\n queryKey,\n signal,\n }: {\n queryKey: readonly unknown[]\n signal?: AbortSignal\n }) {\n // If demo mode is not enabled, use fallback\n if (!isEnabled()) {\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fallback query function provided and demo mode is disabled. ` +\n `Query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, queryKey as unknown[])\n\n if (!match) {\n // No fixture found, try fallback\n if (fallbackQueryFn) {\n return fallbackQueryFn({ queryKey, signal })\n }\n throw new Error(\n `[DemoKit] No fixture found for query key: ${JSON.stringify(queryKey)}`\n )\n }\n\n const [handler, { params }] = match\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n if (typeof handler === 'function') {\n return handler({\n queryKey: queryKey as unknown[],\n params,\n match: { matched: true, params },\n signal,\n })\n }\n\n // Return static value\n return handler\n }\n}\n\n/**\n * Create a demo-aware QueryClient\n *\n * This creates a QueryClient configured to intercept queries when demo mode\n * is enabled and return fixture data instead of making real API calls.\n *\n * @example\n * const { client, enable, disable, isEnabled } = createDemoQueryClient({\n * queries: {\n * '[\"users\"]': [{ id: '1', name: 'Demo User' }],\n * '[\"users\", \":id\"]': ({ params }) => ({ id: params.id, name: 'Demo User' }),\n * },\n * delay: 100, // Simulate 100ms latency\n * })\n *\n * // Use with QueryClientProvider\n * <QueryClientProvider client={client}>\n * <App />\n * </QueryClientProvider>\n */\nexport function createDemoQueryClient(config: DemoQueryClientConfig = {}) {\n const {\n queries = new Map(),\n delay = 0,\n staleTime = Infinity,\n fallbackQueryFn,\n queryClientConfig = {},\n prepopulateCache = false,\n } = config\n\n let enabled = config.enabled ?? false\n const fixtures = normalizeFixtureMap(queries)\n\n const isEnabled = () => enabled\n\n const demoQueryFn = createDemoQueryFn({\n fixtures,\n delay,\n fallbackQueryFn,\n isEnabled,\n })\n\n const client = new QueryClient({\n ...queryClientConfig,\n defaultOptions: {\n ...queryClientConfig.defaultOptions,\n queries: {\n ...queryClientConfig.defaultOptions?.queries,\n queryFn: demoQueryFn,\n staleTime: enabled ? staleTime : queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: enabled ? false : queryClientConfig.defaultOptions?.queries?.retry,\n },\n },\n })\n\n // Pre-populate cache if configured\n const prepopulate = () => {\n if (!prepopulateCache || !enabled) return\n\n for (const [pattern, handler] of fixtures) {\n // Only pre-populate static values (not functions)\n if (typeof handler !== 'function') {\n // Use pattern as query key for static fixtures\n client.setQueryData(pattern, handler)\n }\n }\n }\n\n return {\n /**\n * The QueryClient instance\n */\n client,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime,\n retry: false,\n },\n })\n prepopulate()\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n client.setDefaultOptions({\n ...client.getDefaultOptions(),\n queries: {\n ...client.getDefaultOptions().queries,\n staleTime: queryClientConfig.defaultOptions?.queries?.staleTime,\n retry: queryClientConfig.defaultOptions?.queries?.retry,\n },\n })\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled,\n\n /**\n * Get the fixture map\n */\n getFixtures: () => fixtures,\n\n /**\n * Add or update a fixture\n */\n setFixture: (pattern: QueryKey, handler: QueryFixtureHandler) => {\n fixtures.set(pattern, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (pattern: QueryKey) => {\n fixtures.delete(pattern)\n },\n\n /**\n * Clear all query cache\n */\n clearCache: () => {\n client.clear()\n },\n\n /**\n * Invalidate all queries\n */\n invalidateAll: () => {\n client.invalidateQueries()\n },\n }\n}\n\nexport type DemoQueryClient = ReturnType<typeof createDemoQueryClient>\n","import { matchQueryKey, findMatchingQueryKeyPattern } from '@demokit-ai/core'\nimport type { QueryKey } from '@demokit-ai/core'\nimport type { QueryKey as TanStackQueryKey } from '@tanstack/react-query'\nimport type { QueryFixtureHandler, QueryFixtureMap, QueryFixtureMapObject } from './types'\n\n/**\n * Convert TanStack Query key to DemoKit QueryKey\n * TanStack Query keys can contain any value, so we normalize them\n */\nexport function normalizeQueryKey(queryKey: TanStackQueryKey): QueryKey {\n return queryKey.map((element) => {\n if (element === null || element === undefined) {\n return element\n }\n if (typeof element === 'object') {\n // Keep objects as-is for matching\n return element as Record<string, unknown>\n }\n // Primitives are kept as-is\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('[\"users\"]') // ['users']\n * parsePatternString('[\"users\", \":id\"]') // ['users', ':id']\n * parsePatternString('users') // ['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: QueryFixtureMapObject | QueryFixtureMap): QueryFixtureMap {\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const map = new Map<QueryKey, QueryFixtureHandler>()\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 a query key\n *\n * @param fixtures - Map of query key patterns to handlers\n * @param queryKey - The query key to match\n * @returns Tuple of [handler, match result] or null if no match\n */\nexport function findMatchingFixture(\n fixtures: QueryFixtureMap,\n queryKey: TanStackQueryKey\n): [QueryFixtureHandler, { params: Record<string, unknown> }] | null {\n const normalizedKey = normalizeQueryKey(queryKey)\n const result = findMatchingQueryKeyPattern(fixtures, normalizedKey)\n\n if (result) {\n const [, handler, matchResult] = result\n return [handler, { params: matchResult.params }]\n }\n\n return null\n}\n\n/**\n * Re-export the matchQueryKey function for direct use\n */\nexport { matchQueryKey }\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/tanstack-query'\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 * <DemoQueryProvider source={demokitSource}>\n * <QueryClientProvider client={queryClient}>\n * <App />\n * </QueryClientProvider>\n * </DemoQueryProvider>\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 } from 'react'\nimport { DemoQueryContext } from './context'\nimport type { DemoQueryState } from './types'\n\n/**\n * Hook to access DemoQuery state and controls\n *\n * @returns DemoQuery context value\n * @throws Error if used outside of DemoQueryProvider\n *\n * @example\n * function MyComponent() {\n * const { isDemoMode, setQueryFixture, invalidateAll } = useDemoQuery()\n *\n * // Dynamically add a fixture\n * const handleAddFixture = () => {\n * setQueryFixture(['users', 'custom'], { id: 'custom', name: 'Custom User' })\n * invalidateAll() // Trigger refetch\n * }\n *\n * return (\n * <button onClick={handleAddFixture}>Add Custom Fixture</button>\n * )\n * }\n */\nexport function useDemoQuery(): DemoQueryState {\n const context = useContext(DemoQueryContext)\n\n if (context === undefined) {\n throw new Error(\n 'useDemoQuery must be used within a DemoQueryProvider. ' +\n 'Make sure to wrap your app with <DemoQueryProvider>.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to check if demo mode is enabled\n * Shorthand for useDemoQuery().isDemoMode\n *\n * @example\n * function MyComponent() {\n * const isDemoMode = useIsDemoQueryMode()\n *\n * return isDemoMode ? <DemoBadge /> : null\n * }\n */\nexport function useIsDemoQueryMode(): boolean {\n return useDemoQuery().isDemoMode\n}\n","'use client'\n\nimport { useMutation, useQueryClient, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport type { MutationFixtureContext, MutationFixtureHandler } from './types'\nimport { useDemoQuery } from './hooks'\n\n/**\n * Options for useDemoMutation hook\n */\nexport interface UseDemoMutationOptions<TData, TError, TVariables, TContext>\n extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {\n /**\n * The real mutation function to use when demo mode is disabled\n */\n mutationFn: (variables: TVariables) => Promise<TData>\n\n /**\n * Name used to look up the demo fixture\n * If not provided, uses mutationKey as string\n */\n demoName?: string\n\n /**\n * Demo fixture handler for this mutation\n * If provided, overrides the fixture from DemoQueryProvider\n */\n demoFixture?: MutationFixtureHandler<TData, TVariables>\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 * @example\n * const createUser = useDemoMutation({\n * mutationFn: async (data) => api.createUser(data),\n * demoName: 'createUser',\n * demoFixture: ({ variables, queryClient }) => {\n * // Create demo user\n * const newUser = { id: crypto.randomUUID(), ...variables }\n *\n * // Update the users query cache\n * queryClient.setQueryData(['users'], (old: User[] = []) => [...old, newUser])\n *\n * return newUser\n * },\n * onSuccess: (data) => {\n * console.log('Created user:', data)\n * },\n * })\n *\n * // Use like normal useMutation\n * createUser.mutate({ name: 'New User', email: 'user@example.com' })\n */\nexport function useDemoMutation<\n TData = unknown,\n TError = unknown,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseDemoMutationOptions<TData, TError, TVariables, TContext>\n): UseMutationResult<TData, TError, TVariables, TContext> {\n const { mutationFn, demoName, demoFixture, demoDelay = 0, ...mutationOptions } = options\n\n const queryClient = useQueryClient()\n\n // Try to get demo state - may not be in DemoQueryProvider context\n let isDemoMode = false\n try {\n const demoState = useDemoQuery()\n isDemoMode = demoState.isDemoMode\n } catch {\n // Not in DemoQueryProvider context, use real mutation\n }\n\n // Create the demo-aware mutation function\n const demoAwareMutationFn = useCallback(\n async (variables: TVariables): Promise<TData> => {\n // If not in demo mode, use real mutation\n if (!isDemoMode) {\n return mutationFn(variables)\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: MutationFixtureContext<TVariables> = {\n mutationKey: mutationOptions.mutationKey,\n variables,\n queryClient,\n }\n\n if (typeof demoFixture === 'function') {\n // Cast to the function type to help TypeScript understand\n const fixtureFn = demoFixture as (context: MutationFixtureContext<TVariables>) => 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] No mutation fixture found for \"${demoName || mutationOptions.mutationKey?.join('/') || 'unknown'}\". ` +\n 'Using real mutation function.'\n )\n return mutationFn(variables)\n },\n [isDemoMode, mutationFn, demoFixture, demoDelay, demoName, mutationOptions.mutationKey, queryClient]\n )\n\n return useMutation({\n ...mutationOptions,\n mutationFn: demoAwareMutationFn,\n })\n}\n\n/**\n * Create a set of demo mutations with fixtures\n *\n * @example\n * const mutations = createDemoMutations({\n * createUser: {\n * mutationFn: api.createUser,\n * fixture: ({ variables, queryClient }) => {\n * const newUser = { id: 'demo-1', ...variables }\n * queryClient.setQueryData(['users'], (old = []) => [...old, newUser])\n * return newUser\n * },\n * },\n * deleteUser: {\n * mutationFn: api.deleteUser,\n * fixture: ({ variables, queryClient }) => {\n * queryClient.setQueryData(['users'], (old: User[] = []) =>\n * old.filter(u => u.id !== variables.id)\n * )\n * return { success: true }\n * },\n * },\n * })\n *\n * // Use in components\n * const { createUser, deleteUser } = mutations\n */\nexport type DemoMutationConfig<TData, TVariables> = {\n mutationFn: (variables: TVariables) => Promise<TData>\n fixture: MutationFixtureHandler<TData, TVariables>\n delay?: number\n}\n\n/**\n * Helper to create mutation options with demo fixture\n */\nexport function createMutationOptions<TData, TVariables>(\n config: DemoMutationConfig<TData, TVariables>\n): Pick<UseDemoMutationOptions<TData, unknown, TVariables, unknown>, 'mutationFn' | 'demoFixture' | 'demoDelay'> {\n return {\n mutationFn: config.mutationFn,\n demoFixture: config.fixture,\n demoDelay: config.delay,\n }\n}\n"],"mappings":"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","names":["useQueryClient","useQueryClient"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demokit-ai/tanstack-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "TanStack Query integration for DemoKit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -22,18 +22,19 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@demokit-ai/
|
|
26
|
-
"@demokit-ai/
|
|
25
|
+
"@demokit-ai/core": "0.4.2",
|
|
26
|
+
"@demokit-ai/react": "0.4.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@tanstack/react-query": "^5.
|
|
30
|
-
"@types/
|
|
31
|
-
"
|
|
32
|
-
"
|
|
29
|
+
"@tanstack/react-query": "^5.95.2",
|
|
30
|
+
"@types/node": "^22.0.0",
|
|
31
|
+
"@types/react": "^19.2.14",
|
|
32
|
+
"tsup": "^8.5.1",
|
|
33
|
+
"typescript": "^6.0.2"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
|
35
36
|
"@tanstack/react-query": ">=5.0.0",
|
|
36
|
-
"react": ">=
|
|
37
|
+
"react": ">=18.0.0"
|
|
37
38
|
},
|
|
38
39
|
"engines": {
|
|
39
40
|
"node": ">=18"
|