theokit 0.12.0 → 0.13.0

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.
Files changed (131) hide show
  1. package/dist/{actions-virtual-module-SQDY3V5X.js → actions-virtual-module-3CDQTWOC.js} +6 -6
  2. package/dist/{actions-virtual-module-PNPRCEOS.js → actions-virtual-module-EIPXX4ZB.js} +3 -3
  3. package/dist/adapters/web-shim.d.ts +67 -0
  4. package/dist/adapters/ws-shim.d.ts +55 -0
  5. package/dist/agent-events-DosDXkSV.d.ts +94 -0
  6. package/dist/agents-typed-client-SAWAAH7K.js +142 -0
  7. package/dist/agents-typed-client-SAWAAH7K.js.map +1 -0
  8. package/dist/agents-typed-client-UTEQUA63.js +143 -0
  9. package/dist/agents-typed-client-UTEQUA63.js.map +1 -0
  10. package/dist/{app-typed-client-5GYEOYP3.js → app-typed-client-7PBFWZUE.js} +3 -3
  11. package/dist/{app-typed-client-QG7BVZYW.js → app-typed-client-CSOK7NPC.js} +6 -6
  12. package/dist/audit-log-BQWM5YLG.d.ts +60 -0
  13. package/dist/body-parser-web-FV5HWCY3.js +71 -0
  14. package/dist/body-parser-web-FV5HWCY3.js.map +1 -0
  15. package/dist/boot/index.d.ts +39 -0
  16. package/dist/{build-QFRLSEZ4.js → build-HXND27XG.js} +11 -11
  17. package/dist/{chunk-223EFY5X.js → chunk-2J7XU3PW.js} +68 -27
  18. package/dist/chunk-2J7XU3PW.js.map +1 -0
  19. package/dist/{chunk-RESN62GB.js → chunk-2KZQPDYR.js} +5 -48
  20. package/dist/chunk-2KZQPDYR.js.map +1 -0
  21. package/dist/chunk-3S3BNW5K.js +445 -0
  22. package/dist/chunk-3S3BNW5K.js.map +1 -0
  23. package/dist/{chunk-6FYD34NX.js → chunk-BQDGES7C.js} +28 -28
  24. package/dist/{chunk-6FYD34NX.js.map → chunk-BQDGES7C.js.map} +1 -1
  25. package/dist/chunk-EXP56GFQ.js +52 -0
  26. package/dist/chunk-EXP56GFQ.js.map +1 -0
  27. package/dist/chunk-F4YUPDJ2.js +115 -0
  28. package/dist/chunk-F4YUPDJ2.js.map +1 -0
  29. package/dist/{chunk-NAZ4E2GT.js → chunk-KXA37ONC.js} +2 -2
  30. package/dist/chunk-NHJMZCAS.js +32 -0
  31. package/dist/chunk-NHJMZCAS.js.map +1 -0
  32. package/dist/{chunk-43D6XNDR.js → chunk-O62MW4MT.js} +91 -18
  33. package/dist/chunk-O62MW4MT.js.map +1 -0
  34. package/dist/chunk-RSVN727G.js +1 -0
  35. package/dist/{chunk-7CBRKNQA.js → chunk-RYTZYFSD.js} +198 -6
  36. package/dist/chunk-RYTZYFSD.js.map +1 -0
  37. package/dist/chunk-UNLA45FY.js +235 -0
  38. package/dist/chunk-UNLA45FY.js.map +1 -0
  39. package/dist/{chunk-GFMQJHXX.js → chunk-WR4F4EEZ.js} +1082 -1074
  40. package/dist/chunk-WR4F4EEZ.js.map +1 -0
  41. package/dist/{chunk-AD74EAK3.js → chunk-ZSTZXR2D.js} +1 -30
  42. package/dist/chunk-ZSTZXR2D.js.map +1 -0
  43. package/dist/cli/index.js +5 -5
  44. package/dist/client/index.d.ts +418 -0
  45. package/dist/client/index.js +84 -3
  46. package/dist/client/index.js.map +1 -1
  47. package/dist/csrf-BBrEZSBW.d.ts +107 -0
  48. package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
  49. package/dist/define-websocket-CdK94O-D.d.ts +64 -0
  50. package/dist/{dev-GBXOTXUP.js → dev-OWW4XVIH.js} +10 -10
  51. package/dist/{dev-emit-FEFEDLZF.js → dev-emit-5MDSBP5D.js} +3 -3
  52. package/dist/{dev-emit-O4EGOSNV.js → dev-emit-QH2YGZXN.js} +2 -2
  53. package/dist/devtools/entry.d.ts +5 -0
  54. package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
  55. package/dist/health-route-C0hk64_U.d.ts +57 -0
  56. package/dist/index-B40qUSrQ.d.ts +575 -0
  57. package/dist/index.d.ts +361 -0
  58. package/dist/index.js +6 -4
  59. package/dist/index.js.map +1 -1
  60. package/dist/internal-api-4YTJDITC.js +83 -0
  61. package/dist/internal-api-EFKZWIYZ.js +66 -0
  62. package/dist/internal-api-EFKZWIYZ.js.map +1 -0
  63. package/dist/job-backend-CgC8Xf33.d.ts +68 -0
  64. package/dist/match-CfbEFRG4.d.ts +26 -0
  65. package/dist/{openapi-VR6AFBLJ.js → openapi-FHY6HC6I.js} +7 -7
  66. package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
  67. package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
  68. package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
  69. package/dist/rate-limit-store-BEJnhWdw.d.ts +72 -0
  70. package/dist/react-query/index.d.ts +33 -0
  71. package/dist/{registry-Q2TZQLUH.js → registry-34LL7NF4.js} +1 -1
  72. package/dist/{routes-LRYOIIAI.js → routes-EW7TP7NJ.js} +2 -2
  73. package/dist/schema-BpH6ivDY.d.ts +74 -0
  74. package/dist/server/agent/index.d.ts +229 -0
  75. package/dist/server/agent/index.js +2 -1
  76. package/dist/server/auth/index.d.ts +419 -0
  77. package/dist/server/cost/index.d.ts +177 -0
  78. package/dist/server/cron/index.d.ts +208 -0
  79. package/dist/server/define/index.d.ts +313 -0
  80. package/dist/server/define/index.js +4 -2
  81. package/dist/server/http/index.d.ts +11 -0
  82. package/dist/server/index.d.ts +848 -0
  83. package/dist/server/index.js +9 -294
  84. package/dist/server/index.js.map +1 -1
  85. package/dist/server/jobs/index.d.ts +348 -0
  86. package/dist/server/observability/index.d.ts +324 -0
  87. package/dist/server/plugins/index.d.ts +17 -0
  88. package/dist/server/rate-limit/index.d.ts +105 -0
  89. package/dist/server/realtime/index.d.ts +15 -0
  90. package/dist/server/scan/index.d.ts +126 -0
  91. package/dist/server/scan/index.js +1 -1
  92. package/dist/server/security/index.d.ts +193 -0
  93. package/dist/server/storage/index.d.ts +22 -0
  94. package/dist/server/webhook/index.d.ts +148 -0
  95. package/dist/{start-3ZHAXSJE.js → start-KIQ5TTLR.js} +76 -13
  96. package/dist/start-KIQ5TTLR.js.map +1 -0
  97. package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
  98. package/dist/storage-types-DsDTCPbp.d.ts +96 -0
  99. package/dist/vite-plugin/index.d.ts +115 -0
  100. package/dist/vite-plugin/index.js +6 -4
  101. package/dist/{vite-plugin-WO72VLYR.js → vite-plugin-RK66K26Z.js} +7 -7
  102. package/dist/vite-plugin-RK66K26Z.js.map +1 -0
  103. package/package.json +4 -4
  104. package/dist/chunk-223EFY5X.js.map +0 -1
  105. package/dist/chunk-3LVRAGAZ.js +0 -73
  106. package/dist/chunk-3LVRAGAZ.js.map +0 -1
  107. package/dist/chunk-43D6XNDR.js.map +0 -1
  108. package/dist/chunk-7CBRKNQA.js.map +0 -1
  109. package/dist/chunk-AD74EAK3.js.map +0 -1
  110. package/dist/chunk-GFMQJHXX.js.map +0 -1
  111. package/dist/chunk-PBEH6NXR.js +0 -44
  112. package/dist/chunk-PBEH6NXR.js.map +0 -1
  113. package/dist/chunk-PIVX3DYW.js +0 -142
  114. package/dist/chunk-PIVX3DYW.js.map +0 -1
  115. package/dist/chunk-PPPR5DGR.js +0 -1
  116. package/dist/chunk-RESN62GB.js.map +0 -1
  117. package/dist/start-3ZHAXSJE.js.map +0 -1
  118. /package/dist/{actions-virtual-module-SQDY3V5X.js.map → actions-virtual-module-3CDQTWOC.js.map} +0 -0
  119. /package/dist/{actions-virtual-module-PNPRCEOS.js.map → actions-virtual-module-EIPXX4ZB.js.map} +0 -0
  120. /package/dist/{app-typed-client-5GYEOYP3.js.map → app-typed-client-7PBFWZUE.js.map} +0 -0
  121. /package/dist/{app-typed-client-QG7BVZYW.js.map → app-typed-client-CSOK7NPC.js.map} +0 -0
  122. /package/dist/{build-QFRLSEZ4.js.map → build-HXND27XG.js.map} +0 -0
  123. /package/dist/{chunk-NAZ4E2GT.js.map → chunk-KXA37ONC.js.map} +0 -0
  124. /package/dist/{chunk-PPPR5DGR.js.map → chunk-RSVN727G.js.map} +0 -0
  125. /package/dist/{dev-GBXOTXUP.js.map → dev-OWW4XVIH.js.map} +0 -0
  126. /package/dist/{dev-emit-FEFEDLZF.js.map → dev-emit-5MDSBP5D.js.map} +0 -0
  127. /package/dist/{dev-emit-O4EGOSNV.js.map → dev-emit-QH2YGZXN.js.map} +0 -0
  128. /package/dist/{vite-plugin-WO72VLYR.js.map → internal-api-4YTJDITC.js.map} +0 -0
  129. /package/dist/{openapi-VR6AFBLJ.js.map → openapi-FHY6HC6I.js.map} +0 -0
  130. /package/dist/{registry-Q2TZQLUH.js.map → registry-34LL7NF4.js.map} +0 -0
  131. /package/dist/{routes-LRYOIIAI.js.map → routes-EW7TP7NJ.js.map} +0 -0
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import "tsx/esm";
3
+ import {
4
+ emitOpenApi,
5
+ loadRoutesForOpenApi
6
+ } from "./chunk-JAIKGP3Q.js";
3
7
  import {
4
8
  loadConfig
5
9
  } from "./chunk-7YZHAQU7.js";
6
10
  import "./chunk-YJAUJXZS.js";
7
11
  import "./chunk-45C3WUQ7.js";
8
- import {
9
- emitOpenApi,
10
- loadRoutesForOpenApi
11
- } from "./chunk-JAIKGP3Q.js";
12
12
  import {
13
13
  generateManifest
14
- } from "./chunk-3LVRAGAZ.js";
15
- import "./chunk-6FYD34NX.js";
14
+ } from "./chunk-F4YUPDJ2.js";
15
+ import "./chunk-BQDGES7C.js";
16
16
 
17
17
  // src/cli/commands/openapi.ts
18
18
  import { mkdtempSync, rmSync } from "fs";
@@ -79,4 +79,4 @@ function emitOpenApiInMemory(manifest, config) {
79
79
  export {
80
80
  openapiCommand
81
81
  };
82
- //# sourceMappingURL=openapi-VR6AFBLJ.js.map
82
+ //# sourceMappingURL=openapi-FHY6HC6I.js.map
@@ -0,0 +1,95 @@
1
+ import { T as TheoPlugin, a as TheoApp, P as PluginContext, H as HookResult, R as RunHookOptions } from './plugin-types-DNJGxr4Z.js';
2
+
3
+ declare class DuplicatePluginError extends Error {
4
+ constructor(name: string);
5
+ }
6
+ /**
7
+ * @deprecated Per T3.1 (C1 plugin scope encapsulation) — duplicate decoration
8
+ * keys across sibling plugins are now PERMITTED because each plugin gets its
9
+ * own child scope via `Object.create(parent)` (Fastify pattern, ADR-0028
10
+ * blueprint D1). This class is retained for one minor cycle so consumers who
11
+ * `instanceof DuplicateDecorationError` continue to compile; the constructor
12
+ * is no longer reachable from `PluginRunner.register()`. Removal scheduled
13
+ * for 0.x+2 per CHANGELOG.
14
+ */
15
+ declare class DuplicateDecorationError extends Error {
16
+ constructor(key: string, existingPlugin: string, newPlugin: string);
17
+ }
18
+ declare class PluginRunner {
19
+ private plugins;
20
+ private pluginScopes;
21
+ private onRequestHooks;
22
+ private preHandlerHooks;
23
+ private onResponseHooks;
24
+ private onErrorHooks;
25
+ /**
26
+ * Parent app — proto-chain root for all child scopes. Has its OWN empty
27
+ * decorations map (parent never receives `decorateRequest` calls under
28
+ * the T3.1 contract; only child scopes do).
29
+ */
30
+ private parentDecorations;
31
+ private parentApp;
32
+ has(name: string): boolean;
33
+ /**
34
+ * Per T3.1 (C1 plugin scope encapsulation):
35
+ * 1. Reserve the plugin name (still rejects duplicates).
36
+ * 2. Build a CHILD TheoApp via `Object.create(parentApp)` — Fastify
37
+ * `plugin-override.js:38` pattern. The child's own `decorateRequest`
38
+ * populates per-scope `decorations`; the child's `addHook` still
39
+ * forwards into the shared hook lists (hooks ARE process-global —
40
+ * only decorations are scoped, mirroring Fastify's decoration vs
41
+ * hook semantics).
42
+ * 3. Invoke `plugin.register(childApp)`.
43
+ *
44
+ * Cross-plugin decoration-key collisions are PERMITTED (per blueprint
45
+ * D1). The legacy `DuplicateDecorationError` is no longer thrown.
46
+ */
47
+ register(plugin: TheoPlugin): Promise<void>;
48
+ /**
49
+ * Build the parent app facade. Hooks forward to shared lists.
50
+ * `decorateRequest` writes into the parent decorations map — used only
51
+ * if a future consumer registers a non-plugin "app-level" decoration
52
+ * directly. T3.1 contract: plugins decorate ONLY through child scopes.
53
+ */
54
+ private buildParentAppFacade;
55
+ /**
56
+ * Build a child scope via `Object.create(parentApp)` so the child
57
+ * inherits the parent's facade methods through the prototype chain.
58
+ * Then override `decorateRequest` on the child instance so writes
59
+ * land in the per-scope `decorations` map (parent is NOT mutated).
60
+ */
61
+ private buildPluginScope;
62
+ private routeHookByName;
63
+ /**
64
+ * Apply ALL plugin scopes' decorations into the request ctx. Per T3.1,
65
+ * sibling plugins MAY decorate the same key — last-writer-wins at apply
66
+ * time (ordering = registration order). This keeps the legacy
67
+ * `ctx.<key>` flat surface working for consumers that already aggregate
68
+ * decorations into a single bag.
69
+ */
70
+ applyDecorations(ctx: Record<string, unknown>): void;
71
+ /**
72
+ * Apply ONLY one plugin's scoped decorations into `target`. Used by
73
+ * the T1.1 RED-3 test (sibling isolation proof) and by future scope-aware
74
+ * dispatch paths. Throws if the plugin name isn't registered.
75
+ */
76
+ applyScopedDecorations(pluginName: string, target: Record<string, unknown>): void;
77
+ /** T1.1 RED-1/RED-4 introspection: returns the child TheoApp built for `pluginName`. */
78
+ getPluginScope(pluginName: string): TheoApp;
79
+ /** T1.1 RED-4: returns the parent TheoApp (root of every child's proto chain). */
80
+ getParentApp(): TheoApp;
81
+ /** T1.1 RED-2: returns the parent's decorations map (NEVER touched by plugin decorate calls under T3.1 contract). */
82
+ getParentDecorations(): Map<string, unknown>;
83
+ runOnRequest(ctx: PluginContext): Promise<HookResult>;
84
+ runPreHandler(ctx: PluginContext): Promise<HookResult>;
85
+ runOnResponse(ctx: PluginContext, options?: RunHookOptions): Promise<HookResult>;
86
+ /**
87
+ * Run all onError hooks. Swallows errors thrown inside hooks themselves to
88
+ * prevent recursion (an error in an error handler must not trigger onError
89
+ * again).
90
+ */
91
+ runOnError(ctx: PluginContext, error: unknown): Promise<HookResult>;
92
+ private runHookList;
93
+ }
94
+
95
+ export { DuplicateDecorationError as D, PluginRunner as P, DuplicatePluginError as a };
@@ -0,0 +1,79 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+
3
+ interface PluginContext {
4
+ request: IncomingMessage;
5
+ response: ServerResponse;
6
+ ctx: Record<string, unknown>;
7
+ requestId: string;
8
+ }
9
+ interface PluginErrorContext extends PluginContext {
10
+ error: unknown;
11
+ }
12
+ interface RunHookOptions {
13
+ inErrorPath?: boolean;
14
+ }
15
+ interface HookResult {
16
+ shortCircuited: boolean;
17
+ }
18
+ type OnRequestHook = (ctx: PluginContext) => void | Promise<void>;
19
+ type PreHandlerHook = (ctx: PluginContext) => void | Promise<void>;
20
+ type OnResponseHook = (ctx: PluginContext) => void | Promise<void>;
21
+ type OnErrorHook = (ctx: PluginErrorContext) => void | Promise<void>;
22
+ type HookName = 'onRequest' | 'preHandler' | 'onResponse' | 'onError';
23
+ type HookByName<K extends HookName> = K extends 'onError' ? OnErrorHook : K extends 'onRequest' ? OnRequestHook : K extends 'preHandler' ? PreHandlerHook : K extends 'onResponse' ? OnResponseHook : never;
24
+ interface TheoApp {
25
+ addHook<K extends HookName>(name: K, fn: HookByName<K>): void;
26
+ decorateRequest<T>(key: string, value: T): void;
27
+ }
28
+ interface TheoPlugin {
29
+ name: string;
30
+ register(app: TheoApp): void | Promise<void>;
31
+ }
32
+ /**
33
+ * Identity function for plugin authors. Provides auto-completion + type
34
+ * inference at the call site (TanStack/Vite/Astro pattern). Pure runtime
35
+ * no-op — returns the input unchanged.
36
+ *
37
+ * @example
38
+ * import { definePlugin } from 'theokit/server'
39
+ * export default definePlugin({
40
+ * name: 'my-plugin',
41
+ * register(app) {
42
+ * app.addHook('onRequest', (req) => { ... })
43
+ * },
44
+ * })
45
+ *
46
+ * Equivalent to `const p: TheoPlugin = {...}` but more ergonomic. See
47
+ * ADR-0008 (D1 + D6) for the rationale.
48
+ */
49
+ declare function definePlugin(plugin: TheoPlugin): TheoPlugin;
50
+ /**
51
+ * Web-Standards plugin context. Available during all 4 hook lifecycle
52
+ * stages (onRequest, preHandler, onResponse, onError).
53
+ *
54
+ * - `request` — the incoming Web Request (read-only at the runtime level;
55
+ * plugins can call `request.headers.get()`, `request.clone()`, etc.).
56
+ * - `responseHeaders` — a mutable `Headers` instance the runtime threads
57
+ * through the hook chain. Plugins append (e.g., CORS, Set-Cookie); the
58
+ * final Response composes these.
59
+ * - `response` — set to the handler's Response AFTER the handler returns.
60
+ * Available during `onResponse` / `onError`. `undefined` during
61
+ * `onRequest` / `preHandler` (which fire before the handler runs).
62
+ * - `ctx` / `requestId` — same semantics as the IncomingMessage path.
63
+ */
64
+ interface WebPluginContext {
65
+ request: Request;
66
+ responseHeaders: Headers;
67
+ response?: Response;
68
+ ctx: Record<string, unknown>;
69
+ requestId: string;
70
+ }
71
+ interface WebPluginErrorContext extends WebPluginContext {
72
+ error: unknown;
73
+ }
74
+ type WebOnRequestHook = (ctx: WebPluginContext) => void | Promise<void>;
75
+ type WebPreHandlerHook = (ctx: WebPluginContext) => void | Promise<void>;
76
+ type WebOnResponseHook = (ctx: WebPluginContext) => void | Promise<void>;
77
+ type WebOnErrorHook = (ctx: WebPluginErrorContext) => void | Promise<void>;
78
+
79
+ export { type HookResult as H, type OnErrorHook as O, type PluginContext as P, type RunHookOptions as R, type TheoPlugin as T, type WebOnRequestHook as W, type TheoApp as a, type WebPreHandlerHook as b, type WebOnResponseHook as c, type WebOnErrorHook as d, type HookName as e, type OnRequestHook as f, type OnResponseHook as g, type PluginErrorContext as h, type PreHandlerHook as i, definePlugin as j };
@@ -0,0 +1,58 @@
1
+ import { IncomingMessage } from 'node:http';
2
+ import { R as RateLimitStore } from './rate-limit-store-BEJnhWdw.js';
3
+
4
+ /**
5
+ * Rate limit configuration — basic single-bucket shape. Per ADR D2, the
6
+ * per-route + per-user variant is layered on top via T2.2; this base
7
+ * struct is the smallest unit.
8
+ */
9
+ interface RateLimitConfig {
10
+ windowMs: number;
11
+ max: number;
12
+ }
13
+ interface RateLimitResult {
14
+ limited: boolean;
15
+ headers: Record<string, string>;
16
+ }
17
+ /**
18
+ * Create a rate limiter that consumes a pluggable `RateLimitStore`.
19
+ *
20
+ * Backwards-compatible signature: callers passing only `config` get the
21
+ * default `InMemoryStore`. Distributed deployments pass a Redis adapter
22
+ * (or any other `RateLimitStore` implementation) via `opts.store`.
23
+ *
24
+ * T2.1: synchronous return for back-compat with the current
25
+ * `api-middleware.ts` integration point. The async store contract is
26
+ * exercised lazily — we use a sync fast-path against the in-memory store
27
+ * (single-thread JS makes this safe). External stores remain async and
28
+ * would require a different async wrapper at the middleware layer.
29
+ */
30
+ declare function createRateLimiter(config: RateLimitConfig, opts?: {
31
+ store?: RateLimitStore;
32
+ }): (req: IncomingMessage) => RateLimitResult;
33
+ /**
34
+ * T5a.2 Phase D slice 2/3 — Web-Standards single-bucket rate limiter.
35
+ *
36
+ * Mirror of `createRateLimiter(config, opts)` returning a checker that
37
+ * accepts `(clientIp: string)` instead of `(req: IncomingMessage)`. Web
38
+ * `Request` has no `req.socket.remoteAddress` — the IP is resolved by
39
+ * the caller per-runtime (Node adapter from socket; CF Workers from
40
+ * `cf-connecting-ip`; etc., same convention as Phase D slice 1/3's
41
+ * `DeriveKeyRequestContext.clientIp`).
42
+ *
43
+ * Same `RateLimitConfig`, same `InMemoryStore` default, same async
44
+ * store rejection (use a dedicated async middleware for external stores).
45
+ * Same `RateLimitResult` return shape.
46
+ *
47
+ * **Signature difference from `createRateLimiter`:** this Web factory's
48
+ * checker takes a raw IP string instead of a Request object. The IP is
49
+ * the ONLY input the bucket needs; passing a Request object would force
50
+ * the caller to populate `request.headers.get('x-forwarded-for')` or
51
+ * similar without giving us any safer extraction. KISS — accept the IP
52
+ * directly, document the per-runtime resolution at the adapter boundary.
53
+ */
54
+ declare function createRateLimiterWeb(config: RateLimitConfig, opts?: {
55
+ store?: RateLimitStore;
56
+ }): (clientIp: string) => RateLimitResult;
57
+
58
+ export { type RateLimitConfig as R, type RateLimitResult as a, createRateLimiterWeb as b, createRateLimiter as c };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * T2.1 — RateLimitStore interface.
3
+ *
4
+ * Pluggable backend for the rate limiter. The default `InMemoryStore`
5
+ * preserves current single-instance behavior. Multi-instance deployments
6
+ * (TheoCloud canary, K8s replicas) opt in to a distributed adapter
7
+ * (Redis, Cloudflare KV) without bloating single-instance apps.
8
+ *
9
+ * Contract per ADR D1:
10
+ * - `incr` is atomic — concurrent calls for the same key both observe
11
+ * the same `resetAt` and increment count by 1.
12
+ * - `get` returns `null` for expired entries (not just absent — checks
13
+ * `now > resetAt`).
14
+ * - `reset` removes the key entirely; next `incr` creates fresh.
15
+ *
16
+ * Async signature is honest about Redis adapters even though in-memory
17
+ * implementation is synchronous. Callers MUST await.
18
+ */
19
+ interface RateLimitState {
20
+ /** Number of requests counted in the current window. */
21
+ count: number;
22
+ /** Absolute timestamp (ms since epoch) when this window expires. */
23
+ resetAt: number;
24
+ }
25
+ interface RateLimitStore {
26
+ /**
27
+ * Atomic increment-and-get. If the key is missing OR the previous
28
+ * window expired (`now >= resetAt`), create with `count=1, resetAt=now+windowMs`.
29
+ * Otherwise increment count by 1, preserving the original resetAt.
30
+ */
31
+ incr(key: string, windowMs: number): Promise<RateLimitState>;
32
+ /** Read current state. Returns `null` for missing or expired entries. */
33
+ get(key: string): Promise<RateLimitState | null>;
34
+ /** Remove a key. Used by login throttling on success (T6.1). */
35
+ reset(key: string): Promise<void>;
36
+ }
37
+ /**
38
+ * Default in-memory store. Backed by `Map<string, RateLimitState>`.
39
+ *
40
+ * GC: every 1000 `incr` calls, expired entries are removed. Pathological
41
+ * key explosion is bounded by `MAX_ENTRIES` (LRU-evict oldest insertion).
42
+ *
43
+ * Single-thread by virtue of Node's event loop — `incr` is atomic at the
44
+ * JavaScript level (no preemption between Map.get and Map.set).
45
+ */
46
+ declare class InMemoryStore implements RateLimitStore {
47
+ private store;
48
+ /** Bound the map to prevent unbounded growth from pathological inputs. */
49
+ static readonly MAX_ENTRIES = 100000;
50
+ /** GC sweep interval, milliseconds. */
51
+ static readonly GC_INTERVAL_MS = 30000;
52
+ private gcTimer;
53
+ constructor();
54
+ /**
55
+ * Synchronous fast-path used by the legacy sync `createRateLimiter`
56
+ * surface (`api-middleware.ts` is sync). The async `incr` delegates to
57
+ * this for in-memory; external adapters override `incr` directly.
58
+ */
59
+ incrSync(key: string, windowMs: number): RateLimitState;
60
+ /** Sweep expired entries. Called by the GC timer; safe to call manually. */
61
+ sweepExpired(): void;
62
+ /**
63
+ * Stop the GC timer. Call from tests or when discarding the store. After
64
+ * `dispose`, the store still works but no longer auto-sweeps.
65
+ */
66
+ dispose(): void;
67
+ incr(key: string, windowMs: number): Promise<RateLimitState>;
68
+ get(key: string): Promise<RateLimitState | null>;
69
+ reset(key: string): Promise<void>;
70
+ }
71
+
72
+ export { InMemoryStore as I, type RateLimitStore as R, type RateLimitState as a };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * T5.3 — React Query adapter primitives.
3
+ *
4
+ * Exposes:
5
+ * - `stableQueryKey(path, options)` — produces a deterministic queryKey
6
+ * that is equal across calls when the logical content of query/body is
7
+ * equal, regardless of property order or inline-object identity. Solves
8
+ * EC-10 (inline-object → infinite refetch).
9
+ * - `buildUseTheoQueryConfig(path, options, fetcher)` — produces the
10
+ * `{ queryKey, queryFn }` pair that consumers pass to `useQuery` from
11
+ * `@tanstack/react-query`.
12
+ *
13
+ * The canonical implementation lives here in `theokit/client`. The
14
+ * dedicated subpath `theokit/react-query` re-exports this surface so
15
+ * consumers who only need the React Query bridge can import from a
16
+ * clearly named entry point — same shape as `theokit/server`,
17
+ * `theokit/vite-plugin`, etc. No separate npm package.
18
+ */
19
+ interface FetchOptionsLike {
20
+ query?: unknown;
21
+ body?: unknown;
22
+ params?: unknown;
23
+ }
24
+ type QueryKey = readonly unknown[];
25
+ declare function stableQueryKey(path: string, options: FetchOptionsLike): QueryKey;
26
+ type Fetcher<TResult = unknown> = (path: string, options: FetchOptionsLike) => Promise<TResult>;
27
+ interface UseTheoQueryConfig<TResult = unknown> {
28
+ queryKey: QueryKey;
29
+ queryFn: () => Promise<TResult>;
30
+ }
31
+ declare function buildUseTheoQueryConfig<TResult = unknown>(path: string, options: FetchOptionsLike, fetcher: Fetcher<TResult>): UseTheoQueryConfig<TResult>;
32
+
33
+ export { type FetchOptionsLike, type Fetcher, type Fetcher as FetcherFn, type QueryKey, type UseTheoQueryConfig, type UseTheoQueryConfig as UseTheoQueryInternals, buildUseTheoQueryConfig, buildUseTheoQueryConfig as buildUseTheoQueryInternals, stableQueryKey };
@@ -21,4 +21,4 @@ export {
21
21
  adapterRegistry,
22
22
  resolveAdapter
23
23
  };
24
- //# sourceMappingURL=registry-Q2TZQLUH.js.map
24
+ //# sourceMappingURL=registry-34LL7NF4.js.map
@@ -12,7 +12,7 @@ import {
12
12
  scanServerActions,
13
13
  scanServerRoutes,
14
14
  scanWebSocketRoutes
15
- } from "./chunk-6FYD34NX.js";
15
+ } from "./chunk-BQDGES7C.js";
16
16
 
17
17
  // src/cli/commands/routes.ts
18
18
  import { resolve, relative } from "path";
@@ -60,4 +60,4 @@ async function routesCommand() {
60
60
  export {
61
61
  routesCommand
62
62
  };
63
- //# sourceMappingURL=routes-LRYOIIAI.js.map
63
+ //# sourceMappingURL=routes-EW7TP7NJ.js.map
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Wave 2 — Polyglot Services Orchestration (T1.1).
5
+ *
6
+ * Declarative `services: {}` primitive for `theo.config.ts`. Each entry
7
+ * declares an external sidecar process (Python FastAPI / Node Hono) that
8
+ * boots alongside the TheoKit TS app. Empty `services: {}` is the default
9
+ * and preserves Wave 1 behavior (no impact on TS-only apps).
10
+ *
11
+ * See ADRs 0012-0015 + plan: docs/plans/wave-2-polyglot-services-plan.md
12
+ */
13
+
14
+ /**
15
+ * Single service definition. All commands run from `services/<name>/` cwd.
16
+ *
17
+ * EC-4 fix: `proxy` regex requires NON-EMPTY path after `/` (the `+` quantifier)
18
+ * to reject `/` which would catch-all and conflict with TheoKit's own routing.
19
+ */
20
+ declare const ServiceDefinitionSchema: z.ZodObject<{
21
+ runtime: z.ZodEnum<{
22
+ python: "python";
23
+ node: "node";
24
+ }>;
25
+ type: z.ZodOptional<z.ZodEnum<{
26
+ server: "server";
27
+ worker: "worker";
28
+ }>>;
29
+ port: z.ZodNumber;
30
+ proxy: z.ZodString;
31
+ dev: z.ZodString;
32
+ build: z.ZodOptional<z.ZodString>;
33
+ start: z.ZodString;
34
+ openapi: z.ZodOptional<z.ZodURL>;
35
+ healthcheck: z.ZodDefault<z.ZodString>;
36
+ cors: z.ZodDefault<z.ZodBoolean>;
37
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
38
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ passSetCookie: z.ZodDefault<z.ZodBoolean>;
40
+ }, z.core.$strip>;
41
+ type ServiceDefinition = z.infer<typeof ServiceDefinitionSchema>;
42
+ type ServicesConfig = Record<string, ServiceDefinition>;
43
+ /**
44
+ * Full services config schema with cross-service refines.
45
+ *
46
+ * EC-1 fix: detect duplicate ports across services.
47
+ * EC-13: empty `dependsOn: []` accepted as no-deps.
48
+ * Self-dep, missing-ref, and cycles rejected via topological check.
49
+ */
50
+ declare const servicesConfigSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
51
+ runtime: z.ZodEnum<{
52
+ python: "python";
53
+ node: "node";
54
+ }>;
55
+ type: z.ZodOptional<z.ZodEnum<{
56
+ server: "server";
57
+ worker: "worker";
58
+ }>>;
59
+ port: z.ZodNumber;
60
+ proxy: z.ZodString;
61
+ dev: z.ZodString;
62
+ build: z.ZodOptional<z.ZodString>;
63
+ start: z.ZodString;
64
+ openapi: z.ZodOptional<z.ZodURL>;
65
+ healthcheck: z.ZodDefault<z.ZodString>;
66
+ cors: z.ZodDefault<z.ZodBoolean>;
67
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
68
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ passSetCookie: z.ZodDefault<z.ZodBoolean>;
70
+ }, z.core.$strip>>>;
71
+ type ServicesConfigInput = z.input<typeof servicesConfigSchema>;
72
+ type ServicesConfigOutput = z.output<typeof servicesConfigSchema>;
73
+
74
+ export type { ServicesConfig as S, ServiceDefinition as a, ServicesConfigInput as b, ServicesConfigOutput as c };