@simpleapps-com/augur-core 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -180,11 +180,24 @@ function createOptionsProxy(api, config) {
180
180
  function createActionsProxy(api, config) {
181
181
  return createDeepProxy(async (path, args) => {
182
182
  const methodPath = path.join(".");
183
+ const methodName = path[path.length - 1];
183
184
  const sdkMethod = resolveMethod(api, path);
184
185
  const transform = _optionalChain([config, 'optionalAccess', _4 => _4.transforms, 'optionalAccess', _5 => _5[methodPath]]);
185
186
  const finalArgs = _optionalChain([transform, 'optionalAccess', _6 => _6.pre]) ? transform.pre(args) : args;
186
- const result = await sdkMethod(...finalArgs);
187
- return _optionalChain([transform, 'optionalAccess', _7 => _7.post]) ? transform.post(result) : result;
187
+ let result;
188
+ if (_optionalChain([config, 'optionalAccess', _7 => _7.wrapCall])) {
189
+ const tier = getCacheTier(methodPath, config.cache);
190
+ result = await config.wrapCall({
191
+ methodPath,
192
+ args: finalArgs,
193
+ sdkCall: (...a) => sdkMethod(...a),
194
+ tier,
195
+ isRead: isReadMethod(methodName)
196
+ });
197
+ } else {
198
+ result = await sdkMethod(...finalArgs);
199
+ }
200
+ return _optionalChain([transform, 'optionalAccess', _8 => _8.post]) ? transform.post(result) : result;
188
201
  });
189
202
  }
190
203
 
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-core/dist/index.cjs","../src/classification.ts","../src/cache.ts","../src/keys.ts","../src/utils.ts","../src/proxy.ts"],"names":["base","tier"],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-core/dist/index.cjs","sourcesContent":[null,"/**\n * Method classification — determines whether an SDK method is a read (GET)\n * or write (POST/PUT/DELETE) based on its leaf method name.\n *\n * Read methods produce UseQueryOptions; write methods produce UseMutationOptions.\n */\n\nconst READ_METHODS = new Set([\"get\", \"list\", \"lookup\", \"search\", \"suggest\"]);\n\n/**\n * Returns true if the leaf method name represents a read (GET) operation.\n *\n * Read methods: get, list, lookup, search, suggest\n */\nexport function isReadMethod(methodName: string): boolean {\n return READ_METHODS.has(methodName);\n}\n\n/**\n * Returns true if the leaf method name represents a write (POST/PUT/DELETE) operation.\n *\n * Write methods: create, update, delete, enable, and anything not in the read set.\n */\nexport function isWriteMethod(methodName: string): boolean {\n return !READ_METHODS.has(methodName);\n}\n","/**\n * Cache tier resolution — maps SDK method paths to cache tiers.\n *\n * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).\n */\n\nimport type { CacheTierConfig } from \"./shared-types\";\n\n/** Internal resolved cache tier with all timing values. */\nexport interface ResolvedCacheTier {\n staleTime: number;\n gcTime: number;\n edgeCache?: number | string;\n redisTtl?: number;\n}\n\n/** Cache tier configuration with defaults for all tiers. */\nexport interface CacheTierDefaults {\n static: ResolvedCacheTier;\n semiStatic: ResolvedCacheTier;\n none: ResolvedCacheTier;\n}\n\n/** Default cache tier values. */\nexport const DEFAULT_CACHE_TIERS: CacheTierDefaults = {\n static: {\n staleTime: 60 * 60 * 1000, // 60 min\n gcTime: 2 * 60 * 60 * 1000, // 120 min\n edgeCache: 8,\n redisTtl: 28800, // 8 hours\n },\n semiStatic: {\n staleTime: 60 * 1000, // 1 min\n gcTime: 5 * 60 * 1000, // 5 min\n edgeCache: 1,\n redisTtl: 3600, // 1 hour\n },\n none: {\n staleTime: 0,\n gcTime: 0,\n },\n};\n\n/** Paths that should use the static cache tier. */\nconst STATIC_PATHS = [\n \"agrSite.settings\",\n \"agrSite.metaFiles\",\n \"agrSite.geoCodesPostalCodes\",\n \"items.categories\",\n \"items.itemCategory\",\n \"items.brands\",\n \"items.attributeGroups\",\n \"items.attributes\",\n \"p21Core.company\",\n \"p21Core.location\",\n \"p21Core.paymentTypes\",\n \"p21Core.codeP21\",\n \"p21Core.cashDrawer\",\n \"joomla.menu\",\n \"joomla.tags\",\n \"joomla.userGroups\",\n \"legacy.state\",\n];\n\n/** Paths that should not be cached. */\nconst NO_CACHE_PATHS = [\"commerce\"];\n\n/**\n * Resolves the cache tier for a given SDK method path.\n *\n * @param methodPath Dot-separated SDK method path (e.g. \"items.invMast.stock.get\")\n * @param overrides Optional per-tier overrides from consumer config\n * @returns Resolved cache tier with timing values\n *\n * @example\n * getCacheTier(\"items.categories.list\") → static (60 min stale)\n * getCacheTier(\"pricing.priceEngine.get\") → semiStatic (1 min stale)\n * getCacheTier(\"commerce.cartLine.add.create\") → none (0 stale)\n */\nexport function getCacheTier(\n methodPath: string,\n overrides?: { static?: CacheTierConfig; semiStatic?: CacheTierConfig },\n): ResolvedCacheTier {\n if (NO_CACHE_PATHS.some((p) => methodPath.startsWith(p))) {\n return DEFAULT_CACHE_TIERS.none;\n }\n\n if (STATIC_PATHS.some((p) => methodPath.startsWith(p))) {\n const base = DEFAULT_CACHE_TIERS.static;\n const tier = overrides?.static;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n }\n\n // Default: semiStatic\n const base = DEFAULT_CACHE_TIERS.semiStatic;\n const tier = overrides?.semiStatic;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n}\n","/**\n * Deterministic key generation utilities.\n *\n * stableStringify and fnv1a are the single source of truth —\n * augur-hooks and augur-server both import from here so cache keys\n * are guaranteed identical across client and server.\n */\n\n/**\n * JSON.stringify with sorted object keys for deterministic cache keys.\n * Ensures { a: 1, b: 2 } and { b: 2, a: 1 } produce the same string.\n */\nexport function stableStringify(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(\n (key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`,\n );\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * FNV-1a 32-bit hash. Fast non-cryptographic hash for cache keys.\n * Returns an 8-character zero-padded hex string.\n */\nexport function fnv1a(str: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Builds a deterministic query key from a method path and arguments.\n *\n * @example\n * buildQueryKey([\"items\", \"invMast\", \"get\"], [42])\n * → [\"items\", \"invMast\", \"get\", 42]\n *\n * buildQueryKey([\"pricing\", \"priceEngine\", \"get\"], [{ itemId: \"X\", customerId: 1 }])\n * → [\"pricing\", \"priceEngine\", \"get\", { itemId: \"X\", customerId: 1 }]\n */\nexport function buildQueryKey(path: string[], args: unknown[]): unknown[] {\n return [...path, ...args];\n}\n\n/**\n * Builds a deterministic cache key for Redis/CDN caching.\n *\n * Format: `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`\n *\n * @example\n * buildCacheKey(\"ampro:\", \"pricing.priceEngine.get\", [{ itemId: \"X\" }])\n * → \"ampro:sdk:pricing.priceEngine.get:a1b2c3d4\"\n */\nexport function buildCacheKey(\n prefix: string,\n methodPath: string,\n args: unknown[],\n): string {\n return `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`;\n}\n","/**\n * Utility functions for the proxy infrastructure.\n */\n\n/**\n * Walk an object by path array to find the leaf function.\n *\n * @example\n * resolveMethod(api, [\"items\", \"invMast\", \"stock\", \"get\"])\n * → api.items.invMast.stock.get\n */\nexport function resolveMethod(\n obj: unknown,\n path: string[],\n): (...args: unknown[]) => unknown {\n let current: unknown = obj;\n for (const segment of path) {\n if (current == null || typeof current !== \"object\") {\n throw new Error(\n `Cannot resolve method path \"${path.join(\".\")}\": ` +\n `\"${segment}\" is not accessible on ${typeof current}`,\n );\n }\n current = (current as Record<string, unknown>)[segment];\n }\n if (typeof current !== \"function\") {\n throw new Error(\n `Method path \"${path.join(\".\")}\" does not resolve to a function ` +\n `(got ${typeof current})`,\n );\n }\n return current as (...args: unknown[]) => unknown;\n}\n\n/**\n * Normalize arguments for deterministic cache/query keys.\n * Filters out undefined values from argument objects.\n */\nexport function stableArgs(args: unknown[]): unknown[] {\n return args.map((arg) => {\n if (arg === null || arg === undefined || typeof arg !== \"object\") return arg;\n if (Array.isArray(arg)) return arg;\n const obj = arg as Record<string, unknown>;\n const filtered: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n if (obj[key] !== undefined) {\n filtered[key] = obj[key];\n }\n }\n return filtered;\n });\n}\n","/**\n * Deep proxy factories — runtime SDK namespace mirroring.\n *\n * The same Proxy pattern that powers `createMockClient()` in the SDK\n * powers every downstream consumer. One proxy shape, multiple behaviors\n * via the handler callback.\n */\n\nimport { isReadMethod } from \"./classification\";\nimport { getCacheTier } from \"./cache\";\nimport type { CacheTierConfig } from \"./shared-types\";\nimport { buildQueryKey, buildCacheKey, stableStringify, fnv1a } from \"./keys\";\nimport { resolveMethod, stableArgs } from \"./utils\";\nimport type { ProxyQueryOptions, ProxyMutationOptions } from \"./types\";\n\n/** Configuration for the options proxy (hooks). */\nexport interface OptionsProxyConfig {\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n}\n\n/** Configuration for the actions proxy (server). */\nexport interface ActionsProxyConfig {\n /** Cache key prefix (e.g. \"ampro:\"). */\n cachePrefix?: string;\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n /** Pre/post transforms per method path. */\n transforms?: Record<\n string,\n {\n pre?: (args: unknown[]) => unknown[];\n post?: (result: unknown) => unknown;\n }\n >;\n}\n\n/**\n * Creates a deep proxy that intercepts property access to build a method\n * path, then calls the handler when the proxy is invoked as a function.\n *\n * This is the core mechanism. `createOptionsProxy` and `createActionsProxy`\n * are thin wrappers that provide different handlers.\n */\nexport function createDeepProxy<TResult>(\n handler: (path: string[], args: unknown[]) => TResult,\n path: string[] = [],\n): unknown {\n /* v8 ignore next -- placeholder body, only the Proxy traps execute */\n const callable = function () {};\n\n return new Proxy(callable, {\n get(_target, prop: string | symbol) {\n if (typeof prop === \"symbol\") return undefined;\n return createDeepProxy(handler, [...path, prop]);\n },\n apply(_target, _thisArg, args: unknown[]) {\n return handler(path, args);\n },\n });\n}\n\n/**\n * Creates a proxy that returns TanStack Query options for every SDK method.\n *\n * Read methods (get, list, lookup, search, suggest) return ProxyQueryOptions.\n * Write methods (create, update, delete, etc.) return ProxyMutationOptions.\n *\n * @param api The SDK client instance\n * @param config Optional cache configuration\n * @returns Proxy mirroring the SDK with query/mutation options at every leaf\n *\n * @example\n * const q = createOptionsProxy(api);\n * const opts = q.items.invMast.stock.get(42);\n * // opts.queryKey → [\"items\", \"invMast\", \"stock\", \"get\", 42]\n * // opts.queryFn → () => api.items.invMast.stock.get(42)\n * // opts.staleTime → 60000 (semiStatic default)\n */\nexport function createOptionsProxy<TApi extends object>(\n api: TApi,\n config?: OptionsProxyConfig,\n): unknown {\n return createDeepProxy(\n (\n path: string[],\n args: unknown[],\n ): ProxyQueryOptions<unknown> | ProxyMutationOptions<unknown, unknown[]> => {\n const methodName = path[path.length - 1]!;\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const normalizedArgs = stableArgs(args);\n\n if (isReadMethod(methodName)) {\n const tier = getCacheTier(methodPath, config?.cache);\n return {\n queryKey: buildQueryKey(path, normalizedArgs),\n queryFn: () => sdkMethod(...args) as Promise<unknown>,\n staleTime: tier.staleTime,\n gcTime: tier.gcTime,\n };\n }\n\n return {\n mutationKey: path,\n mutationFn: (...mutationArgs: unknown[]) =>\n sdkMethod(...mutationArgs) as Promise<unknown>,\n };\n },\n );\n}\n\n/**\n * Creates a proxy that wraps every SDK method as a direct async action.\n *\n * For read methods, the result is cached using the cache key builder.\n * For write methods, the call passes through directly.\n *\n * @param api The SDK client instance\n * @param config Optional cache and transform configuration\n * @returns Proxy mirroring the SDK with cached/transformed actions at every leaf\n *\n * @example\n * const actions = createActionsProxy(api, { cachePrefix: \"ampro:\" });\n * const stock = await actions.items.invMast.stock.get(42);\n */\nexport function createActionsProxy<TApi extends object>(\n api: TApi,\n config?: ActionsProxyConfig,\n): unknown {\n return createDeepProxy(async (path: string[], args: unknown[]) => {\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const transform = config?.transforms?.[methodPath];\n\n const finalArgs = transform?.pre ? transform.pre(args) : args;\n const result = await (sdkMethod(...finalArgs) as Promise<unknown>);\n return transform?.post ? transform.post(result) : result;\n });\n}\n\n// Re-export key utilities for consumers who need to build keys manually\nexport { buildQueryKey, buildCacheKey, stableStringify, fnv1a };\n"]}
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-core/dist/index.cjs","../src/classification.ts","../src/cache.ts","../src/keys.ts","../src/utils.ts","../src/proxy.ts"],"names":["base","tier"],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-core/dist/index.cjs","sourcesContent":[null,"/**\n * Method classification — determines whether an SDK method is a read (GET)\n * or write (POST/PUT/DELETE) based on its leaf method name.\n *\n * Read methods produce UseQueryOptions; write methods produce UseMutationOptions.\n */\n\nconst READ_METHODS = new Set([\"get\", \"list\", \"lookup\", \"search\", \"suggest\"]);\n\n/**\n * Returns true if the leaf method name represents a read (GET) operation.\n *\n * Read methods: get, list, lookup, search, suggest\n */\nexport function isReadMethod(methodName: string): boolean {\n return READ_METHODS.has(methodName);\n}\n\n/**\n * Returns true if the leaf method name represents a write (POST/PUT/DELETE) operation.\n *\n * Write methods: create, update, delete, enable, and anything not in the read set.\n */\nexport function isWriteMethod(methodName: string): boolean {\n return !READ_METHODS.has(methodName);\n}\n","/**\n * Cache tier resolution — maps SDK method paths to cache tiers.\n *\n * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).\n */\n\nimport type { CacheTierConfig } from \"./shared-types\";\n\n/** Internal resolved cache tier with all timing values. */\nexport interface ResolvedCacheTier {\n staleTime: number;\n gcTime: number;\n edgeCache?: number | string;\n redisTtl?: number;\n}\n\n/** Cache tier configuration with defaults for all tiers. */\nexport interface CacheTierDefaults {\n static: ResolvedCacheTier;\n semiStatic: ResolvedCacheTier;\n none: ResolvedCacheTier;\n}\n\n/** Default cache tier values. */\nexport const DEFAULT_CACHE_TIERS: CacheTierDefaults = {\n static: {\n staleTime: 60 * 60 * 1000, // 60 min\n gcTime: 2 * 60 * 60 * 1000, // 120 min\n edgeCache: 8,\n redisTtl: 28800, // 8 hours\n },\n semiStatic: {\n staleTime: 60 * 1000, // 1 min\n gcTime: 5 * 60 * 1000, // 5 min\n edgeCache: 1,\n redisTtl: 3600, // 1 hour\n },\n none: {\n staleTime: 0,\n gcTime: 0,\n },\n};\n\n/** Paths that should use the static cache tier. */\nconst STATIC_PATHS = [\n \"agrSite.settings\",\n \"agrSite.metaFiles\",\n \"agrSite.geoCodesPostalCodes\",\n \"items.categories\",\n \"items.itemCategory\",\n \"items.brands\",\n \"items.attributeGroups\",\n \"items.attributes\",\n \"p21Core.company\",\n \"p21Core.location\",\n \"p21Core.paymentTypes\",\n \"p21Core.codeP21\",\n \"p21Core.cashDrawer\",\n \"joomla.menu\",\n \"joomla.tags\",\n \"joomla.userGroups\",\n \"legacy.state\",\n];\n\n/** Paths that should not be cached. */\nconst NO_CACHE_PATHS = [\"commerce\"];\n\n/**\n * Resolves the cache tier for a given SDK method path.\n *\n * @param methodPath Dot-separated SDK method path (e.g. \"items.invMast.stock.get\")\n * @param overrides Optional per-tier overrides from consumer config\n * @returns Resolved cache tier with timing values\n *\n * @example\n * getCacheTier(\"items.categories.list\") → static (60 min stale)\n * getCacheTier(\"pricing.priceEngine.get\") → semiStatic (1 min stale)\n * getCacheTier(\"commerce.cartLine.add.create\") → none (0 stale)\n */\nexport function getCacheTier(\n methodPath: string,\n overrides?: { static?: CacheTierConfig; semiStatic?: CacheTierConfig },\n): ResolvedCacheTier {\n if (NO_CACHE_PATHS.some((p) => methodPath.startsWith(p))) {\n return DEFAULT_CACHE_TIERS.none;\n }\n\n if (STATIC_PATHS.some((p) => methodPath.startsWith(p))) {\n const base = DEFAULT_CACHE_TIERS.static;\n const tier = overrides?.static;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n }\n\n // Default: semiStatic\n const base = DEFAULT_CACHE_TIERS.semiStatic;\n const tier = overrides?.semiStatic;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n}\n","/**\n * Deterministic key generation utilities.\n *\n * stableStringify and fnv1a are the single source of truth —\n * augur-hooks and augur-server both import from here so cache keys\n * are guaranteed identical across client and server.\n */\n\n/**\n * JSON.stringify with sorted object keys for deterministic cache keys.\n * Ensures { a: 1, b: 2 } and { b: 2, a: 1 } produce the same string.\n */\nexport function stableStringify(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(\n (key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`,\n );\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * FNV-1a 32-bit hash. Fast non-cryptographic hash for cache keys.\n * Returns an 8-character zero-padded hex string.\n */\nexport function fnv1a(str: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Builds a deterministic query key from a method path and arguments.\n *\n * @example\n * buildQueryKey([\"items\", \"invMast\", \"get\"], [42])\n * → [\"items\", \"invMast\", \"get\", 42]\n *\n * buildQueryKey([\"pricing\", \"priceEngine\", \"get\"], [{ itemId: \"X\", customerId: 1 }])\n * → [\"pricing\", \"priceEngine\", \"get\", { itemId: \"X\", customerId: 1 }]\n */\nexport function buildQueryKey(path: string[], args: unknown[]): unknown[] {\n return [...path, ...args];\n}\n\n/**\n * Builds a deterministic cache key for Redis/CDN caching.\n *\n * Format: `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`\n *\n * @example\n * buildCacheKey(\"ampro:\", \"pricing.priceEngine.get\", [{ itemId: \"X\" }])\n * → \"ampro:sdk:pricing.priceEngine.get:a1b2c3d4\"\n */\nexport function buildCacheKey(\n prefix: string,\n methodPath: string,\n args: unknown[],\n): string {\n return `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`;\n}\n","/**\n * Utility functions for the proxy infrastructure.\n */\n\n/**\n * Walk an object by path array to find the leaf function.\n *\n * @example\n * resolveMethod(api, [\"items\", \"invMast\", \"stock\", \"get\"])\n * → api.items.invMast.stock.get\n */\nexport function resolveMethod(\n obj: unknown,\n path: string[],\n): (...args: unknown[]) => unknown {\n let current: unknown = obj;\n for (const segment of path) {\n if (current == null || typeof current !== \"object\") {\n throw new Error(\n `Cannot resolve method path \"${path.join(\".\")}\": ` +\n `\"${segment}\" is not accessible on ${typeof current}`,\n );\n }\n current = (current as Record<string, unknown>)[segment];\n }\n if (typeof current !== \"function\") {\n throw new Error(\n `Method path \"${path.join(\".\")}\" does not resolve to a function ` +\n `(got ${typeof current})`,\n );\n }\n return current as (...args: unknown[]) => unknown;\n}\n\n/**\n * Normalize arguments for deterministic cache/query keys.\n * Filters out undefined values from argument objects.\n */\nexport function stableArgs(args: unknown[]): unknown[] {\n return args.map((arg) => {\n if (arg === null || arg === undefined || typeof arg !== \"object\") return arg;\n if (Array.isArray(arg)) return arg;\n const obj = arg as Record<string, unknown>;\n const filtered: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n if (obj[key] !== undefined) {\n filtered[key] = obj[key];\n }\n }\n return filtered;\n });\n}\n","/**\n * Deep proxy factories — runtime SDK namespace mirroring.\n *\n * The same Proxy pattern that powers `createMockClient()` in the SDK\n * powers every downstream consumer. One proxy shape, multiple behaviors\n * via the handler callback.\n */\n\nimport { isReadMethod } from \"./classification\";\nimport { getCacheTier } from \"./cache\";\nimport type { ResolvedCacheTier } from \"./cache\";\nimport type { CacheTierConfig } from \"./shared-types\";\nimport { buildQueryKey, buildCacheKey, stableStringify, fnv1a } from \"./keys\";\nimport { resolveMethod, stableArgs } from \"./utils\";\nimport type { ProxyQueryOptions, ProxyMutationOptions } from \"./types\";\n\n/** Configuration for the options proxy (hooks). */\nexport interface OptionsProxyConfig {\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n}\n\n/** Context passed to the wrapCall hook. */\nexport interface WrapCallContext {\n /** Dot-separated SDK method path (e.g. \"joomla.users.verifyPassword.create\"). */\n methodPath: string;\n /** Arguments to pass to the SDK method (after pre-transform). */\n args: unknown[];\n /** Calls the underlying SDK method. */\n sdkCall: (...a: unknown[]) => Promise<unknown>;\n /** Resolved cache tier for this method path. */\n tier: ResolvedCacheTier;\n /** True when the leaf method name is a read (get, list, lookup, search, suggest). */\n isRead: boolean;\n}\n\n/** Configuration for the actions proxy (server). */\nexport interface ActionsProxyConfig {\n /** Cache key prefix (e.g. \"ampro:\"). */\n cachePrefix?: string;\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n /** Pre/post transforms per method path. */\n transforms?: Record<\n string,\n {\n pre?: (args: unknown[]) => unknown[];\n post?: (result: unknown) => unknown;\n }\n >;\n /**\n * Optional middleware hook called instead of the raw SDK call.\n * Lets consumers inject caching, logging, or other cross-cutting concerns\n * without augur-core needing framework dependencies.\n */\n wrapCall?: (ctx: WrapCallContext) => Promise<unknown>;\n}\n\n/**\n * Creates a deep proxy that intercepts property access to build a method\n * path, then calls the handler when the proxy is invoked as a function.\n *\n * This is the core mechanism. `createOptionsProxy` and `createActionsProxy`\n * are thin wrappers that provide different handlers.\n */\nexport function createDeepProxy<TResult>(\n handler: (path: string[], args: unknown[]) => TResult,\n path: string[] = [],\n): unknown {\n /* v8 ignore next -- placeholder body, only the Proxy traps execute */\n const callable = function () {};\n\n return new Proxy(callable, {\n get(_target, prop: string | symbol) {\n if (typeof prop === \"symbol\") return undefined;\n return createDeepProxy(handler, [...path, prop]);\n },\n apply(_target, _thisArg, args: unknown[]) {\n return handler(path, args);\n },\n });\n}\n\n/**\n * Creates a proxy that returns TanStack Query options for every SDK method.\n *\n * Read methods (get, list, lookup, search, suggest) return ProxyQueryOptions.\n * Write methods (create, update, delete, etc.) return ProxyMutationOptions.\n *\n * @param api The SDK client instance\n * @param config Optional cache configuration\n * @returns Proxy mirroring the SDK with query/mutation options at every leaf\n *\n * @example\n * const q = createOptionsProxy(api);\n * const opts = q.items.invMast.stock.get(42);\n * // opts.queryKey → [\"items\", \"invMast\", \"stock\", \"get\", 42]\n * // opts.queryFn → () => api.items.invMast.stock.get(42)\n * // opts.staleTime → 60000 (semiStatic default)\n */\nexport function createOptionsProxy<TApi extends object>(\n api: TApi,\n config?: OptionsProxyConfig,\n): unknown {\n return createDeepProxy(\n (\n path: string[],\n args: unknown[],\n ): ProxyQueryOptions<unknown> | ProxyMutationOptions<unknown, unknown[]> => {\n const methodName = path[path.length - 1]!;\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const normalizedArgs = stableArgs(args);\n\n if (isReadMethod(methodName)) {\n const tier = getCacheTier(methodPath, config?.cache);\n return {\n queryKey: buildQueryKey(path, normalizedArgs),\n queryFn: () => sdkMethod(...args) as Promise<unknown>,\n staleTime: tier.staleTime,\n gcTime: tier.gcTime,\n };\n }\n\n return {\n mutationKey: path,\n mutationFn: (...mutationArgs: unknown[]) =>\n sdkMethod(...mutationArgs) as Promise<unknown>,\n };\n },\n );\n}\n\n/**\n * Creates a proxy that wraps every SDK method as a direct async action.\n *\n * For read methods, the result is cached using the cache key builder.\n * For write methods, the call passes through directly.\n *\n * @param api The SDK client instance\n * @param config Optional cache and transform configuration\n * @returns Proxy mirroring the SDK with cached/transformed actions at every leaf\n *\n * @example\n * const actions = createActionsProxy(api, { cachePrefix: \"ampro:\" });\n * const stock = await actions.items.invMast.stock.get(42);\n */\nexport function createActionsProxy<TApi extends object>(\n api: TApi,\n config?: ActionsProxyConfig,\n): unknown {\n return createDeepProxy(async (path: string[], args: unknown[]) => {\n const methodPath = path.join(\".\");\n const methodName = path[path.length - 1]!;\n const sdkMethod = resolveMethod(api, path);\n const transform = config?.transforms?.[methodPath];\n\n const finalArgs = transform?.pre ? transform.pre(args) : args;\n\n let result: unknown;\n if (config?.wrapCall) {\n const tier = getCacheTier(methodPath, config.cache);\n result = await config.wrapCall({\n methodPath,\n args: finalArgs,\n sdkCall: (...a: unknown[]) => sdkMethod(...a) as Promise<unknown>,\n tier,\n isRead: isReadMethod(methodName),\n });\n } else {\n result = await (sdkMethod(...finalArgs) as Promise<unknown>);\n }\n\n return transform?.post ? transform.post(result) : result;\n });\n}\n\n// Re-export key utilities for consumers who need to build keys manually\nexport { buildQueryKey, buildCacheKey, stableStringify, fnv1a };\n"]}
package/dist/index.d.cts CHANGED
@@ -61,6 +61,44 @@ type ActionResult<T> = {
61
61
  error: string;
62
62
  };
63
63
 
64
+ /**
65
+ * Cache tier resolution — maps SDK method paths to cache tiers.
66
+ *
67
+ * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).
68
+ */
69
+
70
+ /** Internal resolved cache tier with all timing values. */
71
+ interface ResolvedCacheTier {
72
+ staleTime: number;
73
+ gcTime: number;
74
+ edgeCache?: number | string;
75
+ redisTtl?: number;
76
+ }
77
+ /** Cache tier configuration with defaults for all tiers. */
78
+ interface CacheTierDefaults {
79
+ static: ResolvedCacheTier;
80
+ semiStatic: ResolvedCacheTier;
81
+ none: ResolvedCacheTier;
82
+ }
83
+ /** Default cache tier values. */
84
+ declare const DEFAULT_CACHE_TIERS: CacheTierDefaults;
85
+ /**
86
+ * Resolves the cache tier for a given SDK method path.
87
+ *
88
+ * @param methodPath Dot-separated SDK method path (e.g. "items.invMast.stock.get")
89
+ * @param overrides Optional per-tier overrides from consumer config
90
+ * @returns Resolved cache tier with timing values
91
+ *
92
+ * @example
93
+ * getCacheTier("items.categories.list") → static (60 min stale)
94
+ * getCacheTier("pricing.priceEngine.get") → semiStatic (1 min stale)
95
+ * getCacheTier("commerce.cartLine.add.create") → none (0 stale)
96
+ */
97
+ declare function getCacheTier(methodPath: string, overrides?: {
98
+ static?: CacheTierConfig;
99
+ semiStatic?: CacheTierConfig;
100
+ }): ResolvedCacheTier;
101
+
64
102
  /**
65
103
  * Deterministic key generation utilities.
66
104
  *
@@ -116,6 +154,19 @@ interface OptionsProxyConfig {
116
154
  semiStatic?: CacheTierConfig;
117
155
  };
118
156
  }
157
+ /** Context passed to the wrapCall hook. */
158
+ interface WrapCallContext {
159
+ /** Dot-separated SDK method path (e.g. "joomla.users.verifyPassword.create"). */
160
+ methodPath: string;
161
+ /** Arguments to pass to the SDK method (after pre-transform). */
162
+ args: unknown[];
163
+ /** Calls the underlying SDK method. */
164
+ sdkCall: (...a: unknown[]) => Promise<unknown>;
165
+ /** Resolved cache tier for this method path. */
166
+ tier: ResolvedCacheTier;
167
+ /** True when the leaf method name is a read (get, list, lookup, search, suggest). */
168
+ isRead: boolean;
169
+ }
119
170
  /** Configuration for the actions proxy (server). */
120
171
  interface ActionsProxyConfig {
121
172
  /** Cache key prefix (e.g. "ampro:"). */
@@ -130,6 +181,12 @@ interface ActionsProxyConfig {
130
181
  pre?: (args: unknown[]) => unknown[];
131
182
  post?: (result: unknown) => unknown;
132
183
  }>;
184
+ /**
185
+ * Optional middleware hook called instead of the raw SDK call.
186
+ * Lets consumers inject caching, logging, or other cross-cutting concerns
187
+ * without augur-core needing framework dependencies.
188
+ */
189
+ wrapCall?: (ctx: WrapCallContext) => Promise<unknown>;
133
190
  }
134
191
  /**
135
192
  * Creates a deep proxy that intercepts property access to build a method
@@ -192,44 +249,6 @@ declare function isReadMethod(methodName: string): boolean;
192
249
  */
193
250
  declare function isWriteMethod(methodName: string): boolean;
194
251
 
195
- /**
196
- * Cache tier resolution — maps SDK method paths to cache tiers.
197
- *
198
- * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).
199
- */
200
-
201
- /** Internal resolved cache tier with all timing values. */
202
- interface ResolvedCacheTier {
203
- staleTime: number;
204
- gcTime: number;
205
- edgeCache?: number | string;
206
- redisTtl?: number;
207
- }
208
- /** Cache tier configuration with defaults for all tiers. */
209
- interface CacheTierDefaults {
210
- static: ResolvedCacheTier;
211
- semiStatic: ResolvedCacheTier;
212
- none: ResolvedCacheTier;
213
- }
214
- /** Default cache tier values. */
215
- declare const DEFAULT_CACHE_TIERS: CacheTierDefaults;
216
- /**
217
- * Resolves the cache tier for a given SDK method path.
218
- *
219
- * @param methodPath Dot-separated SDK method path (e.g. "items.invMast.stock.get")
220
- * @param overrides Optional per-tier overrides from consumer config
221
- * @returns Resolved cache tier with timing values
222
- *
223
- * @example
224
- * getCacheTier("items.categories.list") → static (60 min stale)
225
- * getCacheTier("pricing.priceEngine.get") → semiStatic (1 min stale)
226
- * getCacheTier("commerce.cartLine.add.create") → none (0 stale)
227
- */
228
- declare function getCacheTier(methodPath: string, overrides?: {
229
- static?: CacheTierConfig;
230
- semiStatic?: CacheTierConfig;
231
- }): ResolvedCacheTier;
232
-
233
252
  /**
234
253
  * Utility functions for the proxy infrastructure.
235
254
  */
@@ -295,4 +314,4 @@ type DeepActions<T> = {
295
314
  [K in keyof T]: T[K] extends (...args: infer A) => Promise<infer R> ? (...args: A) => Promise<R> : T[K] extends object ? DeepActions<T[K]> : never;
296
315
  };
297
316
 
298
- export { type ActionResult, type ActionsProxyConfig, type AugurAuthContext, type CacheConfig, type CacheProvider, type CacheTierConfig, type CacheTierDefaults, DEFAULT_CACHE_TIERS, type DeepActions, type DeepQueryOptions, type EdgeCacheValue, type InfiniteScrollPage, type IsReadMethod, type OptionsProxyConfig, type ProxyMutationOptions, type ProxyQueryOptions, type ResolvedCacheTier, buildCacheKey, buildQueryKey, createActionsProxy, createDeepProxy, createOptionsProxy, fnv1a, getCacheTier, isReadMethod, isWriteMethod, resolveMethod, stableArgs, stableStringify };
317
+ export { type ActionResult, type ActionsProxyConfig, type AugurAuthContext, type CacheConfig, type CacheProvider, type CacheTierConfig, type CacheTierDefaults, DEFAULT_CACHE_TIERS, type DeepActions, type DeepQueryOptions, type EdgeCacheValue, type InfiniteScrollPage, type IsReadMethod, type OptionsProxyConfig, type ProxyMutationOptions, type ProxyQueryOptions, type ResolvedCacheTier, type WrapCallContext, buildCacheKey, buildQueryKey, createActionsProxy, createDeepProxy, createOptionsProxy, fnv1a, getCacheTier, isReadMethod, isWriteMethod, resolveMethod, stableArgs, stableStringify };
package/dist/index.d.ts CHANGED
@@ -61,6 +61,44 @@ type ActionResult<T> = {
61
61
  error: string;
62
62
  };
63
63
 
64
+ /**
65
+ * Cache tier resolution — maps SDK method paths to cache tiers.
66
+ *
67
+ * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).
68
+ */
69
+
70
+ /** Internal resolved cache tier with all timing values. */
71
+ interface ResolvedCacheTier {
72
+ staleTime: number;
73
+ gcTime: number;
74
+ edgeCache?: number | string;
75
+ redisTtl?: number;
76
+ }
77
+ /** Cache tier configuration with defaults for all tiers. */
78
+ interface CacheTierDefaults {
79
+ static: ResolvedCacheTier;
80
+ semiStatic: ResolvedCacheTier;
81
+ none: ResolvedCacheTier;
82
+ }
83
+ /** Default cache tier values. */
84
+ declare const DEFAULT_CACHE_TIERS: CacheTierDefaults;
85
+ /**
86
+ * Resolves the cache tier for a given SDK method path.
87
+ *
88
+ * @param methodPath Dot-separated SDK method path (e.g. "items.invMast.stock.get")
89
+ * @param overrides Optional per-tier overrides from consumer config
90
+ * @returns Resolved cache tier with timing values
91
+ *
92
+ * @example
93
+ * getCacheTier("items.categories.list") → static (60 min stale)
94
+ * getCacheTier("pricing.priceEngine.get") → semiStatic (1 min stale)
95
+ * getCacheTier("commerce.cartLine.add.create") → none (0 stale)
96
+ */
97
+ declare function getCacheTier(methodPath: string, overrides?: {
98
+ static?: CacheTierConfig;
99
+ semiStatic?: CacheTierConfig;
100
+ }): ResolvedCacheTier;
101
+
64
102
  /**
65
103
  * Deterministic key generation utilities.
66
104
  *
@@ -116,6 +154,19 @@ interface OptionsProxyConfig {
116
154
  semiStatic?: CacheTierConfig;
117
155
  };
118
156
  }
157
+ /** Context passed to the wrapCall hook. */
158
+ interface WrapCallContext {
159
+ /** Dot-separated SDK method path (e.g. "joomla.users.verifyPassword.create"). */
160
+ methodPath: string;
161
+ /** Arguments to pass to the SDK method (after pre-transform). */
162
+ args: unknown[];
163
+ /** Calls the underlying SDK method. */
164
+ sdkCall: (...a: unknown[]) => Promise<unknown>;
165
+ /** Resolved cache tier for this method path. */
166
+ tier: ResolvedCacheTier;
167
+ /** True when the leaf method name is a read (get, list, lookup, search, suggest). */
168
+ isRead: boolean;
169
+ }
119
170
  /** Configuration for the actions proxy (server). */
120
171
  interface ActionsProxyConfig {
121
172
  /** Cache key prefix (e.g. "ampro:"). */
@@ -130,6 +181,12 @@ interface ActionsProxyConfig {
130
181
  pre?: (args: unknown[]) => unknown[];
131
182
  post?: (result: unknown) => unknown;
132
183
  }>;
184
+ /**
185
+ * Optional middleware hook called instead of the raw SDK call.
186
+ * Lets consumers inject caching, logging, or other cross-cutting concerns
187
+ * without augur-core needing framework dependencies.
188
+ */
189
+ wrapCall?: (ctx: WrapCallContext) => Promise<unknown>;
133
190
  }
134
191
  /**
135
192
  * Creates a deep proxy that intercepts property access to build a method
@@ -192,44 +249,6 @@ declare function isReadMethod(methodName: string): boolean;
192
249
  */
193
250
  declare function isWriteMethod(methodName: string): boolean;
194
251
 
195
- /**
196
- * Cache tier resolution — maps SDK method paths to cache tiers.
197
- *
198
- * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).
199
- */
200
-
201
- /** Internal resolved cache tier with all timing values. */
202
- interface ResolvedCacheTier {
203
- staleTime: number;
204
- gcTime: number;
205
- edgeCache?: number | string;
206
- redisTtl?: number;
207
- }
208
- /** Cache tier configuration with defaults for all tiers. */
209
- interface CacheTierDefaults {
210
- static: ResolvedCacheTier;
211
- semiStatic: ResolvedCacheTier;
212
- none: ResolvedCacheTier;
213
- }
214
- /** Default cache tier values. */
215
- declare const DEFAULT_CACHE_TIERS: CacheTierDefaults;
216
- /**
217
- * Resolves the cache tier for a given SDK method path.
218
- *
219
- * @param methodPath Dot-separated SDK method path (e.g. "items.invMast.stock.get")
220
- * @param overrides Optional per-tier overrides from consumer config
221
- * @returns Resolved cache tier with timing values
222
- *
223
- * @example
224
- * getCacheTier("items.categories.list") → static (60 min stale)
225
- * getCacheTier("pricing.priceEngine.get") → semiStatic (1 min stale)
226
- * getCacheTier("commerce.cartLine.add.create") → none (0 stale)
227
- */
228
- declare function getCacheTier(methodPath: string, overrides?: {
229
- static?: CacheTierConfig;
230
- semiStatic?: CacheTierConfig;
231
- }): ResolvedCacheTier;
232
-
233
252
  /**
234
253
  * Utility functions for the proxy infrastructure.
235
254
  */
@@ -295,4 +314,4 @@ type DeepActions<T> = {
295
314
  [K in keyof T]: T[K] extends (...args: infer A) => Promise<infer R> ? (...args: A) => Promise<R> : T[K] extends object ? DeepActions<T[K]> : never;
296
315
  };
297
316
 
298
- export { type ActionResult, type ActionsProxyConfig, type AugurAuthContext, type CacheConfig, type CacheProvider, type CacheTierConfig, type CacheTierDefaults, DEFAULT_CACHE_TIERS, type DeepActions, type DeepQueryOptions, type EdgeCacheValue, type InfiniteScrollPage, type IsReadMethod, type OptionsProxyConfig, type ProxyMutationOptions, type ProxyQueryOptions, type ResolvedCacheTier, buildCacheKey, buildQueryKey, createActionsProxy, createDeepProxy, createOptionsProxy, fnv1a, getCacheTier, isReadMethod, isWriteMethod, resolveMethod, stableArgs, stableStringify };
317
+ export { type ActionResult, type ActionsProxyConfig, type AugurAuthContext, type CacheConfig, type CacheProvider, type CacheTierConfig, type CacheTierDefaults, DEFAULT_CACHE_TIERS, type DeepActions, type DeepQueryOptions, type EdgeCacheValue, type InfiniteScrollPage, type IsReadMethod, type OptionsProxyConfig, type ProxyMutationOptions, type ProxyQueryOptions, type ResolvedCacheTier, type WrapCallContext, buildCacheKey, buildQueryKey, createActionsProxy, createDeepProxy, createOptionsProxy, fnv1a, getCacheTier, isReadMethod, isWriteMethod, resolveMethod, stableArgs, stableStringify };
package/dist/index.js CHANGED
@@ -180,10 +180,23 @@ function createOptionsProxy(api, config) {
180
180
  function createActionsProxy(api, config) {
181
181
  return createDeepProxy(async (path, args) => {
182
182
  const methodPath = path.join(".");
183
+ const methodName = path[path.length - 1];
183
184
  const sdkMethod = resolveMethod(api, path);
184
185
  const transform = config?.transforms?.[methodPath];
185
186
  const finalArgs = transform?.pre ? transform.pre(args) : args;
186
- const result = await sdkMethod(...finalArgs);
187
+ let result;
188
+ if (config?.wrapCall) {
189
+ const tier = getCacheTier(methodPath, config.cache);
190
+ result = await config.wrapCall({
191
+ methodPath,
192
+ args: finalArgs,
193
+ sdkCall: (...a) => sdkMethod(...a),
194
+ tier,
195
+ isRead: isReadMethod(methodName)
196
+ });
197
+ } else {
198
+ result = await sdkMethod(...finalArgs);
199
+ }
187
200
  return transform?.post ? transform.post(result) : result;
188
201
  });
189
202
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/classification.ts","../src/cache.ts","../src/keys.ts","../src/utils.ts","../src/proxy.ts"],"sourcesContent":["/**\n * Method classification — determines whether an SDK method is a read (GET)\n * or write (POST/PUT/DELETE) based on its leaf method name.\n *\n * Read methods produce UseQueryOptions; write methods produce UseMutationOptions.\n */\n\nconst READ_METHODS = new Set([\"get\", \"list\", \"lookup\", \"search\", \"suggest\"]);\n\n/**\n * Returns true if the leaf method name represents a read (GET) operation.\n *\n * Read methods: get, list, lookup, search, suggest\n */\nexport function isReadMethod(methodName: string): boolean {\n return READ_METHODS.has(methodName);\n}\n\n/**\n * Returns true if the leaf method name represents a write (POST/PUT/DELETE) operation.\n *\n * Write methods: create, update, delete, enable, and anything not in the read set.\n */\nexport function isWriteMethod(methodName: string): boolean {\n return !READ_METHODS.has(methodName);\n}\n","/**\n * Cache tier resolution — maps SDK method paths to cache tiers.\n *\n * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).\n */\n\nimport type { CacheTierConfig } from \"./shared-types\";\n\n/** Internal resolved cache tier with all timing values. */\nexport interface ResolvedCacheTier {\n staleTime: number;\n gcTime: number;\n edgeCache?: number | string;\n redisTtl?: number;\n}\n\n/** Cache tier configuration with defaults for all tiers. */\nexport interface CacheTierDefaults {\n static: ResolvedCacheTier;\n semiStatic: ResolvedCacheTier;\n none: ResolvedCacheTier;\n}\n\n/** Default cache tier values. */\nexport const DEFAULT_CACHE_TIERS: CacheTierDefaults = {\n static: {\n staleTime: 60 * 60 * 1000, // 60 min\n gcTime: 2 * 60 * 60 * 1000, // 120 min\n edgeCache: 8,\n redisTtl: 28800, // 8 hours\n },\n semiStatic: {\n staleTime: 60 * 1000, // 1 min\n gcTime: 5 * 60 * 1000, // 5 min\n edgeCache: 1,\n redisTtl: 3600, // 1 hour\n },\n none: {\n staleTime: 0,\n gcTime: 0,\n },\n};\n\n/** Paths that should use the static cache tier. */\nconst STATIC_PATHS = [\n \"agrSite.settings\",\n \"agrSite.metaFiles\",\n \"agrSite.geoCodesPostalCodes\",\n \"items.categories\",\n \"items.itemCategory\",\n \"items.brands\",\n \"items.attributeGroups\",\n \"items.attributes\",\n \"p21Core.company\",\n \"p21Core.location\",\n \"p21Core.paymentTypes\",\n \"p21Core.codeP21\",\n \"p21Core.cashDrawer\",\n \"joomla.menu\",\n \"joomla.tags\",\n \"joomla.userGroups\",\n \"legacy.state\",\n];\n\n/** Paths that should not be cached. */\nconst NO_CACHE_PATHS = [\"commerce\"];\n\n/**\n * Resolves the cache tier for a given SDK method path.\n *\n * @param methodPath Dot-separated SDK method path (e.g. \"items.invMast.stock.get\")\n * @param overrides Optional per-tier overrides from consumer config\n * @returns Resolved cache tier with timing values\n *\n * @example\n * getCacheTier(\"items.categories.list\") → static (60 min stale)\n * getCacheTier(\"pricing.priceEngine.get\") → semiStatic (1 min stale)\n * getCacheTier(\"commerce.cartLine.add.create\") → none (0 stale)\n */\nexport function getCacheTier(\n methodPath: string,\n overrides?: { static?: CacheTierConfig; semiStatic?: CacheTierConfig },\n): ResolvedCacheTier {\n if (NO_CACHE_PATHS.some((p) => methodPath.startsWith(p))) {\n return DEFAULT_CACHE_TIERS.none;\n }\n\n if (STATIC_PATHS.some((p) => methodPath.startsWith(p))) {\n const base = DEFAULT_CACHE_TIERS.static;\n const tier = overrides?.static;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n }\n\n // Default: semiStatic\n const base = DEFAULT_CACHE_TIERS.semiStatic;\n const tier = overrides?.semiStatic;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n}\n","/**\n * Deterministic key generation utilities.\n *\n * stableStringify and fnv1a are the single source of truth —\n * augur-hooks and augur-server both import from here so cache keys\n * are guaranteed identical across client and server.\n */\n\n/**\n * JSON.stringify with sorted object keys for deterministic cache keys.\n * Ensures { a: 1, b: 2 } and { b: 2, a: 1 } produce the same string.\n */\nexport function stableStringify(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(\n (key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`,\n );\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * FNV-1a 32-bit hash. Fast non-cryptographic hash for cache keys.\n * Returns an 8-character zero-padded hex string.\n */\nexport function fnv1a(str: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Builds a deterministic query key from a method path and arguments.\n *\n * @example\n * buildQueryKey([\"items\", \"invMast\", \"get\"], [42])\n * → [\"items\", \"invMast\", \"get\", 42]\n *\n * buildQueryKey([\"pricing\", \"priceEngine\", \"get\"], [{ itemId: \"X\", customerId: 1 }])\n * → [\"pricing\", \"priceEngine\", \"get\", { itemId: \"X\", customerId: 1 }]\n */\nexport function buildQueryKey(path: string[], args: unknown[]): unknown[] {\n return [...path, ...args];\n}\n\n/**\n * Builds a deterministic cache key for Redis/CDN caching.\n *\n * Format: `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`\n *\n * @example\n * buildCacheKey(\"ampro:\", \"pricing.priceEngine.get\", [{ itemId: \"X\" }])\n * → \"ampro:sdk:pricing.priceEngine.get:a1b2c3d4\"\n */\nexport function buildCacheKey(\n prefix: string,\n methodPath: string,\n args: unknown[],\n): string {\n return `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`;\n}\n","/**\n * Utility functions for the proxy infrastructure.\n */\n\n/**\n * Walk an object by path array to find the leaf function.\n *\n * @example\n * resolveMethod(api, [\"items\", \"invMast\", \"stock\", \"get\"])\n * → api.items.invMast.stock.get\n */\nexport function resolveMethod(\n obj: unknown,\n path: string[],\n): (...args: unknown[]) => unknown {\n let current: unknown = obj;\n for (const segment of path) {\n if (current == null || typeof current !== \"object\") {\n throw new Error(\n `Cannot resolve method path \"${path.join(\".\")}\": ` +\n `\"${segment}\" is not accessible on ${typeof current}`,\n );\n }\n current = (current as Record<string, unknown>)[segment];\n }\n if (typeof current !== \"function\") {\n throw new Error(\n `Method path \"${path.join(\".\")}\" does not resolve to a function ` +\n `(got ${typeof current})`,\n );\n }\n return current as (...args: unknown[]) => unknown;\n}\n\n/**\n * Normalize arguments for deterministic cache/query keys.\n * Filters out undefined values from argument objects.\n */\nexport function stableArgs(args: unknown[]): unknown[] {\n return args.map((arg) => {\n if (arg === null || arg === undefined || typeof arg !== \"object\") return arg;\n if (Array.isArray(arg)) return arg;\n const obj = arg as Record<string, unknown>;\n const filtered: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n if (obj[key] !== undefined) {\n filtered[key] = obj[key];\n }\n }\n return filtered;\n });\n}\n","/**\n * Deep proxy factories — runtime SDK namespace mirroring.\n *\n * The same Proxy pattern that powers `createMockClient()` in the SDK\n * powers every downstream consumer. One proxy shape, multiple behaviors\n * via the handler callback.\n */\n\nimport { isReadMethod } from \"./classification\";\nimport { getCacheTier } from \"./cache\";\nimport type { CacheTierConfig } from \"./shared-types\";\nimport { buildQueryKey, buildCacheKey, stableStringify, fnv1a } from \"./keys\";\nimport { resolveMethod, stableArgs } from \"./utils\";\nimport type { ProxyQueryOptions, ProxyMutationOptions } from \"./types\";\n\n/** Configuration for the options proxy (hooks). */\nexport interface OptionsProxyConfig {\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n}\n\n/** Configuration for the actions proxy (server). */\nexport interface ActionsProxyConfig {\n /** Cache key prefix (e.g. \"ampro:\"). */\n cachePrefix?: string;\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n /** Pre/post transforms per method path. */\n transforms?: Record<\n string,\n {\n pre?: (args: unknown[]) => unknown[];\n post?: (result: unknown) => unknown;\n }\n >;\n}\n\n/**\n * Creates a deep proxy that intercepts property access to build a method\n * path, then calls the handler when the proxy is invoked as a function.\n *\n * This is the core mechanism. `createOptionsProxy` and `createActionsProxy`\n * are thin wrappers that provide different handlers.\n */\nexport function createDeepProxy<TResult>(\n handler: (path: string[], args: unknown[]) => TResult,\n path: string[] = [],\n): unknown {\n /* v8 ignore next -- placeholder body, only the Proxy traps execute */\n const callable = function () {};\n\n return new Proxy(callable, {\n get(_target, prop: string | symbol) {\n if (typeof prop === \"symbol\") return undefined;\n return createDeepProxy(handler, [...path, prop]);\n },\n apply(_target, _thisArg, args: unknown[]) {\n return handler(path, args);\n },\n });\n}\n\n/**\n * Creates a proxy that returns TanStack Query options for every SDK method.\n *\n * Read methods (get, list, lookup, search, suggest) return ProxyQueryOptions.\n * Write methods (create, update, delete, etc.) return ProxyMutationOptions.\n *\n * @param api The SDK client instance\n * @param config Optional cache configuration\n * @returns Proxy mirroring the SDK with query/mutation options at every leaf\n *\n * @example\n * const q = createOptionsProxy(api);\n * const opts = q.items.invMast.stock.get(42);\n * // opts.queryKey → [\"items\", \"invMast\", \"stock\", \"get\", 42]\n * // opts.queryFn → () => api.items.invMast.stock.get(42)\n * // opts.staleTime → 60000 (semiStatic default)\n */\nexport function createOptionsProxy<TApi extends object>(\n api: TApi,\n config?: OptionsProxyConfig,\n): unknown {\n return createDeepProxy(\n (\n path: string[],\n args: unknown[],\n ): ProxyQueryOptions<unknown> | ProxyMutationOptions<unknown, unknown[]> => {\n const methodName = path[path.length - 1]!;\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const normalizedArgs = stableArgs(args);\n\n if (isReadMethod(methodName)) {\n const tier = getCacheTier(methodPath, config?.cache);\n return {\n queryKey: buildQueryKey(path, normalizedArgs),\n queryFn: () => sdkMethod(...args) as Promise<unknown>,\n staleTime: tier.staleTime,\n gcTime: tier.gcTime,\n };\n }\n\n return {\n mutationKey: path,\n mutationFn: (...mutationArgs: unknown[]) =>\n sdkMethod(...mutationArgs) as Promise<unknown>,\n };\n },\n );\n}\n\n/**\n * Creates a proxy that wraps every SDK method as a direct async action.\n *\n * For read methods, the result is cached using the cache key builder.\n * For write methods, the call passes through directly.\n *\n * @param api The SDK client instance\n * @param config Optional cache and transform configuration\n * @returns Proxy mirroring the SDK with cached/transformed actions at every leaf\n *\n * @example\n * const actions = createActionsProxy(api, { cachePrefix: \"ampro:\" });\n * const stock = await actions.items.invMast.stock.get(42);\n */\nexport function createActionsProxy<TApi extends object>(\n api: TApi,\n config?: ActionsProxyConfig,\n): unknown {\n return createDeepProxy(async (path: string[], args: unknown[]) => {\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const transform = config?.transforms?.[methodPath];\n\n const finalArgs = transform?.pre ? transform.pre(args) : args;\n const result = await (sdkMethod(...finalArgs) as Promise<unknown>);\n return transform?.post ? transform.post(result) : result;\n });\n}\n\n// Re-export key utilities for consumers who need to build keys manually\nexport { buildQueryKey, buildCacheKey, stableStringify, fnv1a };\n"],"mappings":";AAOA,IAAM,eAAe,oBAAI,IAAI,CAAC,OAAO,QAAQ,UAAU,UAAU,SAAS,CAAC;AAOpE,SAAS,aAAa,YAA6B;AACxD,SAAO,aAAa,IAAI,UAAU;AACpC;AAOO,SAAS,cAAc,YAA6B;AACzD,SAAO,CAAC,aAAa,IAAI,UAAU;AACrC;;;ACDO,IAAM,sBAAyC;AAAA,EACpD,QAAQ;AAAA,IACN,WAAW,KAAK,KAAK;AAAA;AAAA,IACrB,QAAQ,IAAI,KAAK,KAAK;AAAA;AAAA,IACtB,WAAW;AAAA,IACX,UAAU;AAAA;AAAA,EACZ;AAAA,EACA,YAAY;AAAA,IACV,WAAW,KAAK;AAAA;AAAA,IAChB,QAAQ,IAAI,KAAK;AAAA;AAAA,IACjB,WAAW;AAAA,IACX,UAAU;AAAA;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACF;AAGA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,iBAAiB,CAAC,UAAU;AAc3B,SAAS,aACd,YACA,WACmB;AACnB,MAAI,eAAe,KAAK,CAAC,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG;AACxD,WAAO,oBAAoB;AAAA,EAC7B;AAEA,MAAI,aAAa,KAAK,CAAC,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG;AACtD,UAAMA,QAAO,oBAAoB;AACjC,UAAMC,QAAO,WAAW;AACxB,QAAI,CAACA,MAAM,QAAOD;AAClB,WAAO;AAAA,MACL,WAAWC,MAAK,aAAaD,MAAK;AAAA,MAClC,QAAQC,MAAK,UAAUD,MAAK;AAAA,MAC5B,WAAWC,MAAK,aAAaD,MAAK;AAAA,MAClC,UAAUC,MAAK,SAASD,MAAK;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,OAAO,oBAAoB;AACjC,QAAM,OAAO,WAAW;AACxB,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO;AAAA,IACL,WAAW,KAAK,aAAa,KAAK;AAAA,IAClC,QAAQ,KAAK,UAAU,KAAK;AAAA,IAC5B,WAAW,KAAK,aAAa,KAAK;AAAA,IAClC,UAAU,KAAK,SAAS,KAAK;AAAA,EAC/B;AACF;;;ACjGO,SAAS,gBAAgB,OAAwB;AACtD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,KAAK,UAAU,KAAK;AACtE,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC1D,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAAA,EACjD;AACA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AACnC,QAAM,UAAU,KAAK;AAAA,IACnB,CAAC,QAAQ,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,IAAI,GAAG,CAAC,CAAC;AAAA,EAC9D;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAMO,SAAS,MAAM,KAAqB;AACzC,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,SAAK,IAAI,WAAW,CAAC;AACrB,QAAI,KAAK,KAAK,GAAG,QAAU;AAAA,EAC7B;AACA,UAAQ,MAAM,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC/C;AAYO,SAAS,cAAc,MAAgB,MAA4B;AACxE,SAAO,CAAC,GAAG,MAAM,GAAG,IAAI;AAC1B;AAWO,SAAS,cACd,QACA,YACA,MACQ;AACR,SAAO,GAAG,MAAM,OAAO,UAAU,IAAI,MAAM,gBAAgB,IAAI,CAAC,CAAC;AACnE;;;ACzDO,SAAS,cACd,KACA,MACiC;AACjC,MAAI,UAAmB;AACvB,aAAW,WAAW,MAAM;AAC1B,QAAI,WAAW,QAAQ,OAAO,YAAY,UAAU;AAClD,YAAM,IAAI;AAAA,QACR,+BAA+B,KAAK,KAAK,GAAG,CAAC,OACvC,OAAO,0BAA0B,OAAO,OAAO;AAAA,MACvD;AAAA,IACF;AACA,cAAW,QAAoC,OAAO;AAAA,EACxD;AACA,MAAI,OAAO,YAAY,YAAY;AACjC,UAAM,IAAI;AAAA,MACR,gBAAgB,KAAK,KAAK,GAAG,CAAC,yCACpB,OAAO,OAAO;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,WAAW,MAA4B;AACrD,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,QAAI,QAAQ,QAAQ,QAAQ,UAAa,OAAO,QAAQ,SAAU,QAAO;AACzE,QAAI,MAAM,QAAQ,GAAG,EAAG,QAAO;AAC/B,UAAM,MAAM;AACZ,UAAM,WAAoC,CAAC;AAC3C,eAAW,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK,GAAG;AACzC,UAAI,IAAI,GAAG,MAAM,QAAW;AAC1B,iBAAS,GAAG,IAAI,IAAI,GAAG;AAAA,MACzB;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;;;ACDO,SAAS,gBACd,SACA,OAAiB,CAAC,GACT;AAET,QAAM,WAAW,WAAY;AAAA,EAAC;AAE9B,SAAO,IAAI,MAAM,UAAU;AAAA,IACzB,IAAI,SAAS,MAAuB;AAClC,UAAI,OAAO,SAAS,SAAU,QAAO;AACrC,aAAO,gBAAgB,SAAS,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IACjD;AAAA,IACA,MAAM,SAAS,UAAU,MAAiB;AACxC,aAAO,QAAQ,MAAM,IAAI;AAAA,IAC3B;AAAA,EACF,CAAC;AACH;AAmBO,SAAS,mBACd,KACA,QACS;AACT,SAAO;AAAA,IACL,CACE,MACA,SAC0E;AAC1E,YAAM,aAAa,KAAK,KAAK,SAAS,CAAC;AACvC,YAAM,aAAa,KAAK,KAAK,GAAG;AAChC,YAAM,YAAY,cAAc,KAAK,IAAI;AACzC,YAAM,iBAAiB,WAAW,IAAI;AAEtC,UAAI,aAAa,UAAU,GAAG;AAC5B,cAAM,OAAO,aAAa,YAAY,QAAQ,KAAK;AACnD,eAAO;AAAA,UACL,UAAU,cAAc,MAAM,cAAc;AAAA,UAC5C,SAAS,MAAM,UAAU,GAAG,IAAI;AAAA,UAChC,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,QACf;AAAA,MACF;AAEA,aAAO;AAAA,QACL,aAAa;AAAA,QACb,YAAY,IAAI,iBACd,UAAU,GAAG,YAAY;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;AAgBO,SAAS,mBACd,KACA,QACS;AACT,SAAO,gBAAgB,OAAO,MAAgB,SAAoB;AAChE,UAAM,aAAa,KAAK,KAAK,GAAG;AAChC,UAAM,YAAY,cAAc,KAAK,IAAI;AACzC,UAAM,YAAY,QAAQ,aAAa,UAAU;AAEjD,UAAM,YAAY,WAAW,MAAM,UAAU,IAAI,IAAI,IAAI;AACzD,UAAM,SAAS,MAAO,UAAU,GAAG,SAAS;AAC5C,WAAO,WAAW,OAAO,UAAU,KAAK,MAAM,IAAI;AAAA,EACpD,CAAC;AACH;","names":["base","tier"]}
1
+ {"version":3,"sources":["../src/classification.ts","../src/cache.ts","../src/keys.ts","../src/utils.ts","../src/proxy.ts"],"sourcesContent":["/**\n * Method classification — determines whether an SDK method is a read (GET)\n * or write (POST/PUT/DELETE) based on its leaf method name.\n *\n * Read methods produce UseQueryOptions; write methods produce UseMutationOptions.\n */\n\nconst READ_METHODS = new Set([\"get\", \"list\", \"lookup\", \"search\", \"suggest\"]);\n\n/**\n * Returns true if the leaf method name represents a read (GET) operation.\n *\n * Read methods: get, list, lookup, search, suggest\n */\nexport function isReadMethod(methodName: string): boolean {\n return READ_METHODS.has(methodName);\n}\n\n/**\n * Returns true if the leaf method name represents a write (POST/PUT/DELETE) operation.\n *\n * Write methods: create, update, delete, enable, and anything not in the read set.\n */\nexport function isWriteMethod(methodName: string): boolean {\n return !READ_METHODS.has(methodName);\n}\n","/**\n * Cache tier resolution — maps SDK method paths to cache tiers.\n *\n * The same tiers apply on client (staleTime/gcTime) and server (edgeCache/redisTtl).\n */\n\nimport type { CacheTierConfig } from \"./shared-types\";\n\n/** Internal resolved cache tier with all timing values. */\nexport interface ResolvedCacheTier {\n staleTime: number;\n gcTime: number;\n edgeCache?: number | string;\n redisTtl?: number;\n}\n\n/** Cache tier configuration with defaults for all tiers. */\nexport interface CacheTierDefaults {\n static: ResolvedCacheTier;\n semiStatic: ResolvedCacheTier;\n none: ResolvedCacheTier;\n}\n\n/** Default cache tier values. */\nexport const DEFAULT_CACHE_TIERS: CacheTierDefaults = {\n static: {\n staleTime: 60 * 60 * 1000, // 60 min\n gcTime: 2 * 60 * 60 * 1000, // 120 min\n edgeCache: 8,\n redisTtl: 28800, // 8 hours\n },\n semiStatic: {\n staleTime: 60 * 1000, // 1 min\n gcTime: 5 * 60 * 1000, // 5 min\n edgeCache: 1,\n redisTtl: 3600, // 1 hour\n },\n none: {\n staleTime: 0,\n gcTime: 0,\n },\n};\n\n/** Paths that should use the static cache tier. */\nconst STATIC_PATHS = [\n \"agrSite.settings\",\n \"agrSite.metaFiles\",\n \"agrSite.geoCodesPostalCodes\",\n \"items.categories\",\n \"items.itemCategory\",\n \"items.brands\",\n \"items.attributeGroups\",\n \"items.attributes\",\n \"p21Core.company\",\n \"p21Core.location\",\n \"p21Core.paymentTypes\",\n \"p21Core.codeP21\",\n \"p21Core.cashDrawer\",\n \"joomla.menu\",\n \"joomla.tags\",\n \"joomla.userGroups\",\n \"legacy.state\",\n];\n\n/** Paths that should not be cached. */\nconst NO_CACHE_PATHS = [\"commerce\"];\n\n/**\n * Resolves the cache tier for a given SDK method path.\n *\n * @param methodPath Dot-separated SDK method path (e.g. \"items.invMast.stock.get\")\n * @param overrides Optional per-tier overrides from consumer config\n * @returns Resolved cache tier with timing values\n *\n * @example\n * getCacheTier(\"items.categories.list\") → static (60 min stale)\n * getCacheTier(\"pricing.priceEngine.get\") → semiStatic (1 min stale)\n * getCacheTier(\"commerce.cartLine.add.create\") → none (0 stale)\n */\nexport function getCacheTier(\n methodPath: string,\n overrides?: { static?: CacheTierConfig; semiStatic?: CacheTierConfig },\n): ResolvedCacheTier {\n if (NO_CACHE_PATHS.some((p) => methodPath.startsWith(p))) {\n return DEFAULT_CACHE_TIERS.none;\n }\n\n if (STATIC_PATHS.some((p) => methodPath.startsWith(p))) {\n const base = DEFAULT_CACHE_TIERS.static;\n const tier = overrides?.static;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n }\n\n // Default: semiStatic\n const base = DEFAULT_CACHE_TIERS.semiStatic;\n const tier = overrides?.semiStatic;\n if (!tier) return base;\n return {\n staleTime: tier.staleTime ?? base.staleTime,\n gcTime: tier.gcTime ?? base.gcTime,\n edgeCache: tier.edgeCache ?? base.edgeCache,\n redisTtl: tier.redis ?? base.redisTtl,\n };\n}\n","/**\n * Deterministic key generation utilities.\n *\n * stableStringify and fnv1a are the single source of truth —\n * augur-hooks and augur-server both import from here so cache keys\n * are guaranteed identical across client and server.\n */\n\n/**\n * JSON.stringify with sorted object keys for deterministic cache keys.\n * Ensures { a: 1, b: 2 } and { b: 2, a: 1 } produce the same string.\n */\nexport function stableStringify(value: unknown): string {\n if (value === null || value === undefined) return JSON.stringify(value);\n if (typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(\n (key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`,\n );\n return `{${entries.join(\",\")}}`;\n}\n\n/**\n * FNV-1a 32-bit hash. Fast non-cryptographic hash for cache keys.\n * Returns an 8-character zero-padded hex string.\n */\nexport function fnv1a(str: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Builds a deterministic query key from a method path and arguments.\n *\n * @example\n * buildQueryKey([\"items\", \"invMast\", \"get\"], [42])\n * → [\"items\", \"invMast\", \"get\", 42]\n *\n * buildQueryKey([\"pricing\", \"priceEngine\", \"get\"], [{ itemId: \"X\", customerId: 1 }])\n * → [\"pricing\", \"priceEngine\", \"get\", { itemId: \"X\", customerId: 1 }]\n */\nexport function buildQueryKey(path: string[], args: unknown[]): unknown[] {\n return [...path, ...args];\n}\n\n/**\n * Builds a deterministic cache key for Redis/CDN caching.\n *\n * Format: `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`\n *\n * @example\n * buildCacheKey(\"ampro:\", \"pricing.priceEngine.get\", [{ itemId: \"X\" }])\n * → \"ampro:sdk:pricing.priceEngine.get:a1b2c3d4\"\n */\nexport function buildCacheKey(\n prefix: string,\n methodPath: string,\n args: unknown[],\n): string {\n return `${prefix}sdk:${methodPath}:${fnv1a(stableStringify(args))}`;\n}\n","/**\n * Utility functions for the proxy infrastructure.\n */\n\n/**\n * Walk an object by path array to find the leaf function.\n *\n * @example\n * resolveMethod(api, [\"items\", \"invMast\", \"stock\", \"get\"])\n * → api.items.invMast.stock.get\n */\nexport function resolveMethod(\n obj: unknown,\n path: string[],\n): (...args: unknown[]) => unknown {\n let current: unknown = obj;\n for (const segment of path) {\n if (current == null || typeof current !== \"object\") {\n throw new Error(\n `Cannot resolve method path \"${path.join(\".\")}\": ` +\n `\"${segment}\" is not accessible on ${typeof current}`,\n );\n }\n current = (current as Record<string, unknown>)[segment];\n }\n if (typeof current !== \"function\") {\n throw new Error(\n `Method path \"${path.join(\".\")}\" does not resolve to a function ` +\n `(got ${typeof current})`,\n );\n }\n return current as (...args: unknown[]) => unknown;\n}\n\n/**\n * Normalize arguments for deterministic cache/query keys.\n * Filters out undefined values from argument objects.\n */\nexport function stableArgs(args: unknown[]): unknown[] {\n return args.map((arg) => {\n if (arg === null || arg === undefined || typeof arg !== \"object\") return arg;\n if (Array.isArray(arg)) return arg;\n const obj = arg as Record<string, unknown>;\n const filtered: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n if (obj[key] !== undefined) {\n filtered[key] = obj[key];\n }\n }\n return filtered;\n });\n}\n","/**\n * Deep proxy factories — runtime SDK namespace mirroring.\n *\n * The same Proxy pattern that powers `createMockClient()` in the SDK\n * powers every downstream consumer. One proxy shape, multiple behaviors\n * via the handler callback.\n */\n\nimport { isReadMethod } from \"./classification\";\nimport { getCacheTier } from \"./cache\";\nimport type { ResolvedCacheTier } from \"./cache\";\nimport type { CacheTierConfig } from \"./shared-types\";\nimport { buildQueryKey, buildCacheKey, stableStringify, fnv1a } from \"./keys\";\nimport { resolveMethod, stableArgs } from \"./utils\";\nimport type { ProxyQueryOptions, ProxyMutationOptions } from \"./types\";\n\n/** Configuration for the options proxy (hooks). */\nexport interface OptionsProxyConfig {\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n}\n\n/** Context passed to the wrapCall hook. */\nexport interface WrapCallContext {\n /** Dot-separated SDK method path (e.g. \"joomla.users.verifyPassword.create\"). */\n methodPath: string;\n /** Arguments to pass to the SDK method (after pre-transform). */\n args: unknown[];\n /** Calls the underlying SDK method. */\n sdkCall: (...a: unknown[]) => Promise<unknown>;\n /** Resolved cache tier for this method path. */\n tier: ResolvedCacheTier;\n /** True when the leaf method name is a read (get, list, lookup, search, suggest). */\n isRead: boolean;\n}\n\n/** Configuration for the actions proxy (server). */\nexport interface ActionsProxyConfig {\n /** Cache key prefix (e.g. \"ampro:\"). */\n cachePrefix?: string;\n /** Per-tier cache overrides. */\n cache?: {\n static?: CacheTierConfig;\n semiStatic?: CacheTierConfig;\n };\n /** Pre/post transforms per method path. */\n transforms?: Record<\n string,\n {\n pre?: (args: unknown[]) => unknown[];\n post?: (result: unknown) => unknown;\n }\n >;\n /**\n * Optional middleware hook called instead of the raw SDK call.\n * Lets consumers inject caching, logging, or other cross-cutting concerns\n * without augur-core needing framework dependencies.\n */\n wrapCall?: (ctx: WrapCallContext) => Promise<unknown>;\n}\n\n/**\n * Creates a deep proxy that intercepts property access to build a method\n * path, then calls the handler when the proxy is invoked as a function.\n *\n * This is the core mechanism. `createOptionsProxy` and `createActionsProxy`\n * are thin wrappers that provide different handlers.\n */\nexport function createDeepProxy<TResult>(\n handler: (path: string[], args: unknown[]) => TResult,\n path: string[] = [],\n): unknown {\n /* v8 ignore next -- placeholder body, only the Proxy traps execute */\n const callable = function () {};\n\n return new Proxy(callable, {\n get(_target, prop: string | symbol) {\n if (typeof prop === \"symbol\") return undefined;\n return createDeepProxy(handler, [...path, prop]);\n },\n apply(_target, _thisArg, args: unknown[]) {\n return handler(path, args);\n },\n });\n}\n\n/**\n * Creates a proxy that returns TanStack Query options for every SDK method.\n *\n * Read methods (get, list, lookup, search, suggest) return ProxyQueryOptions.\n * Write methods (create, update, delete, etc.) return ProxyMutationOptions.\n *\n * @param api The SDK client instance\n * @param config Optional cache configuration\n * @returns Proxy mirroring the SDK with query/mutation options at every leaf\n *\n * @example\n * const q = createOptionsProxy(api);\n * const opts = q.items.invMast.stock.get(42);\n * // opts.queryKey → [\"items\", \"invMast\", \"stock\", \"get\", 42]\n * // opts.queryFn → () => api.items.invMast.stock.get(42)\n * // opts.staleTime → 60000 (semiStatic default)\n */\nexport function createOptionsProxy<TApi extends object>(\n api: TApi,\n config?: OptionsProxyConfig,\n): unknown {\n return createDeepProxy(\n (\n path: string[],\n args: unknown[],\n ): ProxyQueryOptions<unknown> | ProxyMutationOptions<unknown, unknown[]> => {\n const methodName = path[path.length - 1]!;\n const methodPath = path.join(\".\");\n const sdkMethod = resolveMethod(api, path);\n const normalizedArgs = stableArgs(args);\n\n if (isReadMethod(methodName)) {\n const tier = getCacheTier(methodPath, config?.cache);\n return {\n queryKey: buildQueryKey(path, normalizedArgs),\n queryFn: () => sdkMethod(...args) as Promise<unknown>,\n staleTime: tier.staleTime,\n gcTime: tier.gcTime,\n };\n }\n\n return {\n mutationKey: path,\n mutationFn: (...mutationArgs: unknown[]) =>\n sdkMethod(...mutationArgs) as Promise<unknown>,\n };\n },\n );\n}\n\n/**\n * Creates a proxy that wraps every SDK method as a direct async action.\n *\n * For read methods, the result is cached using the cache key builder.\n * For write methods, the call passes through directly.\n *\n * @param api The SDK client instance\n * @param config Optional cache and transform configuration\n * @returns Proxy mirroring the SDK with cached/transformed actions at every leaf\n *\n * @example\n * const actions = createActionsProxy(api, { cachePrefix: \"ampro:\" });\n * const stock = await actions.items.invMast.stock.get(42);\n */\nexport function createActionsProxy<TApi extends object>(\n api: TApi,\n config?: ActionsProxyConfig,\n): unknown {\n return createDeepProxy(async (path: string[], args: unknown[]) => {\n const methodPath = path.join(\".\");\n const methodName = path[path.length - 1]!;\n const sdkMethod = resolveMethod(api, path);\n const transform = config?.transforms?.[methodPath];\n\n const finalArgs = transform?.pre ? transform.pre(args) : args;\n\n let result: unknown;\n if (config?.wrapCall) {\n const tier = getCacheTier(methodPath, config.cache);\n result = await config.wrapCall({\n methodPath,\n args: finalArgs,\n sdkCall: (...a: unknown[]) => sdkMethod(...a) as Promise<unknown>,\n tier,\n isRead: isReadMethod(methodName),\n });\n } else {\n result = await (sdkMethod(...finalArgs) as Promise<unknown>);\n }\n\n return transform?.post ? transform.post(result) : result;\n });\n}\n\n// Re-export key utilities for consumers who need to build keys manually\nexport { buildQueryKey, buildCacheKey, stableStringify, fnv1a };\n"],"mappings":"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","names":["base","tier"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simpleapps-com/augur-core",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Universal foundation for Augur packages — proxy infrastructure, cache keys, method classification, shared types",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,7 @@
29
29
  "dist"
30
30
  ],
31
31
  "dependencies": {
32
- "@simpleapps-com/augur-utils": "1.0.2"
32
+ "@simpleapps-com/augur-utils": "1.0.4"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@simpleapps-com/augur-api": "^0.9.12"