@demokit-ai/trpc 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.
@@ -164,6 +164,38 @@ interface DemoTRPCState {
164
164
  */
165
165
  getFixtures: () => FlatFixtureMap;
166
166
  }
167
+ /**
168
+ * Configuration for remote fixture source (DemoKit Cloud)
169
+ */
170
+ interface RemoteSourceConfig {
171
+ /**
172
+ * DemoKit Cloud API URL (versioned base URL)
173
+ * The SDK will append `/fixtures` to this URL.
174
+ * @example 'https://demokit-cloud.kasava.dev/api'
175
+ * @default 'https://api.demokit.cloud/api'
176
+ */
177
+ apiUrl: string;
178
+ /**
179
+ * DemoKit Cloud API key
180
+ * Format: dk_live_xxx
181
+ */
182
+ apiKey: string;
183
+ /**
184
+ * Request timeout in milliseconds
185
+ * @default 10000
186
+ */
187
+ timeout?: number;
188
+ /**
189
+ * Whether to retry failed requests
190
+ * @default true
191
+ */
192
+ retry?: boolean;
193
+ /**
194
+ * Maximum number of retries
195
+ * @default 3
196
+ */
197
+ maxRetries?: number;
198
+ }
167
199
 
168
200
  /**
169
201
  * Create a demo-aware tRPC link
@@ -366,4 +398,4 @@ declare function createFixtureHandler<TInput, TOutput>(handler: TRPCFixtureHandl
366
398
  */
367
399
  declare function normalizeFixtures(fixtures: Record<string, unknown> | FlatFixtureMap | undefined): FlatFixtureMap;
368
400
 
369
- export { type CreateDemoLinkOptions as C, type DemoLinkWithState as D, type FlatFixtureMap as F, type NestedFixtures as N, type RouterInputs as R, type TRPCFixtureContext as T, type FixtureMatchResult as a, createDemoLinkWithState as b, createDemoLink as c, defineTRPCFixtures as d, defineFixtureMap as e, createFixtureHandler as f, type TRPCFixtureHandler as g, type RouterOutputs as h, type FlatFixtureMapObject as i, type DemoTRPCProviderConfig as j, type DemoTRPCProviderProps as k, type DemoTRPCState as l, normalizeFixtures as n };
401
+ export { type CreateDemoLinkOptions as C, type DemoLinkWithState as D, type FlatFixtureMap as F, type NestedFixtures as N, type RemoteSourceConfig as R, type TRPCFixtureContext as T, type FixtureMatchResult as a, createDemoLinkWithState as b, createDemoLink as c, defineTRPCFixtures as d, defineFixtureMap as e, createFixtureHandler as f, type TRPCFixtureHandler as g, type RouterInputs as h, type RouterOutputs as i, type FlatFixtureMapObject as j, type DemoTRPCProviderConfig as k, type DemoTRPCProviderProps as l, type DemoTRPCState as m, normalizeFixtures as n };
@@ -164,6 +164,38 @@ interface DemoTRPCState {
164
164
  */
165
165
  getFixtures: () => FlatFixtureMap;
166
166
  }
167
+ /**
168
+ * Configuration for remote fixture source (DemoKit Cloud)
169
+ */
170
+ interface RemoteSourceConfig {
171
+ /**
172
+ * DemoKit Cloud API URL (versioned base URL)
173
+ * The SDK will append `/fixtures` to this URL.
174
+ * @example 'https://demokit-cloud.kasava.dev/api'
175
+ * @default 'https://api.demokit.cloud/api'
176
+ */
177
+ apiUrl: string;
178
+ /**
179
+ * DemoKit Cloud API key
180
+ * Format: dk_live_xxx
181
+ */
182
+ apiKey: string;
183
+ /**
184
+ * Request timeout in milliseconds
185
+ * @default 10000
186
+ */
187
+ timeout?: number;
188
+ /**
189
+ * Whether to retry failed requests
190
+ * @default true
191
+ */
192
+ retry?: boolean;
193
+ /**
194
+ * Maximum number of retries
195
+ * @default 3
196
+ */
197
+ maxRetries?: number;
198
+ }
167
199
 
168
200
  /**
169
201
  * Create a demo-aware tRPC link
@@ -366,4 +398,4 @@ declare function createFixtureHandler<TInput, TOutput>(handler: TRPCFixtureHandl
366
398
  */
367
399
  declare function normalizeFixtures(fixtures: Record<string, unknown> | FlatFixtureMap | undefined): FlatFixtureMap;
368
400
 
369
- export { type CreateDemoLinkOptions as C, type DemoLinkWithState as D, type FlatFixtureMap as F, type NestedFixtures as N, type RouterInputs as R, type TRPCFixtureContext as T, type FixtureMatchResult as a, createDemoLinkWithState as b, createDemoLink as c, defineTRPCFixtures as d, defineFixtureMap as e, createFixtureHandler as f, type TRPCFixtureHandler as g, type RouterOutputs as h, type FlatFixtureMapObject as i, type DemoTRPCProviderConfig as j, type DemoTRPCProviderProps as k, type DemoTRPCState as l, normalizeFixtures as n };
401
+ export { type CreateDemoLinkOptions as C, type DemoLinkWithState as D, type FlatFixtureMap as F, type NestedFixtures as N, type RemoteSourceConfig as R, type TRPCFixtureContext as T, type FixtureMatchResult as a, createDemoLinkWithState as b, createDemoLink as c, defineTRPCFixtures as d, defineFixtureMap as e, createFixtureHandler as f, type TRPCFixtureHandler as g, type RouterInputs as h, type RouterOutputs as i, type FlatFixtureMapObject as j, type DemoTRPCProviderConfig as k, type DemoTRPCProviderProps as l, type DemoTRPCState as m, normalizeFixtures as n };
package/dist/index.cjs CHANGED
@@ -23,6 +23,7 @@ __export(src_exports, {
23
23
  createDemoLink: () => createDemoLink,
24
24
  createDemoLinkWithState: () => createDemoLinkWithState,
25
25
  createFixtureHandler: () => createFixtureHandler,
26
+ createRemoteSource: () => createRemoteSource,
26
27
  defineFixtureMap: () => defineFixtureMap,
27
28
  defineTRPCFixtures: () => defineTRPCFixtures,
28
29
  filterFixtures: () => filterFixtures,
@@ -298,11 +299,22 @@ function createDemoLinkWithState(options = {}) {
298
299
  }
299
300
  };
300
301
  }
302
+
303
+ // src/config.ts
304
+ function createRemoteSource(config) {
305
+ return {
306
+ timeout: 1e4,
307
+ retry: true,
308
+ maxRetries: 3,
309
+ ...config
310
+ };
311
+ }
301
312
  // Annotate the CommonJS export names for ESM import in node:
302
313
  0 && (module.exports = {
303
314
  createDemoLink,
304
315
  createDemoLinkWithState,
305
316
  createFixtureHandler,
317
+ createRemoteSource,
306
318
  defineFixtureMap,
307
319
  defineTRPCFixtures,
308
320
  filterFixtures,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/link.ts","../src/fixtures.ts","../src/matcher.ts"],"sourcesContent":["/**\n * @demokit-ai/trpc\n *\n * Type-safe tRPC v11 adapter for DemoKit.\n * Mock tRPC procedures with full type inference from your router.\n *\n * @example\n * // Define type-safe fixtures\n * import { defineTRPCFixtures } from '@demokit-ai/trpc'\n * import type { AppRouter } from '../server/router'\n *\n * const fixtures = defineTRPCFixtures<AppRouter>()({\n * user: {\n * list: () => [\n * { id: '1', name: 'Demo User', email: 'demo@example.com' }\n * ],\n * get: ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * email: 'demo@example.com',\n * }),\n * create: async ({ input }) => ({\n * id: crypto.randomUUID(),\n * ...input,\n * createdAt: new Date(),\n * }),\n * },\n * })\n *\n * @example\n * // Create tRPC client with demo link\n * import { createTRPCClient, httpBatchLink } from '@trpc/client'\n * import { createDemoLink } from '@demokit-ai/trpc'\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [\n * createDemoLink({\n * fixtures,\n * isEnabled: () => localStorage.getItem('demoMode') === 'true',\n * delay: 100, // Simulate 100ms latency\n * }),\n * httpBatchLink({ url: '/api/trpc' }),\n * ],\n * })\n *\n * @example\n * // With state management\n * import { createDemoLinkWithState } from '@demokit-ai/trpc'\n *\n * const { link, enable, disable, setFixture } = createDemoLinkWithState({\n * fixtures,\n * enabled: false,\n * })\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [link, httpBatchLink({ url: '/api/trpc' })],\n * })\n *\n * // Toggle demo mode at runtime\n * enable()\n * disable()\n *\n * // Add fixtures at runtime\n * setFixture('analytics.overview', () => ({ visits: 1000 }))\n *\n * @packageDocumentation\n */\n\n// Link factory\nexport { createDemoLink, createDemoLinkWithState } from './link'\nexport type { DemoLinkWithState } from './link'\n\n// Fixture definition helpers\nexport { defineTRPCFixtures, defineFixtureMap, createFixtureHandler, normalizeFixtures } from './fixtures'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n shouldIntercept,\n matchPath,\n filterFixtures,\n getFixturePaths,\n mergeFixtures,\n} from './matcher'\n\n// Types\nexport type {\n TRPCFixtureContext,\n TRPCFixtureHandler,\n RouterInputs,\n RouterOutputs,\n NestedFixtures,\n FlatFixtureMap,\n FlatFixtureMapObject,\n CreateDemoLinkOptions,\n FixtureMatchResult,\n DemoTRPCProviderConfig,\n DemoTRPCProviderProps,\n DemoTRPCState,\n} from './types'\n","import type { TRPCLink, Operation } from '@trpc/client'\nimport { observable } from '@trpc/server/observable'\nimport type { AnyRouter } from '@trpc/server'\nimport type {\n CreateDemoLinkOptions,\n TRPCFixtureContext,\n TRPCFixtureHandler,\n FlatFixtureMap,\n} from './types'\nimport { normalizeFixtures } from './fixtures'\nimport { findMatchingFixture, shouldIntercept } from './matcher'\n\n/**\n * Create a demo-aware tRPC link\n *\n * This link intercepts tRPC procedure calls when demo mode is enabled\n * and returns fixture data instead of making real API calls.\n *\n * The demo link should be placed before the terminating link (like httpBatchLink)\n * in your link chain.\n *\n * @example\n * import { createTRPCClient, httpBatchLink } from '@trpc/client'\n * import { createDemoLink } from '@demokit-ai/trpc'\n *\n * // Simple usage with fixtures\n * const client = createTRPCClient<AppRouter>({\n * links: [\n * createDemoLink({\n * fixtures: {\n * user: {\n * list: () => [{ id: '1', name: 'Demo User' }],\n * get: ({ input }) => ({ id: input.id, name: 'Demo User' }),\n * },\n * },\n * isEnabled: () => localStorage.getItem('demoMode') === 'true',\n * }),\n * httpBatchLink({ url: '/api/trpc' }),\n * ],\n * })\n *\n * @example\n * // With include/exclude filtering\n * createDemoLink({\n * fixtures: myFixtures,\n * include: ['user.*', 'post.list'], // Only intercept user.* and post.list\n * exclude: ['user.delete'], // Never intercept user.delete\n * delay: 200, // Simulate 200ms network latency\n * onMissing: (path, input) => {\n * console.warn(`No fixture for: ${path}`)\n * },\n * })\n */\nexport function createDemoLink<TRouter extends AnyRouter = AnyRouter>(\n options: CreateDemoLinkOptions<TRouter> = {}\n): TRPCLink<TRouter> {\n const {\n fixtures: rawFixtures,\n isEnabled = () => false,\n delay = 0,\n include,\n exclude,\n onMissing,\n } = options\n\n // Normalize fixtures to flat map on initialization\n const fixtures: FlatFixtureMap = normalizeFixtures(rawFixtures as Record<string, unknown>)\n\n // Return the link factory function\n return () => {\n // Return the link function that handles each operation\n return ({ next, op }) => {\n return observable((observer) => {\n // Check if demo mode is enabled\n if (!isEnabled()) {\n // Forward to next link\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Check if this procedure should be intercepted\n if (!shouldIntercept(op.path, include, exclude)) {\n // Forward to next link\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, op.path)\n\n if (!match.matched || !match.handler) {\n // No fixture found\n onMissing?.(op.path, op.input)\n\n // Forward to next link as fallback\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Execute fixture handler\n const executeFixture = async () => {\n const context: TRPCFixtureContext = {\n path: op.path,\n input: op.input,\n type: op.type,\n }\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n const handler = match.handler as TRPCFixtureHandler\n const result = typeof handler === 'function' ? await handler(context) : handler\n\n return result\n }\n\n // Handle async execution\n executeFixture()\n .then((data) => {\n observer.next({\n result: { data },\n })\n observer.complete()\n })\n .catch((err) => {\n observer.error(err)\n })\n\n // Return cleanup function (no-op for demo fixtures)\n return () => {}\n })\n }\n }\n}\n\n/**\n * Create a demo link with state management\n *\n * Returns the link along with controls to enable/disable demo mode\n * and manage fixtures at runtime.\n *\n * @example\n * const { link, enable, disable, isEnabled, setFixture, removeFixture } =\n * createDemoLinkWithState({\n * fixtures: myFixtures,\n * })\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [link, httpBatchLink({ url: '/api/trpc' })],\n * })\n *\n * // Later...\n * enable() // Turn on demo mode\n * disable() // Turn off demo mode\n *\n * // Add fixture at runtime\n * setFixture('user.get', ({ input }) => ({ id: input.id, name: 'Runtime User' }))\n */\nexport function createDemoLinkWithState<TRouter extends AnyRouter = AnyRouter>(\n options: Omit<CreateDemoLinkOptions<TRouter>, 'isEnabled'> & {\n /**\n * Initial enabled state\n * @default false\n */\n enabled?: boolean\n } = {}\n) {\n const { fixtures: rawFixtures, enabled: initialEnabled = false, ...rest } = options\n\n let enabled = initialEnabled\n const fixtures: FlatFixtureMap = normalizeFixtures(rawFixtures as Record<string, unknown>)\n\n const link = createDemoLink<TRouter>({\n ...rest,\n fixtures,\n isEnabled: () => enabled,\n })\n\n return {\n /**\n * The tRPC link to use in your client\n */\n link,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled: () => enabled,\n\n /**\n * Toggle demo mode\n */\n toggle: () => {\n enabled = !enabled\n return enabled\n },\n\n /**\n * Set or update a fixture\n */\n setFixture: (path: string, handler: TRPCFixtureHandler) => {\n fixtures.set(path, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (path: string) => {\n fixtures.delete(path)\n },\n\n /**\n * Get all fixtures\n */\n getFixtures: () => fixtures,\n\n /**\n * Clear all fixtures\n */\n clearFixtures: () => {\n fixtures.clear()\n },\n }\n}\n\nexport type DemoLinkWithState<TRouter extends AnyRouter = AnyRouter> = ReturnType<\n typeof createDemoLinkWithState<TRouter>\n>\n","import type {\n AnyRouter,\n inferRouterInputs,\n inferRouterOutputs,\n} from '@trpc/server'\nimport type { TRPCFixtureHandler, TRPCFixtureContext, FlatFixtureMap } from './types'\n\n/**\n * Type helper to create fixture handlers with full type inference\n *\n * This helper infers input/output types from your router definition,\n * providing autocomplete and type checking for fixture definitions.\n *\n * @example\n * import { defineTRPCFixtures } from '@demokit-ai/trpc'\n * import type { AppRouter } from '../server/router'\n *\n * // Nested structure matching your router\n * const fixtures = defineTRPCFixtures<AppRouter>()({\n * user: {\n * list: () => [\n * { id: '1', name: 'Demo User', email: 'demo@example.com' }\n * ],\n * get: ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * email: 'demo@example.com',\n * }),\n * create: async ({ input }) => ({\n * id: crypto.randomUUID(),\n * ...input,\n * createdAt: new Date(),\n * }),\n * },\n * post: {\n * list: () => [],\n * },\n * })\n */\nexport function defineTRPCFixtures<TRouter extends AnyRouter>() {\n type RouterIn = inferRouterInputs<TRouter>\n type RouterOut = inferRouterOutputs<TRouter>\n\n /**\n * Helper type to build nested fixture structure\n */\n type BuildFixtureType<TIn, TOut> = {\n [K in keyof TIn & keyof TOut]?: TIn[K] extends object\n ? TOut[K] extends object\n ? // Check if this is a procedure (has no nested keys) or a namespace\n keyof TIn[K] extends never\n ? TRPCFixtureHandler<TIn[K], TOut[K]>\n : BuildFixtureType<TIn[K], TOut[K]>\n : TRPCFixtureHandler<TIn[K], TOut[K]>\n : TRPCFixtureHandler<TIn[K], TOut[K]>\n }\n\n return function <T extends BuildFixtureType<RouterIn, RouterOut>>(fixtures: T): T {\n return fixtures\n }\n}\n\n/**\n * Alternative: define fixtures using flat dot-notation paths\n *\n * Useful when you want to define fixtures independently of router structure.\n *\n * @example\n * const fixtures = defineFixtureMap<AppRouter>({\n * 'user.list': () => [{ id: '1', name: 'Demo' }],\n * 'user.get': ({ input }) => ({ id: input.id, name: 'Demo' }),\n * })\n */\nexport function defineFixtureMap<TRouter extends AnyRouter>(\n fixtures: FlatFixtureRecord<TRouter>\n): FlatFixtureMap {\n return new Map(Object.entries(fixtures))\n}\n\n/**\n * Type for flat fixture map with path-based keys\n */\ntype FlatFixtureRecord<TRouter extends AnyRouter> = {\n [K in ProcedurePaths<TRouter>]?: TRPCFixtureHandler<\n PathInput<TRouter, K>,\n PathOutput<TRouter, K>\n >\n}\n\n/**\n * Extract all procedure paths from a router using dot notation\n */\ntype ProcedurePaths<TRouter extends AnyRouter> = inferRouterInputs<TRouter> extends infer TIn\n ? TIn extends object\n ? FlattenPaths<TIn>\n : never\n : never\n\n/**\n * Flatten nested object keys to dot notation\n */\ntype FlattenPaths<T, Prefix extends string = ''> = T extends object\n ? {\n [K in keyof T]: K extends string\n ? T[K] extends object\n ? keyof T[K] extends never\n ? `${Prefix}${K}`\n : FlattenPaths<T[K], `${Prefix}${K}.`>\n : `${Prefix}${K}`\n : never\n }[keyof T]\n : never\n\n/**\n * Get input type for a specific procedure path\n */\ntype PathInput<TRouter extends AnyRouter, Path extends string> = Path extends `${infer First}.${infer Rest}`\n ? inferRouterInputs<TRouter>[First] extends object\n ? PathInput<inferRouterInputs<TRouter>[First] extends AnyRouter ? inferRouterInputs<TRouter>[First] : never, Rest>\n : never\n : inferRouterInputs<TRouter>[Path]\n\n/**\n * Get output type for a specific procedure path\n */\ntype PathOutput<TRouter extends AnyRouter, Path extends string> = Path extends `${infer First}.${infer Rest}`\n ? inferRouterOutputs<TRouter>[First] extends object\n ? PathOutput<inferRouterOutputs<TRouter>[First] extends AnyRouter ? inferRouterOutputs<TRouter>[First] : never, Rest>\n : never\n : inferRouterOutputs<TRouter>[Path]\n\n/**\n * Create a fixture handler with explicit types\n *\n * Useful when you need to define a fixture outside of the main fixture object.\n *\n * @example\n * const getUserFixture = createFixtureHandler<{ id: string }, User>(\n * ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * })\n * )\n */\nexport function createFixtureHandler<TInput, TOutput>(\n handler: TRPCFixtureHandler<TInput, TOutput>\n): TRPCFixtureHandler<TInput, TOutput> {\n return handler\n}\n\n/**\n * Normalize fixture definitions to a flat Map\n *\n * Converts nested fixture objects to a flat map with dot-notation paths.\n */\nexport function normalizeFixtures(\n fixtures: Record<string, unknown> | FlatFixtureMap | undefined\n): FlatFixtureMap {\n if (!fixtures) {\n return new Map()\n }\n\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const result: FlatFixtureMap = new Map()\n\n function flatten(obj: Record<string, unknown>, prefix = '') {\n for (const [key, value] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${key}` : key\n\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof value !== 'function'\n ) {\n // Check if this looks like a fixture handler or a namespace\n // Fixture handlers are either primitives, arrays, or functions\n // Namespaces are objects with nested procedures\n const hasNestedProcedures = Object.values(value).some(\n (v) => typeof v === 'function' || Array.isArray(v) || (typeof v === 'object' && v !== null)\n )\n\n if (hasNestedProcedures) {\n flatten(value as Record<string, unknown>, path)\n } else {\n // This is a static fixture value (an object)\n result.set(path, value as TRPCFixtureHandler)\n }\n } else {\n // This is a fixture handler (function, array, or primitive)\n result.set(path, value as TRPCFixtureHandler)\n }\n }\n }\n\n flatten(fixtures as Record<string, unknown>)\n return result\n}\n","import type { FlatFixtureMap, TRPCFixtureHandler, FixtureMatchResult } from './types'\n\n/**\n * Find a matching fixture for a procedure path\n *\n * @param fixtures - Map of procedure paths to fixture handlers\n * @param path - The procedure path to match (e.g., 'user.get', 'post.list')\n * @returns Match result with handler if found\n *\n * @example\n * const fixtures = new Map([\n * ['user.list', () => []],\n * ['user.get', ({ input }) => ({ id: input.id })],\n * ])\n *\n * findMatchingFixture(fixtures, 'user.get')\n * // { matched: true, handler: Function, path: 'user.get' }\n *\n * findMatchingFixture(fixtures, 'unknown.path')\n * // { matched: false, path: 'unknown.path' }\n */\nexport function findMatchingFixture<TOutput = unknown>(\n fixtures: FlatFixtureMap,\n path: string\n): FixtureMatchResult<TOutput> {\n const handler = fixtures.get(path)\n\n if (handler !== undefined) {\n return {\n matched: true,\n handler: handler as TRPCFixtureHandler<unknown, TOutput>,\n path,\n }\n }\n\n return {\n matched: false,\n path,\n }\n}\n\n/**\n * Check if a procedure path should be intercepted based on include/exclude rules\n *\n * @param path - The procedure path to check\n * @param include - Optional list of paths to include (if provided, only these are intercepted)\n * @param exclude - Optional list of paths to exclude (takes precedence over include)\n * @returns Whether the path should be intercepted\n *\n * @example\n * // Include only specific paths\n * shouldIntercept('user.get', ['user.get', 'user.list'], [])\n * // true\n *\n * shouldIntercept('post.list', ['user.get', 'user.list'], [])\n * // false\n *\n * // Exclude takes precedence\n * shouldIntercept('user.get', ['user.get'], ['user.get'])\n * // false\n */\nexport function shouldIntercept(\n path: string,\n include?: string[],\n exclude?: string[]\n): boolean {\n // Exclude takes precedence\n if (exclude?.includes(path)) {\n return false\n }\n\n // If include list is provided, only intercept those\n if (include && include.length > 0) {\n return include.includes(path)\n }\n\n // By default, intercept all\n return true\n}\n\n/**\n * Check if a procedure path matches a pattern with wildcards\n *\n * Supports:\n * - Exact match: 'user.get' matches 'user.get'\n * - Wildcard suffix: 'user.*' matches 'user.get', 'user.list', etc.\n * - Wildcard prefix: '*.get' matches 'user.get', 'post.get', etc.\n * - Full wildcard: '*' matches everything\n *\n * @param path - The procedure path to check\n * @param pattern - The pattern to match against\n * @returns Whether the path matches the pattern\n *\n * @example\n * matchPath('user.get', 'user.get') // true\n * matchPath('user.get', 'user.*') // true\n * matchPath('user.get', '*.get') // true\n * matchPath('user.get', '*') // true\n * matchPath('user.get', 'post.*') // false\n */\nexport function matchPath(path: string, pattern: string): boolean {\n if (pattern === '*') {\n return true\n }\n\n if (pattern === path) {\n return true\n }\n\n // Handle wildcard patterns\n if (pattern.includes('*')) {\n const regex = new RegExp(\n '^' +\n pattern\n .split('*')\n .map((s) => escapeRegex(s))\n .join('.*') +\n '$'\n )\n return regex.test(path)\n }\n\n return false\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Filter fixtures based on include/exclude patterns\n *\n * @param fixtures - The fixture map to filter\n * @param include - Patterns to include (supports wildcards)\n * @param exclude - Patterns to exclude (takes precedence, supports wildcards)\n * @returns A new fixture map with only matching fixtures\n */\nexport function filterFixtures(\n fixtures: FlatFixtureMap,\n include?: string[],\n exclude?: string[]\n): FlatFixtureMap {\n const result: FlatFixtureMap = new Map()\n\n for (const [path, handler] of fixtures) {\n // Check if path should be included\n let shouldInclude = true\n\n if (include && include.length > 0) {\n shouldInclude = include.some((pattern) => matchPath(path, pattern))\n }\n\n // Check if path should be excluded\n if (exclude && exclude.length > 0) {\n if (exclude.some((pattern) => matchPath(path, pattern))) {\n shouldInclude = false\n }\n }\n\n if (shouldInclude) {\n result.set(path, handler)\n }\n }\n\n return result\n}\n\n/**\n * Get all procedure paths from a fixture map\n *\n * @param fixtures - The fixture map\n * @returns Array of all procedure paths\n */\nexport function getFixturePaths(fixtures: FlatFixtureMap): string[] {\n return Array.from(fixtures.keys())\n}\n\n/**\n * Merge multiple fixture maps\n *\n * Later maps take precedence over earlier ones for the same path.\n *\n * @param maps - Fixture maps to merge\n * @returns Merged fixture map\n */\nexport function mergeFixtures(...maps: FlatFixtureMap[]): FlatFixtureMap {\n const result: FlatFixtureMap = new Map()\n\n for (const map of maps) {\n for (const [path, handler] of map) {\n result.set(path, handler)\n }\n }\n\n return result\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/link.ts","../src/fixtures.ts","../src/matcher.ts","../src/config.ts"],"sourcesContent":["/**\n * @demokit-ai/trpc\n *\n * Type-safe tRPC v11 adapter for DemoKit.\n * Mock tRPC procedures with full type inference from your router.\n *\n * @example\n * // Define type-safe fixtures\n * import { defineTRPCFixtures } from '@demokit-ai/trpc'\n * import type { AppRouter } from '../server/router'\n *\n * const fixtures = defineTRPCFixtures<AppRouter>()({\n * user: {\n * list: () => [\n * { id: '1', name: 'Demo User', email: 'demo@example.com' }\n * ],\n * get: ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * email: 'demo@example.com',\n * }),\n * create: async ({ input }) => ({\n * id: crypto.randomUUID(),\n * ...input,\n * createdAt: new Date(),\n * }),\n * },\n * })\n *\n * @example\n * // Create tRPC client with demo link\n * import { createTRPCClient, httpBatchLink } from '@trpc/client'\n * import { createDemoLink } from '@demokit-ai/trpc'\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [\n * createDemoLink({\n * fixtures,\n * isEnabled: () => localStorage.getItem('demoMode') === 'true',\n * delay: 100, // Simulate 100ms latency\n * }),\n * httpBatchLink({ url: '/api/trpc' }),\n * ],\n * })\n *\n * @example\n * // With state management\n * import { createDemoLinkWithState } from '@demokit-ai/trpc'\n *\n * const { link, enable, disable, setFixture } = createDemoLinkWithState({\n * fixtures,\n * enabled: false,\n * })\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [link, httpBatchLink({ url: '/api/trpc' })],\n * })\n *\n * // Toggle demo mode at runtime\n * enable()\n * disable()\n *\n * // Add fixtures at runtime\n * setFixture('analytics.overview', () => ({ visits: 1000 }))\n *\n * @packageDocumentation\n */\n\n// Link factory\nexport { createDemoLink, createDemoLinkWithState } from './link'\nexport type { DemoLinkWithState } from './link'\n\n// Config helpers\nexport { createRemoteSource } from './config'\n\n// Fixture definition helpers\nexport { defineTRPCFixtures, defineFixtureMap, createFixtureHandler, normalizeFixtures } from './fixtures'\n\n// Matcher utilities\nexport {\n findMatchingFixture,\n shouldIntercept,\n matchPath,\n filterFixtures,\n getFixturePaths,\n mergeFixtures,\n} from './matcher'\n\n// Types\nexport type {\n TRPCFixtureContext,\n TRPCFixtureHandler,\n RouterInputs,\n RouterOutputs,\n NestedFixtures,\n FlatFixtureMap,\n FlatFixtureMapObject,\n CreateDemoLinkOptions,\n FixtureMatchResult,\n DemoTRPCProviderConfig,\n DemoTRPCProviderProps,\n DemoTRPCState,\n RemoteSourceConfig,\n} from './types'\n","import type { TRPCLink, Operation } from '@trpc/client'\nimport { observable } from '@trpc/server/observable'\nimport type { AnyRouter } from '@trpc/server'\nimport type {\n CreateDemoLinkOptions,\n TRPCFixtureContext,\n TRPCFixtureHandler,\n FlatFixtureMap,\n} from './types'\nimport { normalizeFixtures } from './fixtures'\nimport { findMatchingFixture, shouldIntercept } from './matcher'\n\n/**\n * Create a demo-aware tRPC link\n *\n * This link intercepts tRPC procedure calls when demo mode is enabled\n * and returns fixture data instead of making real API calls.\n *\n * The demo link should be placed before the terminating link (like httpBatchLink)\n * in your link chain.\n *\n * @example\n * import { createTRPCClient, httpBatchLink } from '@trpc/client'\n * import { createDemoLink } from '@demokit-ai/trpc'\n *\n * // Simple usage with fixtures\n * const client = createTRPCClient<AppRouter>({\n * links: [\n * createDemoLink({\n * fixtures: {\n * user: {\n * list: () => [{ id: '1', name: 'Demo User' }],\n * get: ({ input }) => ({ id: input.id, name: 'Demo User' }),\n * },\n * },\n * isEnabled: () => localStorage.getItem('demoMode') === 'true',\n * }),\n * httpBatchLink({ url: '/api/trpc' }),\n * ],\n * })\n *\n * @example\n * // With include/exclude filtering\n * createDemoLink({\n * fixtures: myFixtures,\n * include: ['user.*', 'post.list'], // Only intercept user.* and post.list\n * exclude: ['user.delete'], // Never intercept user.delete\n * delay: 200, // Simulate 200ms network latency\n * onMissing: (path, input) => {\n * console.warn(`No fixture for: ${path}`)\n * },\n * })\n */\nexport function createDemoLink<TRouter extends AnyRouter = AnyRouter>(\n options: CreateDemoLinkOptions<TRouter> = {}\n): TRPCLink<TRouter> {\n const {\n fixtures: rawFixtures,\n isEnabled = () => false,\n delay = 0,\n include,\n exclude,\n onMissing,\n } = options\n\n // Normalize fixtures to flat map on initialization\n const fixtures: FlatFixtureMap = normalizeFixtures(rawFixtures as Record<string, unknown>)\n\n // Return the link factory function\n return () => {\n // Return the link function that handles each operation\n return ({ next, op }) => {\n return observable((observer) => {\n // Check if demo mode is enabled\n if (!isEnabled()) {\n // Forward to next link\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Check if this procedure should be intercepted\n if (!shouldIntercept(op.path, include, exclude)) {\n // Forward to next link\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Find matching fixture\n const match = findMatchingFixture(fixtures, op.path)\n\n if (!match.matched || !match.handler) {\n // No fixture found\n onMissing?.(op.path, op.input)\n\n // Forward to next link as fallback\n const unsubscribe = next(op).subscribe({\n next(value) {\n observer.next(value)\n },\n error(err) {\n observer.error(err)\n },\n complete() {\n observer.complete()\n },\n })\n return unsubscribe\n }\n\n // Execute fixture handler\n const executeFixture = async () => {\n const context: TRPCFixtureContext = {\n path: op.path,\n input: op.input,\n type: op.type,\n }\n\n // Apply delay if configured\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n\n // Execute handler\n const handler = match.handler as TRPCFixtureHandler\n const result = typeof handler === 'function' ? await handler(context) : handler\n\n return result\n }\n\n // Handle async execution\n executeFixture()\n .then((data) => {\n observer.next({\n result: { data },\n })\n observer.complete()\n })\n .catch((err) => {\n observer.error(err)\n })\n\n // Return cleanup function (no-op for demo fixtures)\n return () => {}\n })\n }\n }\n}\n\n/**\n * Create a demo link with state management\n *\n * Returns the link along with controls to enable/disable demo mode\n * and manage fixtures at runtime.\n *\n * @example\n * const { link, enable, disable, isEnabled, setFixture, removeFixture } =\n * createDemoLinkWithState({\n * fixtures: myFixtures,\n * })\n *\n * const client = createTRPCClient<AppRouter>({\n * links: [link, httpBatchLink({ url: '/api/trpc' })],\n * })\n *\n * // Later...\n * enable() // Turn on demo mode\n * disable() // Turn off demo mode\n *\n * // Add fixture at runtime\n * setFixture('user.get', ({ input }) => ({ id: input.id, name: 'Runtime User' }))\n */\nexport function createDemoLinkWithState<TRouter extends AnyRouter = AnyRouter>(\n options: Omit<CreateDemoLinkOptions<TRouter>, 'isEnabled'> & {\n /**\n * Initial enabled state\n * @default false\n */\n enabled?: boolean\n } = {}\n) {\n const { fixtures: rawFixtures, enabled: initialEnabled = false, ...rest } = options\n\n let enabled = initialEnabled\n const fixtures: FlatFixtureMap = normalizeFixtures(rawFixtures as Record<string, unknown>)\n\n const link = createDemoLink<TRouter>({\n ...rest,\n fixtures,\n isEnabled: () => enabled,\n })\n\n return {\n /**\n * The tRPC link to use in your client\n */\n link,\n\n /**\n * Enable demo mode\n */\n enable: () => {\n enabled = true\n },\n\n /**\n * Disable demo mode\n */\n disable: () => {\n enabled = false\n },\n\n /**\n * Check if demo mode is enabled\n */\n isEnabled: () => enabled,\n\n /**\n * Toggle demo mode\n */\n toggle: () => {\n enabled = !enabled\n return enabled\n },\n\n /**\n * Set or update a fixture\n */\n setFixture: (path: string, handler: TRPCFixtureHandler) => {\n fixtures.set(path, handler)\n },\n\n /**\n * Remove a fixture\n */\n removeFixture: (path: string) => {\n fixtures.delete(path)\n },\n\n /**\n * Get all fixtures\n */\n getFixtures: () => fixtures,\n\n /**\n * Clear all fixtures\n */\n clearFixtures: () => {\n fixtures.clear()\n },\n }\n}\n\nexport type DemoLinkWithState<TRouter extends AnyRouter = AnyRouter> = ReturnType<\n typeof createDemoLinkWithState<TRouter>\n>\n","import type {\n AnyRouter,\n inferRouterInputs,\n inferRouterOutputs,\n} from '@trpc/server'\nimport type { TRPCFixtureHandler, TRPCFixtureContext, FlatFixtureMap } from './types'\n\n/**\n * Type helper to create fixture handlers with full type inference\n *\n * This helper infers input/output types from your router definition,\n * providing autocomplete and type checking for fixture definitions.\n *\n * @example\n * import { defineTRPCFixtures } from '@demokit-ai/trpc'\n * import type { AppRouter } from '../server/router'\n *\n * // Nested structure matching your router\n * const fixtures = defineTRPCFixtures<AppRouter>()({\n * user: {\n * list: () => [\n * { id: '1', name: 'Demo User', email: 'demo@example.com' }\n * ],\n * get: ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * email: 'demo@example.com',\n * }),\n * create: async ({ input }) => ({\n * id: crypto.randomUUID(),\n * ...input,\n * createdAt: new Date(),\n * }),\n * },\n * post: {\n * list: () => [],\n * },\n * })\n */\nexport function defineTRPCFixtures<TRouter extends AnyRouter>() {\n type RouterIn = inferRouterInputs<TRouter>\n type RouterOut = inferRouterOutputs<TRouter>\n\n /**\n * Helper type to build nested fixture structure\n */\n type BuildFixtureType<TIn, TOut> = {\n [K in keyof TIn & keyof TOut]?: TIn[K] extends object\n ? TOut[K] extends object\n ? // Check if this is a procedure (has no nested keys) or a namespace\n keyof TIn[K] extends never\n ? TRPCFixtureHandler<TIn[K], TOut[K]>\n : BuildFixtureType<TIn[K], TOut[K]>\n : TRPCFixtureHandler<TIn[K], TOut[K]>\n : TRPCFixtureHandler<TIn[K], TOut[K]>\n }\n\n return function <T extends BuildFixtureType<RouterIn, RouterOut>>(fixtures: T): T {\n return fixtures\n }\n}\n\n/**\n * Alternative: define fixtures using flat dot-notation paths\n *\n * Useful when you want to define fixtures independently of router structure.\n *\n * @example\n * const fixtures = defineFixtureMap<AppRouter>({\n * 'user.list': () => [{ id: '1', name: 'Demo' }],\n * 'user.get': ({ input }) => ({ id: input.id, name: 'Demo' }),\n * })\n */\nexport function defineFixtureMap<TRouter extends AnyRouter>(\n fixtures: FlatFixtureRecord<TRouter>\n): FlatFixtureMap {\n return new Map(Object.entries(fixtures))\n}\n\n/**\n * Type for flat fixture map with path-based keys\n */\ntype FlatFixtureRecord<TRouter extends AnyRouter> = {\n [K in ProcedurePaths<TRouter>]?: TRPCFixtureHandler<\n PathInput<TRouter, K>,\n PathOutput<TRouter, K>\n >\n}\n\n/**\n * Extract all procedure paths from a router using dot notation\n */\ntype ProcedurePaths<TRouter extends AnyRouter> = inferRouterInputs<TRouter> extends infer TIn\n ? TIn extends object\n ? FlattenPaths<TIn>\n : never\n : never\n\n/**\n * Flatten nested object keys to dot notation\n */\ntype FlattenPaths<T, Prefix extends string = ''> = T extends object\n ? {\n [K in keyof T]: K extends string\n ? T[K] extends object\n ? keyof T[K] extends never\n ? `${Prefix}${K}`\n : FlattenPaths<T[K], `${Prefix}${K}.`>\n : `${Prefix}${K}`\n : never\n }[keyof T]\n : never\n\n/**\n * Get input type for a specific procedure path\n */\ntype PathInput<TRouter extends AnyRouter, Path extends string> = Path extends `${infer First}.${infer Rest}`\n ? inferRouterInputs<TRouter>[First] extends object\n ? PathInput<inferRouterInputs<TRouter>[First] extends AnyRouter ? inferRouterInputs<TRouter>[First] : never, Rest>\n : never\n : inferRouterInputs<TRouter>[Path]\n\n/**\n * Get output type for a specific procedure path\n */\ntype PathOutput<TRouter extends AnyRouter, Path extends string> = Path extends `${infer First}.${infer Rest}`\n ? inferRouterOutputs<TRouter>[First] extends object\n ? PathOutput<inferRouterOutputs<TRouter>[First] extends AnyRouter ? inferRouterOutputs<TRouter>[First] : never, Rest>\n : never\n : inferRouterOutputs<TRouter>[Path]\n\n/**\n * Create a fixture handler with explicit types\n *\n * Useful when you need to define a fixture outside of the main fixture object.\n *\n * @example\n * const getUserFixture = createFixtureHandler<{ id: string }, User>(\n * ({ input }) => ({\n * id: input.id,\n * name: 'Demo User',\n * })\n * )\n */\nexport function createFixtureHandler<TInput, TOutput>(\n handler: TRPCFixtureHandler<TInput, TOutput>\n): TRPCFixtureHandler<TInput, TOutput> {\n return handler\n}\n\n/**\n * Normalize fixture definitions to a flat Map\n *\n * Converts nested fixture objects to a flat map with dot-notation paths.\n */\nexport function normalizeFixtures(\n fixtures: Record<string, unknown> | FlatFixtureMap | undefined\n): FlatFixtureMap {\n if (!fixtures) {\n return new Map()\n }\n\n if (fixtures instanceof Map) {\n return fixtures\n }\n\n const result: FlatFixtureMap = new Map()\n\n function flatten(obj: Record<string, unknown>, prefix = '') {\n for (const [key, value] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${key}` : key\n\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof value !== 'function'\n ) {\n // Check if this looks like a fixture handler or a namespace\n // Fixture handlers are either primitives, arrays, or functions\n // Namespaces are objects with nested procedures\n const hasNestedProcedures = Object.values(value).some(\n (v) => typeof v === 'function' || Array.isArray(v) || (typeof v === 'object' && v !== null)\n )\n\n if (hasNestedProcedures) {\n flatten(value as Record<string, unknown>, path)\n } else {\n // This is a static fixture value (an object)\n result.set(path, value as TRPCFixtureHandler)\n }\n } else {\n // This is a fixture handler (function, array, or primitive)\n result.set(path, value as TRPCFixtureHandler)\n }\n }\n }\n\n flatten(fixtures as Record<string, unknown>)\n return result\n}\n","import type { FlatFixtureMap, TRPCFixtureHandler, FixtureMatchResult } from './types'\n\n/**\n * Find a matching fixture for a procedure path\n *\n * @param fixtures - Map of procedure paths to fixture handlers\n * @param path - The procedure path to match (e.g., 'user.get', 'post.list')\n * @returns Match result with handler if found\n *\n * @example\n * const fixtures = new Map([\n * ['user.list', () => []],\n * ['user.get', ({ input }) => ({ id: input.id })],\n * ])\n *\n * findMatchingFixture(fixtures, 'user.get')\n * // { matched: true, handler: Function, path: 'user.get' }\n *\n * findMatchingFixture(fixtures, 'unknown.path')\n * // { matched: false, path: 'unknown.path' }\n */\nexport function findMatchingFixture<TOutput = unknown>(\n fixtures: FlatFixtureMap,\n path: string\n): FixtureMatchResult<TOutput> {\n const handler = fixtures.get(path)\n\n if (handler !== undefined) {\n return {\n matched: true,\n handler: handler as TRPCFixtureHandler<unknown, TOutput>,\n path,\n }\n }\n\n return {\n matched: false,\n path,\n }\n}\n\n/**\n * Check if a procedure path should be intercepted based on include/exclude rules\n *\n * @param path - The procedure path to check\n * @param include - Optional list of paths to include (if provided, only these are intercepted)\n * @param exclude - Optional list of paths to exclude (takes precedence over include)\n * @returns Whether the path should be intercepted\n *\n * @example\n * // Include only specific paths\n * shouldIntercept('user.get', ['user.get', 'user.list'], [])\n * // true\n *\n * shouldIntercept('post.list', ['user.get', 'user.list'], [])\n * // false\n *\n * // Exclude takes precedence\n * shouldIntercept('user.get', ['user.get'], ['user.get'])\n * // false\n */\nexport function shouldIntercept(\n path: string,\n include?: string[],\n exclude?: string[]\n): boolean {\n // Exclude takes precedence\n if (exclude?.includes(path)) {\n return false\n }\n\n // If include list is provided, only intercept those\n if (include && include.length > 0) {\n return include.includes(path)\n }\n\n // By default, intercept all\n return true\n}\n\n/**\n * Check if a procedure path matches a pattern with wildcards\n *\n * Supports:\n * - Exact match: 'user.get' matches 'user.get'\n * - Wildcard suffix: 'user.*' matches 'user.get', 'user.list', etc.\n * - Wildcard prefix: '*.get' matches 'user.get', 'post.get', etc.\n * - Full wildcard: '*' matches everything\n *\n * @param path - The procedure path to check\n * @param pattern - The pattern to match against\n * @returns Whether the path matches the pattern\n *\n * @example\n * matchPath('user.get', 'user.get') // true\n * matchPath('user.get', 'user.*') // true\n * matchPath('user.get', '*.get') // true\n * matchPath('user.get', '*') // true\n * matchPath('user.get', 'post.*') // false\n */\nexport function matchPath(path: string, pattern: string): boolean {\n if (pattern === '*') {\n return true\n }\n\n if (pattern === path) {\n return true\n }\n\n // Handle wildcard patterns\n if (pattern.includes('*')) {\n const regex = new RegExp(\n '^' +\n pattern\n .split('*')\n .map((s) => escapeRegex(s))\n .join('.*') +\n '$'\n )\n return regex.test(path)\n }\n\n return false\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Filter fixtures based on include/exclude patterns\n *\n * @param fixtures - The fixture map to filter\n * @param include - Patterns to include (supports wildcards)\n * @param exclude - Patterns to exclude (takes precedence, supports wildcards)\n * @returns A new fixture map with only matching fixtures\n */\nexport function filterFixtures(\n fixtures: FlatFixtureMap,\n include?: string[],\n exclude?: string[]\n): FlatFixtureMap {\n const result: FlatFixtureMap = new Map()\n\n for (const [path, handler] of fixtures) {\n // Check if path should be included\n let shouldInclude = true\n\n if (include && include.length > 0) {\n shouldInclude = include.some((pattern) => matchPath(path, pattern))\n }\n\n // Check if path should be excluded\n if (exclude && exclude.length > 0) {\n if (exclude.some((pattern) => matchPath(path, pattern))) {\n shouldInclude = false\n }\n }\n\n if (shouldInclude) {\n result.set(path, handler)\n }\n }\n\n return result\n}\n\n/**\n * Get all procedure paths from a fixture map\n *\n * @param fixtures - The fixture map\n * @returns Array of all procedure paths\n */\nexport function getFixturePaths(fixtures: FlatFixtureMap): string[] {\n return Array.from(fixtures.keys())\n}\n\n/**\n * Merge multiple fixture maps\n *\n * Later maps take precedence over earlier ones for the same path.\n *\n * @param maps - Fixture maps to merge\n * @returns Merged fixture map\n */\nexport function mergeFixtures(...maps: FlatFixtureMap[]): FlatFixtureMap {\n const result: FlatFixtureMap = new Map()\n\n for (const map of maps) {\n for (const [path, handler] of map) {\n result.set(path, handler)\n }\n }\n\n return result\n}\n","import type { RemoteSourceConfig } from './types'\n\n/**\n * Create a remote source configuration for fetching fixtures from DemoKit Cloud\n *\n * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.\n *\n * @example\n * ```typescript\n * // lib/demokit-config.ts\n * import { createRemoteSource } from '@demokit-ai/trpc'\n *\n * // .env.local:\n * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,\n * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,\n * })\n *\n * // Then in your providers:\n * import { demokitSource } from '@/lib/demokit-config'\n *\n * <DemoTRPCProvider source={demokitSource}>\n * <TRPCProvider>\n * <App />\n * </TRPCProvider>\n * </DemoTRPCProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,10 +1,41 @@
1
- import { F as FlatFixtureMap, a as FixtureMatchResult } from './fixtures-BV-EUS_X.cjs';
2
- export { C as CreateDemoLinkOptions, D as DemoLinkWithState, j as DemoTRPCProviderConfig, k as DemoTRPCProviderProps, l as DemoTRPCState, i as FlatFixtureMapObject, N as NestedFixtures, R as RouterInputs, h as RouterOutputs, T as TRPCFixtureContext, g as TRPCFixtureHandler, c as createDemoLink, b as createDemoLinkWithState, f as createFixtureHandler, e as defineFixtureMap, d as defineTRPCFixtures, n as normalizeFixtures } from './fixtures-BV-EUS_X.cjs';
1
+ import { R as RemoteSourceConfig, F as FlatFixtureMap, a as FixtureMatchResult } from './fixtures-BjQoawnf.cjs';
2
+ export { C as CreateDemoLinkOptions, D as DemoLinkWithState, k as DemoTRPCProviderConfig, l as DemoTRPCProviderProps, m as DemoTRPCState, j as FlatFixtureMapObject, N as NestedFixtures, h as RouterInputs, i as RouterOutputs, T as TRPCFixtureContext, g as TRPCFixtureHandler, c as createDemoLink, b as createDemoLinkWithState, f as createFixtureHandler, e as defineFixtureMap, d as defineTRPCFixtures, n as normalizeFixtures } from './fixtures-BjQoawnf.cjs';
3
3
  import '@trpc/client';
4
4
  import '@trpc/server';
5
5
  import '@trpc/server/unstable-core-do-not-import';
6
6
  import 'react';
7
7
 
8
+ /**
9
+ * Create a remote source configuration for fetching fixtures from DemoKit Cloud
10
+ *
11
+ * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // lib/demokit-config.ts
16
+ * import { createRemoteSource } from '@demokit-ai/trpc'
17
+ *
18
+ * // .env.local:
19
+ * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
20
+ * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx
21
+ *
22
+ * export const demokitSource = createRemoteSource({
23
+ * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,
24
+ * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,
25
+ * })
26
+ *
27
+ * // Then in your providers:
28
+ * import { demokitSource } from '@/lib/demokit-config'
29
+ *
30
+ * <DemoTRPCProvider source={demokitSource}>
31
+ * <TRPCProvider>
32
+ * <App />
33
+ * </TRPCProvider>
34
+ * </DemoTRPCProvider>
35
+ * ```
36
+ */
37
+ declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
38
+
8
39
  /**
9
40
  * Find a matching fixture for a procedure path
10
41
  *
@@ -93,4 +124,4 @@ declare function getFixturePaths(fixtures: FlatFixtureMap): string[];
93
124
  */
94
125
  declare function mergeFixtures(...maps: FlatFixtureMap[]): FlatFixtureMap;
95
126
 
96
- export { FixtureMatchResult, FlatFixtureMap, filterFixtures, findMatchingFixture, getFixturePaths, matchPath, mergeFixtures, shouldIntercept };
127
+ export { FixtureMatchResult, FlatFixtureMap, RemoteSourceConfig, createRemoteSource, filterFixtures, findMatchingFixture, getFixturePaths, matchPath, mergeFixtures, shouldIntercept };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,41 @@
1
- import { F as FlatFixtureMap, a as FixtureMatchResult } from './fixtures-BV-EUS_X.js';
2
- export { C as CreateDemoLinkOptions, D as DemoLinkWithState, j as DemoTRPCProviderConfig, k as DemoTRPCProviderProps, l as DemoTRPCState, i as FlatFixtureMapObject, N as NestedFixtures, R as RouterInputs, h as RouterOutputs, T as TRPCFixtureContext, g as TRPCFixtureHandler, c as createDemoLink, b as createDemoLinkWithState, f as createFixtureHandler, e as defineFixtureMap, d as defineTRPCFixtures, n as normalizeFixtures } from './fixtures-BV-EUS_X.js';
1
+ import { R as RemoteSourceConfig, F as FlatFixtureMap, a as FixtureMatchResult } from './fixtures-BjQoawnf.js';
2
+ export { C as CreateDemoLinkOptions, D as DemoLinkWithState, k as DemoTRPCProviderConfig, l as DemoTRPCProviderProps, m as DemoTRPCState, j as FlatFixtureMapObject, N as NestedFixtures, h as RouterInputs, i as RouterOutputs, T as TRPCFixtureContext, g as TRPCFixtureHandler, c as createDemoLink, b as createDemoLinkWithState, f as createFixtureHandler, e as defineFixtureMap, d as defineTRPCFixtures, n as normalizeFixtures } from './fixtures-BjQoawnf.js';
3
3
  import '@trpc/client';
4
4
  import '@trpc/server';
5
5
  import '@trpc/server/unstable-core-do-not-import';
6
6
  import 'react';
7
7
 
8
+ /**
9
+ * Create a remote source configuration for fetching fixtures from DemoKit Cloud
10
+ *
11
+ * The SDK appends `/fixtures` to your apiUrl, so provide the versioned base URL.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // lib/demokit-config.ts
16
+ * import { createRemoteSource } from '@demokit-ai/trpc'
17
+ *
18
+ * // .env.local:
19
+ * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api
20
+ * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx
21
+ *
22
+ * export const demokitSource = createRemoteSource({
23
+ * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,
24
+ * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,
25
+ * })
26
+ *
27
+ * // Then in your providers:
28
+ * import { demokitSource } from '@/lib/demokit-config'
29
+ *
30
+ * <DemoTRPCProvider source={demokitSource}>
31
+ * <TRPCProvider>
32
+ * <App />
33
+ * </TRPCProvider>
34
+ * </DemoTRPCProvider>
35
+ * ```
36
+ */
37
+ declare function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig;
38
+
8
39
  /**
9
40
  * Find a matching fixture for a procedure path
10
41
  *
@@ -93,4 +124,4 @@ declare function getFixturePaths(fixtures: FlatFixtureMap): string[];
93
124
  */
94
125
  declare function mergeFixtures(...maps: FlatFixtureMap[]): FlatFixtureMap;
95
126
 
96
- export { FixtureMatchResult, FlatFixtureMap, filterFixtures, findMatchingFixture, getFixturePaths, matchPath, mergeFixtures, shouldIntercept };
127
+ export { FixtureMatchResult, FlatFixtureMap, RemoteSourceConfig, createRemoteSource, filterFixtures, findMatchingFixture, getFixturePaths, matchPath, mergeFixtures, shouldIntercept };
package/dist/index.js CHANGED
@@ -12,10 +12,21 @@ import {
12
12
  normalizeFixtures,
13
13
  shouldIntercept
14
14
  } from "./chunk-2C4EOFRK.js";
15
+
16
+ // src/config.ts
17
+ function createRemoteSource(config) {
18
+ return {
19
+ timeout: 1e4,
20
+ retry: true,
21
+ maxRetries: 3,
22
+ ...config
23
+ };
24
+ }
15
25
  export {
16
26
  createDemoLink,
17
27
  createDemoLinkWithState,
18
28
  createFixtureHandler,
29
+ createRemoteSource,
19
30
  defineFixtureMap,
20
31
  defineTRPCFixtures,
21
32
  filterFixtures,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["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/trpc'\n *\n * // .env.local:\n * // NEXT_PUBLIC_DEMOKIT_API_URL=https://demokit-cloud.kasava.dev/api\n * // NEXT_PUBLIC_DEMOKIT_API_KEY=dk_live_xxxx\n *\n * export const demokitSource = createRemoteSource({\n * apiUrl: process.env.NEXT_PUBLIC_DEMOKIT_API_URL!,\n * apiKey: process.env.NEXT_PUBLIC_DEMOKIT_API_KEY!,\n * })\n *\n * // Then in your providers:\n * import { demokitSource } from '@/lib/demokit-config'\n *\n * <DemoTRPCProvider source={demokitSource}>\n * <TRPCProvider>\n * <App />\n * </TRPCProvider>\n * </DemoTRPCProvider>\n * ```\n */\nexport function createRemoteSource(config: RemoteSourceConfig): RemoteSourceConfig {\n return {\n timeout: 10000,\n retry: true,\n maxRetries: 3,\n ...config,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+BO,SAAS,mBAAmB,QAAgD;AACjF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;","names":[]}
package/dist/react.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { AnyRouter } from '@trpc/server';
3
- import { k as DemoTRPCProviderProps, l as DemoTRPCState, g as TRPCFixtureHandler, F as FlatFixtureMap } from './fixtures-BV-EUS_X.cjs';
4
- export { j as DemoTRPCProviderConfig, c as createDemoLink, b as createDemoLinkWithState, e as defineFixtureMap, d as defineTRPCFixtures } from './fixtures-BV-EUS_X.cjs';
3
+ import { l as DemoTRPCProviderProps, m as DemoTRPCState, g as TRPCFixtureHandler, F as FlatFixtureMap } from './fixtures-BjQoawnf.cjs';
4
+ export { k as DemoTRPCProviderConfig, c as createDemoLink, b as createDemoLinkWithState, e as defineFixtureMap, d as defineTRPCFixtures } from './fixtures-BjQoawnf.cjs';
5
5
  import * as react from 'react';
6
6
  import '@trpc/client';
7
7
  import '@trpc/server/unstable-core-do-not-import';
package/dist/react.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { AnyRouter } from '@trpc/server';
3
- import { k as DemoTRPCProviderProps, l as DemoTRPCState, g as TRPCFixtureHandler, F as FlatFixtureMap } from './fixtures-BV-EUS_X.js';
4
- export { j as DemoTRPCProviderConfig, c as createDemoLink, b as createDemoLinkWithState, e as defineFixtureMap, d as defineTRPCFixtures } from './fixtures-BV-EUS_X.js';
3
+ import { l as DemoTRPCProviderProps, m as DemoTRPCState, g as TRPCFixtureHandler, F as FlatFixtureMap } from './fixtures-BjQoawnf.js';
4
+ export { k as DemoTRPCProviderConfig, c as createDemoLink, b as createDemoLinkWithState, e as defineFixtureMap, d as defineTRPCFixtures } from './fixtures-BjQoawnf.js';
5
5
  import * as react from 'react';
6
6
  import '@trpc/client';
7
7
  import '@trpc/server/unstable-core-do-not-import';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@demokit-ai/trpc",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "tRPC integration for DemoKit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,21 +32,22 @@
32
32
  "dist"
33
33
  ],
34
34
  "dependencies": {
35
- "@demokit-ai/react": "0.3.0",
36
- "@demokit-ai/core": "0.3.0"
35
+ "@demokit-ai/core": "0.4.2",
36
+ "@demokit-ai/react": "0.4.1"
37
37
  },
38
38
  "devDependencies": {
39
- "@trpc/client": "^11.0.0-rc.532",
40
- "@trpc/react-query": "^11.0.0-rc.532",
41
- "@trpc/server": "^11.0.0-rc.532",
39
+ "@trpc/client": "^11.15.0",
40
+ "@trpc/react-query": "^11.15.0",
41
+ "@trpc/server": "^11.15.0",
42
+ "@types/node": "^22.0.0",
42
43
  "@types/react": "^19.0.0",
43
- "tsup": "^8.3.5",
44
- "typescript": "^5.7.2"
44
+ "tsup": "^8.5.1",
45
+ "typescript": "^6.0.2"
45
46
  },
46
47
  "peerDependencies": {
47
- "@trpc/client": ">=11.0.0-rc.0",
48
- "@trpc/react-query": ">=11.0.0-rc.0",
49
- "@trpc/server": ">=11.0.0-rc.0",
48
+ "@trpc/client": ">=11.15.0",
49
+ "@trpc/react-query": ">=11.15.0",
50
+ "@trpc/server": ">=11.15.0",
50
51
  "react": ">=17.0.0"
51
52
  },
52
53
  "engines": {