tina4-nodejs 3.13.92 → 3.13.95

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 (193) hide show
  1. package/CLAUDE.md +170 -28
  2. package/README.md +2 -2
  3. package/package.json +13 -9
  4. package/packages/cli/dist/bin.js +33126 -30055
  5. package/packages/cli/src/commands/metrics.ts +17 -11
  6. package/packages/cli/src/commands/serve.ts +10 -9
  7. package/packages/core/dist/index.js +33062 -29908
  8. package/packages/core/src/ai.ts +7 -1
  9. package/packages/core/src/auth.ts +191 -39
  10. package/packages/core/src/background.ts +19 -19
  11. package/packages/core/src/cache.ts +492 -49
  12. package/packages/core/src/devAdmin.ts +79 -32
  13. package/packages/core/src/devMailbox.ts +20 -44
  14. package/packages/core/src/dispatchPipeline.ts +285 -0
  15. package/packages/core/src/dotenv.ts +185 -40
  16. package/packages/core/src/index.ts +7 -6
  17. package/packages/core/src/logger.ts +257 -36
  18. package/packages/core/src/mcp.ts +1 -1
  19. package/packages/core/src/messenger.ts +81 -13
  20. package/packages/core/src/metrics.ts +199 -961
  21. package/packages/core/src/middleware.ts +390 -123
  22. package/packages/core/src/queue.ts +188 -32
  23. package/packages/core/src/queueBackends/kafkaBackend.ts +109 -13
  24. package/packages/core/src/queueBackends/liteBackend.ts +13 -0
  25. package/packages/core/src/queueBackends/mongoBackend.ts +101 -9
  26. package/packages/core/src/queueBackends/rabbitmqBackend.ts +22 -4
  27. package/packages/core/src/rateLimiter.ts +10 -5
  28. package/packages/core/src/request.ts +6 -9
  29. package/packages/core/src/response.ts +46 -1
  30. package/packages/core/src/router.ts +29 -4
  31. package/packages/core/src/server.ts +751 -414
  32. package/packages/core/src/session.ts +244 -27
  33. package/packages/core/src/sessionHandlers/childError.ts +72 -0
  34. package/packages/core/src/sessionHandlers/databaseHandler.ts +338 -48
  35. package/packages/core/src/sessionHandlers/memcachedHandler.ts +181 -0
  36. package/packages/core/src/sessionHandlers/mongoClient.ts +293 -202
  37. package/packages/core/src/sessionHandlers/mongoHandler.ts +88 -8
  38. package/packages/core/src/sessionHandlers/respClient.ts +16 -143
  39. package/packages/core/src/sessionHandlers/sqlClient.ts +290 -0
  40. package/packages/core/src/sessionHandlers/syncBridge.ts +190 -0
  41. package/packages/core/src/sessionHandlers/syncSocket.ts +236 -0
  42. package/packages/core/src/testClient.ts +18 -5
  43. package/packages/core/src/trustedProxy.ts +249 -0
  44. package/packages/core/src/types.ts +29 -5
  45. package/packages/core/src/websocket.ts +66 -0
  46. package/packages/frond/dist/index.js +74 -31
  47. package/packages/frond/src/engine.ts +99 -33
  48. package/packages/orm/dist/index.js +26554 -23400
  49. package/packages/orm/src/adapters/firebird.ts +183 -56
  50. package/packages/orm/src/adapters/mongodb.ts +25 -4
  51. package/packages/orm/src/adapters/mssql.ts +114 -29
  52. package/packages/orm/src/adapters/mysql.ts +103 -40
  53. package/packages/orm/src/adapters/odbc.ts +44 -21
  54. package/packages/orm/src/adapters/postgres.ts +118 -26
  55. package/packages/orm/src/adapters/sqlDialect.ts +120 -0
  56. package/packages/orm/src/adapters/sqlite.ts +64 -25
  57. package/packages/orm/src/baseModel.ts +135 -40
  58. package/packages/orm/src/cachedDatabase.ts +43 -19
  59. package/packages/orm/src/connectTimeout.ts +265 -0
  60. package/packages/orm/src/database.ts +338 -198
  61. package/packages/orm/src/databaseResult.ts +65 -13
  62. package/packages/orm/src/databaseUrl.ts +484 -0
  63. package/packages/orm/src/docstore.ts +386 -145
  64. package/packages/orm/src/index.ts +13 -3
  65. package/packages/orm/src/migration.ts +18 -3
  66. package/packages/orm/src/queryBuilder.ts +38 -4
  67. package/packages/orm/src/sqlTranslator.ts +310 -4
  68. package/packages/orm/src/types.ts +15 -4
  69. package/types/cli/src/bin.d.ts +92 -0
  70. package/types/cli/src/commands/build.d.ts +2 -0
  71. package/types/cli/src/commands/generate.d.ts +47 -0
  72. package/types/cli/src/commands/init.d.ts +1 -0
  73. package/types/cli/src/commands/metrics.d.ts +6 -0
  74. package/types/cli/src/commands/migrate.d.ts +1 -0
  75. package/types/cli/src/commands/migrateCreate.d.ts +1 -0
  76. package/types/cli/src/commands/migrateRollback.d.ts +1 -0
  77. package/types/cli/src/commands/migrateStatus.d.ts +1 -0
  78. package/types/cli/src/commands/queue.d.ts +20 -0
  79. package/types/cli/src/commands/routes.d.ts +1 -0
  80. package/types/cli/src/commands/seed.d.ts +1 -0
  81. package/types/cli/src/commands/serve.d.ts +6 -0
  82. package/types/cli/src/commands/test.d.ts +1 -0
  83. package/types/core/src/ai.d.ts +64 -0
  84. package/types/core/src/api.d.ts +262 -0
  85. package/types/core/src/auth.d.ts +177 -0
  86. package/types/core/src/authGate.d.ts +20 -0
  87. package/types/core/src/background.d.ts +34 -0
  88. package/types/core/src/cache.d.ts +163 -0
  89. package/types/core/src/constants.d.ts +38 -0
  90. package/types/core/src/container.d.ts +44 -0
  91. package/types/core/src/context/chunker.d.ts +31 -0
  92. package/types/core/src/context/index.d.ts +93 -0
  93. package/types/core/src/devAdmin.d.ts +179 -0
  94. package/types/core/src/devMailbox.d.ts +54 -0
  95. package/types/core/src/dispatchPipeline.d.ts +117 -0
  96. package/types/core/src/docs.d.ts +141 -0
  97. package/types/core/src/docsAutoDiscovery.d.ts +6 -0
  98. package/types/core/src/dotenv.d.ts +87 -0
  99. package/types/core/src/env.d.ts +28 -0
  100. package/types/core/src/errorOverlay.d.ts +36 -0
  101. package/types/core/src/events.d.ts +75 -0
  102. package/types/core/src/fakeData.d.ts +55 -0
  103. package/types/core/src/feedback.d.ts +90 -0
  104. package/types/core/src/graphql.d.ts +207 -0
  105. package/types/core/src/health.d.ts +22 -0
  106. package/types/core/src/htmlElement.d.ts +75 -0
  107. package/types/core/src/i18n.d.ts +37 -0
  108. package/types/core/src/index.d.ts +92 -0
  109. package/types/core/src/job.d.ts +39 -0
  110. package/types/core/src/logger.d.ts +200 -0
  111. package/types/core/src/mcp.d.ts +248 -0
  112. package/types/core/src/messenger.d.ts +191 -0
  113. package/types/core/src/metrics.d.ts +41 -0
  114. package/types/core/src/middleware.d.ts +330 -0
  115. package/types/core/src/mqtt.d.ts +257 -0
  116. package/types/core/src/mqttMessage.d.ts +67 -0
  117. package/types/core/src/plan.d.ts +96 -0
  118. package/types/core/src/projectIndex.d.ts +56 -0
  119. package/types/core/src/queue.d.ts +268 -0
  120. package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
  121. package/types/core/src/queueBackends/liteBackend.d.ts +128 -0
  122. package/types/core/src/queueBackends/mongoBackend.d.ts +119 -0
  123. package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
  124. package/types/core/src/rateLimiter.d.ts +49 -0
  125. package/types/core/src/request.d.ts +25 -0
  126. package/types/core/src/response.d.ts +28 -0
  127. package/types/core/src/routeDiscovery.d.ts +12 -0
  128. package/types/core/src/router.d.ts +366 -0
  129. package/types/core/src/scss.d.ts +19 -0
  130. package/types/core/src/server.d.ts +146 -0
  131. package/types/core/src/service.d.ts +115 -0
  132. package/types/core/src/session.d.ts +341 -0
  133. package/types/core/src/sessionHandlers/childError.d.ts +34 -0
  134. package/types/core/src/sessionHandlers/databaseHandler.d.ts +97 -0
  135. package/types/core/src/sessionHandlers/memcachedHandler.d.ts +60 -0
  136. package/types/core/src/sessionHandlers/mongoClient.d.ts +35 -0
  137. package/types/core/src/sessionHandlers/mongoHandler.d.ts +109 -0
  138. package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
  139. package/types/core/src/sessionHandlers/sqlClient.d.ts +39 -0
  140. package/types/core/src/sessionHandlers/syncBridge.d.ts +91 -0
  141. package/types/core/src/sessionHandlers/syncSocket.d.ts +49 -0
  142. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
  143. package/types/core/src/static.d.ts +2 -0
  144. package/types/core/src/test.d.ts +94 -0
  145. package/types/core/src/testClient.d.ts +36 -0
  146. package/types/core/src/testing.d.ts +58 -0
  147. package/types/core/src/trustedProxy.d.ts +44 -0
  148. package/types/core/src/types.d.ts +242 -0
  149. package/types/core/src/validator.d.ts +52 -0
  150. package/types/core/src/websocket.d.ts +402 -0
  151. package/types/core/src/websocketBackplane.d.ts +166 -0
  152. package/types/core/src/websocketConnection.d.ts +54 -0
  153. package/types/core/src/wsdl.d.ts +101 -0
  154. package/types/frond/src/engine.d.ts +263 -0
  155. package/types/frond/src/index.d.ts +2 -0
  156. package/types/orm/src/adapters/firebird.d.ts +183 -0
  157. package/types/orm/src/adapters/mongodb.d.ts +81 -0
  158. package/types/orm/src/adapters/mssql.d.ts +77 -0
  159. package/types/orm/src/adapters/mysql.d.ts +67 -0
  160. package/types/orm/src/adapters/odbc.d.ts +94 -0
  161. package/types/orm/src/adapters/postgres.d.ts +86 -0
  162. package/types/orm/src/adapters/sqlDialect.d.ts +71 -0
  163. package/types/orm/src/adapters/sqlite.d.ts +68 -0
  164. package/types/orm/src/autoCrud.d.ts +73 -0
  165. package/types/orm/src/baseModel.d.ts +427 -0
  166. package/types/orm/src/cachedDatabase.d.ts +190 -0
  167. package/types/orm/src/connectTimeout.d.ts +100 -0
  168. package/types/orm/src/database.d.ts +655 -0
  169. package/types/orm/src/databaseResult.d.ts +109 -0
  170. package/types/orm/src/databaseUrl.d.ts +125 -0
  171. package/types/orm/src/docstore.d.ts +241 -0
  172. package/types/orm/src/fakeData.d.ts +22 -0
  173. package/types/orm/src/index.d.ts +43 -0
  174. package/types/orm/src/migration.d.ts +275 -0
  175. package/types/orm/src/model.d.ts +7 -0
  176. package/types/orm/src/query.d.ts +14 -0
  177. package/types/orm/src/queryBuilder.d.ts +193 -0
  178. package/types/orm/src/realtime/index.d.ts +7 -0
  179. package/types/orm/src/realtime/models/attachment.d.ts +43 -0
  180. package/types/orm/src/realtime/models/channel.d.ts +32 -0
  181. package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
  182. package/types/orm/src/realtime/models/message.d.ts +36 -0
  183. package/types/orm/src/realtime/models/workspace.d.ts +26 -0
  184. package/types/orm/src/realtime/realtime.d.ts +24 -0
  185. package/types/orm/src/realtime/storage.d.ts +61 -0
  186. package/types/orm/src/seeder.d.ts +118 -0
  187. package/types/orm/src/sqlTranslator.d.ts +258 -0
  188. package/types/orm/src/types.d.ts +148 -0
  189. package/types/orm/src/validation.d.ts +6 -0
  190. package/types/swagger/src/generator.d.ts +46 -0
  191. package/types/swagger/src/index.d.ts +2 -0
  192. package/types/swagger/src/ui.d.ts +11 -0
  193. package/packages/core/src/sessionHandlers/redisHandler.ts +0 -206
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Multi-backend response cache for GET requests.
3
+ *
4
+ * Backends are selected via the TINA4_CACHE_BACKEND env var:
5
+ * memory — in-process LRU cache (default, zero deps)
6
+ * file — JSON files in data/cache/
7
+ * redis — Redis (raw RESP over TCP, or the `redis` package when present)
8
+ * valkey — Valkey (Redis wire protocol — reuses the Redis backend)
9
+ * memcached — Memcached (zero-dep text protocol over TCP; SHA-256-hashed keys)
10
+ * mongodb — MongoDB TTL collection (optional `mongodb` driver, loaded dynamically)
11
+ * database — a `tina4_cache` table in any Tina4-supported DB (via @tina4/orm)
12
+ *
13
+ * Usage (the KV/module API is ASYNC on Node — Node is async-everywhere):
14
+ * import { responseCache, cacheGet, cacheSet, cacheDelete, cacheClear, cacheStats } from "./cache.js";
15
+ *
16
+ * // As middleware — caches GET responses for ttl seconds
17
+ * middleware.use(responseCache({ ttl: 60 }));
18
+ *
19
+ * // Direct usage (await — same semantics as the other 3 languages, async transport)
20
+ * await cacheSet("key", {"data": "value"}, 120);
21
+ * const value = await cacheGet("key");
22
+ * await cacheDelete("key");
23
+ * await cacheClear();
24
+ * const stats = await cacheStats();
25
+ *
26
+ * Availability + file-fallback (mirrors the Python master):
27
+ * Each network/driver backend reports availability (redis/valkey connect+AUTH+PING,
28
+ * memcached VERSION, mongo connect+ping, database connect). When the configured
29
+ * backend's service is unreachable (or its driver is missing / credentials are
30
+ * wrong), createBackend() logs a warning and falls back to the `file` backend —
31
+ * a real, persistent cache, never a silent no-op. The probe is asynchronous, so
32
+ * createBackend() returns a Promise.
33
+ *
34
+ * Asynchronous, NATIVE network I/O (NO child process):
35
+ * The CacheBackend interface is async (get/set/delete/clear/stats return
36
+ * Promises). The network backends use native async Node I/O — redis/valkey speak
37
+ * RESP over a node:net socket (with AUTH + SELECT db), memcached speaks its text
38
+ * protocol over node:net, and mongodb uses the optional `mongodb` driver. No
39
+ * execFileSync, no child processes — connections are pooled per backend instance
40
+ * so each cache op is a single async round-trip (~sub-ms locally), not a ~30-80ms
41
+ * process spawn. Local backends (memory/file/database-sqlite) resolve immediately.
42
+ *
43
+ * Environment (LOCKED — matches Python exactly):
44
+ * TINA4_CACHE_BACKEND — memory | file | redis | valkey | memcached | mongodb | database (default: memory)
45
+ * TINA4_CACHE_URL — connection URL (redis/valkey/memcached/mongo), or a SQL URL for `database`
46
+ * (database falls back to TINA4_DATABASE_URL)
47
+ * TINA4_CACHE_TTL — default TTL in seconds (default: 60)
48
+ * TINA4_CACHE_MAX_ENTRIES — max entries (default: 1000)
49
+ * TINA4_CACHE_DIR — file backend directory (default: data/cache)
50
+ * TINA4_CACHE_USERNAME — credentials when not embedded in the URL
51
+ * TINA4_CACHE_PASSWORD — credentials when not embedded in the URL
52
+ */
53
+ import type { Middleware } from "./types.js";
54
+ export interface ResponseCacheConfig {
55
+ /** Default TTL in seconds. 0 = disabled. Default: 60 */
56
+ ttl?: number;
57
+ /** Maximum cache entries. Default: 1000 */
58
+ maxEntries?: number;
59
+ /** Only cache these status codes. Default: [200] */
60
+ statusCodes?: number[];
61
+ /** Cache backend: memory | redis | file. Default: from env or memory */
62
+ backend?: string;
63
+ /** Redis URL. Default: from env or redis://localhost:6379 */
64
+ cacheUrl?: string;
65
+ /** File cache directory. Default: from env or data/cache */
66
+ cacheDir?: string;
67
+ }
68
+ interface CacheBackend {
69
+ get(key: string): Promise<unknown | undefined>;
70
+ set(key: string, value: unknown, ttl: number): Promise<void>;
71
+ delete(key: string): Promise<boolean>;
72
+ clear(): Promise<void>;
73
+ /**
74
+ * Evict expired entries and return HOW MANY were actually evicted.
75
+ *
76
+ * REQUIRED, not optional. It used to be neither declared nor implemented, so
77
+ * the module-level sweep() found no backend method and returned a permanent
78
+ * 0: the one API whose job is reclaiming expired space did nothing and
79
+ * reported success. Declaring it here makes "every provider can sweep" a
80
+ * compile-time fact instead of a runtime hope.
81
+ *
82
+ * 0 is the HONEST answer on redis/valkey/memcached/mongodb - they expire
83
+ * entries server-side, so there is nothing left for us to evict. It is the
84
+ * WRONG answer for memory, file and database, which own their own expiry.
85
+ */
86
+ sweep(): Promise<number>;
87
+ stats(): Promise<{
88
+ hits: number;
89
+ misses: number;
90
+ size: number;
91
+ backend: string;
92
+ }>;
93
+ name(): string;
94
+ /**
95
+ * Whether this backend is actually usable (driver present + service
96
+ * reachable). Local backends (memory/file) are always available; network /
97
+ * driver backends override this so the factory can fall back to the file
98
+ * backend. Mirrors the Python master's `is_available()`. Probed asynchronously
99
+ * (connect/AUTH/PING/VERSION/ping) so no child process is spawned.
100
+ */
101
+ isAvailable?(): Promise<boolean>;
102
+ /** One-time async connect/probe. Resolves once the backend has decided
103
+ * availability; createBackend() awaits this before falling back to file. */
104
+ ready?(): Promise<void>;
105
+ }
106
+ /** Public shape of a unified cache backend (for cross-package reuse). */
107
+ export type { CacheBackend };
108
+ /**
109
+ * Build a unified cache backend from explicit params or env vars.
110
+ *
111
+ * Backends: memory (default) | file | redis | valkey | memcached | mongodb |
112
+ * database. Unreachable network/driver backends fall back to the file backend.
113
+ * ASYNC because availability is probed asynchronously (connect/AUTH/PING/ping)
114
+ * — no child process. Exported so @tina4/orm can route its persistent DB query
115
+ * cache through the SAME backends (shared cross-instance) without duplicating
116
+ * the implementation. Callers `await createBackend(...)`.
117
+ */
118
+ export declare function createBackend(config?: {
119
+ backend?: string;
120
+ cacheUrl?: string;
121
+ cacheDir?: string;
122
+ maxEntries?: number;
123
+ }): Promise<CacheBackend>;
124
+ export declare function _getResponseBackend(config?: ResponseCacheConfig): Promise<CacheBackend>;
125
+ export declare function responseCache(config?: ResponseCacheConfig): Middleware;
126
+ /**
127
+ * Clear all cached responses (the responseCache middleware backend).
128
+ * ASYNC on Node — callers `await clearCache()` — because the backend may be a
129
+ * network backend (redis/etc.). Resets the backend's namespace; mirrors the
130
+ * Python ResponseCache.clear_cache() which clears its backend.
131
+ */
132
+ export declare function clearCache(): Promise<void>;
133
+ /**
134
+ * Get KV cache stats — reports the same backend that cacheGet/cacheSet/cacheDelete use,
135
+ * so a value stored via cacheSet() is reflected here. Mirrors cache_stats() in the
136
+ * Python / PHP / Ruby frameworks. (Identical to cacheBackendStats(), kept for parity naming.)
137
+ * ASYNC on Node — callers `await cacheStats()`.
138
+ */
139
+ export declare function cacheStats(): Promise<{
140
+ hits: number;
141
+ misses: number;
142
+ size: number;
143
+ backend: string;
144
+ }>;
145
+ /** Get a value from the cache by key. Returns undefined on miss. */
146
+ export declare function cacheGet(key: string): Promise<unknown | undefined>;
147
+ /** Store a value in the cache with optional TTL (seconds). */
148
+ export declare function cacheSet(key: string, value: unknown, ttl?: number): Promise<void>;
149
+ /** Delete a key from the cache. Returns true if it existed. */
150
+ export declare function cacheDelete(key: string): Promise<boolean>;
151
+ /** Clear all entries from the cache. */
152
+ export declare function cacheClear(): Promise<void>;
153
+ /** Remove expired entries from the cache. Returns count removed. */
154
+ export declare function sweep(): Promise<number>;
155
+ /** Return cache statistics from the active backend. */
156
+ export declare function cacheBackendStats(): Promise<{
157
+ hits: number;
158
+ misses: number;
159
+ size: number;
160
+ backend: string;
161
+ }>;
162
+ /** Reset the default backend (for testing). Closes any pooled connection. */
163
+ export declare function _resetBackend(): void;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Tina4 Constants — HTTP status codes and content types.
3
+ *
4
+ * Standard constants for use in route handlers across all Tina4 frameworks.
5
+ *
6
+ * import { HTTP_OK, HTTP_CREATED, APPLICATION_JSON } from "@tina4/core";
7
+ *
8
+ * get("/api/users", async (request, response) => {
9
+ * return response(users, HTTP_OK);
10
+ * });
11
+ */
12
+ export declare const HTTP_OK = 200;
13
+ export declare const HTTP_CREATED = 201;
14
+ export declare const HTTP_ACCEPTED = 202;
15
+ export declare const HTTP_NO_CONTENT = 204;
16
+ export declare const HTTP_MOVED = 301;
17
+ export declare const HTTP_REDIRECT = 302;
18
+ export declare const HTTP_NOT_MODIFIED = 304;
19
+ export declare const HTTP_BAD_REQUEST = 400;
20
+ export declare const HTTP_UNAUTHORIZED = 401;
21
+ export declare const HTTP_FORBIDDEN = 403;
22
+ export declare const HTTP_NOT_FOUND = 404;
23
+ export declare const HTTP_METHOD_NOT_ALLOWED = 405;
24
+ export declare const HTTP_CONFLICT = 409;
25
+ export declare const HTTP_GONE = 410;
26
+ export declare const HTTP_UNPROCESSABLE = 422;
27
+ export declare const HTTP_TOO_MANY = 429;
28
+ export declare const HTTP_SERVER_ERROR = 500;
29
+ export declare const HTTP_BAD_GATEWAY = 502;
30
+ export declare const HTTP_UNAVAILABLE = 503;
31
+ export declare const APPLICATION_JSON = "application/json";
32
+ export declare const APPLICATION_XML = "application/xml";
33
+ export declare const APPLICATION_FORM = "application/x-www-form-urlencoded";
34
+ export declare const APPLICATION_OCTET = "application/octet-stream";
35
+ export declare const TEXT_HTML = "text/html; charset=utf-8";
36
+ export declare const TEXT_PLAIN = "text/plain; charset=utf-8";
37
+ export declare const TEXT_CSV = "text/csv";
38
+ export declare const TEXT_XML = "text/xml";
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Lightweight dependency injection container.
3
+ *
4
+ * Matches the Python tina4_python.container.Container API.
5
+ *
6
+ * import { Container, container } from "@tina4/core";
7
+ *
8
+ * container.register("mailer", () => new MailService());
9
+ * container.singleton("db", () => new Database("sqlite:///app.db"));
10
+ *
11
+ * const mailer = container.get<MailService>("mailer"); // new instance each call
12
+ * const db = container.get<Database>("db"); // same instance every call
13
+ *
14
+ * Node.js is single-threaded so no locking is needed.
15
+ */
16
+ export declare class Container {
17
+ private transients;
18
+ private singletons;
19
+ private instances;
20
+ /**
21
+ * Register a transient factory — a new instance is created on every `get()` call.
22
+ */
23
+ register(name: string, factory: () => unknown): void;
24
+ /**
25
+ * Register a singleton factory — created once on first `get()`, then memoised.
26
+ */
27
+ singleton(name: string, factory: () => unknown): void;
28
+ /**
29
+ * Resolve a dependency by name.
30
+ *
31
+ * Throws an `Error` if the name has not been registered.
32
+ */
33
+ get<T = unknown>(name: string): T;
34
+ /**
35
+ * Return `true` if *name* has been registered (transient or singleton).
36
+ */
37
+ has(name: string): boolean;
38
+ /**
39
+ * Clear all registrations and cached instances.
40
+ */
41
+ reset(): void;
42
+ }
43
+ /** Default container instance. */
44
+ export declare const container: Container;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Lowercase, strip diacritics, join comma-grouped numbers, split camelCase.
3
+ *
4
+ * Applied symmetrically to the indexed `body` and to query tokens so matching
5
+ * is consistent: a query for `field` reaches `IntegerField`. The trailing
6
+ * NFKD-normalise + strip-non-ASCII mirrors python's
7
+ * `unicodedata.normalize("NFKD", ...).encode("ascii", "ignore")`.
8
+ */
9
+ export declare function fold(text: string): string;
10
+ /**
11
+ * Fold simple plurals: strip one trailing 's', never from ss/us/is endings
12
+ * (class, status, axis). QUERY-side only — so `fields` in a question also
13
+ * reaches `Field` definitions.
14
+ */
15
+ export declare function lightStem(token: string): string;
16
+ /** Accent-folded lowercase alphanumeric tokens (digits kept). */
17
+ export declare function terms(text: string): string[];
18
+ /**
19
+ * Chunk source on top-level def/class/decorator boundaries (sentence chunking
20
+ * shreds code). Segments are packed up to `maxLines`, and every chunk starts
21
+ * with a `# file: <path>` line so the path's tokens are indexed — 'where is the
22
+ * router?' should match core/router.ts by name.
23
+ *
24
+ * Returns a list of `[index, chunkText]` pairs.
25
+ */
26
+ export declare function chunkCode(text: string, path?: string, maxLines?: number): Array<[number, string]>;
27
+ /**
28
+ * Chunk prose/docs into sentence-packed windows of at most `maxWords` words.
29
+ * Returns a list of `[index, chunkText]` pairs.
30
+ */
31
+ export declare function chunkText(text: string, maxWords?: number): Array<[number, string]>;
@@ -0,0 +1,93 @@
1
+ /** True if this build of node:sqlite supports FTS5. */
2
+ export declare function fts5Supported(): boolean;
3
+ export interface SearchHit {
4
+ path: string;
5
+ score: number;
6
+ snippet: string;
7
+ }
8
+ /**
9
+ * A SQLite FTS5 index over a project's source + docs.
10
+ *
11
+ * - indexPath(file, label?) upsert one file (delete-by-path, re-chunk, insert)
12
+ * - indexRoot(root) walk a tree, index every eligible file
13
+ * - search(query, k) [{path, score, snippet}] ranked by bm25() with
14
+ * source-over-tests + definition-first reordering
15
+ * - reindexFile(changed) upsert one changed file against the indexed root
16
+ */
17
+ export declare class Context {
18
+ path: string;
19
+ root: string | null;
20
+ available: boolean;
21
+ private conn;
22
+ /**
23
+ * @param dbPath on-disk index file (its parent dir is created).
24
+ * @param fts5Check overrides FTS5 detection (used by tests to exercise the
25
+ * graceful-degradation path); defaults to a real probe.
26
+ */
27
+ constructor(dbPath?: string, fts5Check?: () => boolean);
28
+ /** Whether this Node build's node:sqlite supports FTS5. */
29
+ static fts5Available(): boolean;
30
+ private ensureTable;
31
+ /** Drop and recreate the index (full rebuild starting point). */
32
+ reset(): void;
33
+ private static chunksFor;
34
+ /**
35
+ * UPSERT one file into the index: delete this path's existing chunks,
36
+ * re-chunk the current contents, insert. `label` is the stored/citation path
37
+ * (defaults to `file`) and MUST be stable across calls for the same file so
38
+ * the delete targets the right rows. Returns rows inserted.
39
+ */
40
+ indexPath(file: string, label?: string): number;
41
+ /**
42
+ * The per-file filter used by both indexRoot and reindexFile. Directory
43
+ * skipping is handled separately.
44
+ */
45
+ private static eligible;
46
+ /**
47
+ * Walk `root`, indexing every eligible file (skips vendor/build/runtime
48
+ * dirs). Paths are stored RELATIVE to `root` for clean citations. Records
49
+ * `root` so reindexFile can relabel a changed file consistently. Returns the
50
+ * total number of chunks inserted.
51
+ */
52
+ indexRoot(root: string): number;
53
+ /**
54
+ * Re-index a single changed file into the LIVE index — the hook the dev
55
+ * WebSocket reload trigger (POST /__dev/api/reload) calls so code_search
56
+ * tracks edits without a rebuild. Resolves `changedPath` against the indexed
57
+ * root, then: outside root / under a skip-or-dot dir / ineligible → skip (-1);
58
+ * deleted → drop its chunks (0); otherwise UPSERT (rows). No-op (-1) until
59
+ * indexRoot has run (nothing to keep fresh yet).
60
+ */
61
+ reindexFile(changedPath: string): number;
62
+ private matchExpr;
63
+ private static isTestlike;
64
+ private static defines;
65
+ /**
66
+ * Return the top-`k` chunks as `[{path, score, snippet}]`, ranked by `bm25()`
67
+ * then reordered with two stable, proven passes:
68
+ * - source-over-tests: a test that merely mentions a symbol sinks below the
69
+ * source that defines it (skipped when the query is about tests);
70
+ * - definition-first: a chunk that DEFINES a queried symbol rises above
71
+ * chunks that only use it.
72
+ * Score is a higher-is-better float (sqlite's bm25 sign flipped).
73
+ */
74
+ search(query: string, k?: number): SearchHit[];
75
+ private static snippet;
76
+ count(): number;
77
+ isEmpty(): boolean;
78
+ close(): void;
79
+ }
80
+ export declare const _sharedContexts: Map<string, Context>;
81
+ /**
82
+ * Get (or create) the process-wide Context at `db` (default
83
+ * `<cwd>/.tina4/context.db`). If `root` is given and the index is empty, builds
84
+ * it once. This is what code_search uses so the reload hook can keep the SAME
85
+ * index fresh.
86
+ */
87
+ export declare function defaultContext(root?: string, db?: string): Context;
88
+ /**
89
+ * Return the already-created shared Context for `db` (or undefined). Used by the
90
+ * reload hook so a file change reindexes an EXISTING index but never creates one
91
+ * on its own (nothing to keep fresh until code_search runs).
92
+ */
93
+ export declare function existingContext(db?: string): Context | undefined;
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Tina4 Dev Admin — Built-in development dashboard, zero dependencies.
3
+ *
4
+ * Auto-registered admin panel for development mode.
5
+ * Provides API endpoints and a single-page UI at /__dev/ for:
6
+ * - Route inspector (all registered routes, methods)
7
+ * - Message log (tracked debug messages)
8
+ * - Request inspector (captured HTTP requests)
9
+ * - System info (Node.js version, V8, memory, uptime, platform)
10
+ */
11
+ import type { Router } from "./router.js";
12
+ interface LogEntry {
13
+ id: string;
14
+ timestamp: string;
15
+ category: string;
16
+ level: string;
17
+ message: string;
18
+ data?: unknown;
19
+ }
20
+ interface RequestEntry {
21
+ id: string;
22
+ timestamp: string;
23
+ method: string;
24
+ path: string;
25
+ status: number;
26
+ durationMs: number;
27
+ }
28
+ interface RequestStats {
29
+ total: number;
30
+ avgMs: number;
31
+ errors: number;
32
+ slowestMs: number;
33
+ }
34
+ interface ErrorEntry {
35
+ id: string;
36
+ timestamp: string;
37
+ message: string;
38
+ stack?: string;
39
+ resolved: boolean;
40
+ }
41
+ interface QueueJob {
42
+ id: string;
43
+ timestamp: string;
44
+ name: string;
45
+ status: "pending" | "completed" | "failed" | "reserved";
46
+ payload?: unknown;
47
+ result?: unknown;
48
+ error?: string;
49
+ }
50
+ interface WsConnection {
51
+ id: string;
52
+ connectedAt: string;
53
+ remoteAddress: string;
54
+ path: string;
55
+ }
56
+ export declare class MessageLog {
57
+ private static messages;
58
+ private static maxMessages;
59
+ static log(category: string, level: string, message: string, data?: unknown): void;
60
+ static get(category?: string, limit?: number): LogEntry[];
61
+ static clear(category?: string): void;
62
+ static count(): Record<string, number>;
63
+ }
64
+ export declare class RequestInspector {
65
+ private static requests;
66
+ private static maxRequests;
67
+ static capture(method: string, path: string, status: number, duration: number): void;
68
+ static get(limit?: number): RequestEntry[];
69
+ static stats(): RequestStats;
70
+ static clear(): void;
71
+ }
72
+ export declare class ErrorTracker {
73
+ private static errors;
74
+ private static maxErrors;
75
+ private static registered;
76
+ /**
77
+ * Capture an error with dedup (matches PHP/Ruby/Python signature).
78
+ * Duplicate errors (same message) increment count and update last_seen.
79
+ */
80
+ static capture(errorType: string, message: string, traceback?: string, file?: string, line?: number): void;
81
+ /** Legacy alias for capture (backward compatibility). */
82
+ static track(message: string, stack?: string): void;
83
+ static get(): ErrorEntry[];
84
+ static resolve(id: string): boolean;
85
+ static clearResolved(): void;
86
+ /** Remove ALL tracked errors. */
87
+ static clearAll(): void;
88
+ /** Health summary — are there unresolved errors? */
89
+ static health(): {
90
+ healthy: boolean;
91
+ total: number;
92
+ unresolved: number;
93
+ resolved: number;
94
+ };
95
+ /** Count of unresolved errors. */
96
+ static unresolvedCount(): number;
97
+ /** Reset all state (for testing). */
98
+ static reset(): void;
99
+ /**
100
+ * Register global error handlers to feed the tracker.
101
+ * Safe to call multiple times — only registers once.
102
+ */
103
+ static register(): void;
104
+ }
105
+ export declare class DevMailboxStore {
106
+ private static mailbox;
107
+ static inbox(folder?: string, limit?: number, offset?: number): import("./messenger.js").EmailMessage[];
108
+ static read(id: string): import("./messenger.js").EmailMessage | null;
109
+ static seed(count?: number): void;
110
+ static clear(folder?: string): void;
111
+ static unreadCount(): number;
112
+ static count(folder?: string): {
113
+ inbox: number;
114
+ outbox: number;
115
+ total: number;
116
+ };
117
+ }
118
+ export declare class DevQueue {
119
+ private static jobs;
120
+ static stats(): {
121
+ pending: number;
122
+ completed: number;
123
+ failed: number;
124
+ reserved: number;
125
+ jobs: QueueJob[];
126
+ };
127
+ static add(name: string, payload?: unknown): QueueJob;
128
+ static retryFailed(): number;
129
+ static purgeCompleted(): number;
130
+ static replay(id: string): QueueJob | undefined;
131
+ }
132
+ export declare class WsTracker {
133
+ private static connections;
134
+ static add(remoteAddress: string, path: string): string;
135
+ static remove(id: string): boolean;
136
+ static list(): WsConnection[];
137
+ }
138
+ export declare class DevAdmin {
139
+ /**
140
+ * Check whether dev mode is enabled.
141
+ */
142
+ static isEnabled(): boolean;
143
+ /**
144
+ * Register all /__dev routes on the given router.
145
+ */
146
+ static register(router: Router): void;
147
+ /**
148
+ * Returns the dev toolbar HTML to inject into HTML pages.
149
+ */
150
+ static renderToolbarHtml(ctx: {
151
+ version: string;
152
+ method: string;
153
+ path: string;
154
+ matchedPattern: string;
155
+ requestId: string;
156
+ routeCount: number;
157
+ }): string;
158
+ }
159
+ /**
160
+ * Return the base URL for the co-located Rust agent server.
161
+ *
162
+ * Mirrors Python's `_supervisor_base_url()` in
163
+ * `tina4_python/dev_admin/__init__.py`. Resolution order:
164
+ * 1. `TINA4_SUPERVISOR_URL` — explicit full URL.
165
+ * 2. `TINA4_AGENT_PORT` — explicit port on 127.0.0.1.
166
+ * 3. `PORT` + 2000 — auto-derived (matches `tina4 serve` agent port).
167
+ * 4. Fallback `http://127.0.0.1:9145` — matches standalone `tina4 agent`.
168
+ */
169
+ export declare function supervisorBaseUrl(): string;
170
+ /**
171
+ * Resolve a CodeMirror-friendly language id from a file path's basename.
172
+ *
173
+ * - `Dockerfile` / `Dockerfile.dev` / `Dockerfile.prod` (no extension) → "dockerfile"
174
+ * - `.env.example` (two-part) and `.env` → "env"
175
+ * - otherwise the file extension is looked up in DEV_ADMIN_LANG_MAP
176
+ * - anything unknown → "text"
177
+ */
178
+ export declare function devAdminLanguage(rel: string): string;
179
+ export {};
@@ -0,0 +1,54 @@
1
+ import type { SendResult, EmailMessage } from "./messenger.js";
2
+ export declare class DevMailbox {
3
+ private mailboxDir;
4
+ constructor(mailboxDir?: string);
5
+ /**
6
+ * Ensure a folder directory exists.
7
+ */
8
+ private ensureFolder;
9
+ /**
10
+ * Capture an email to the dev mailbox instead of sending it.
11
+ *
12
+ * The parameter order MATCHES Messenger.send() on purpose. It did not before:
13
+ * send()'s 5th positional was `text` and capture()'s was `cc`, so the same call
14
+ * meant different things depending on which door it came through -- that mismatch
15
+ * IS nodejs#42.
16
+ *
17
+ * BREAKING: `text` is now the 5th positional. A caller passing cc positionally
18
+ * must move it. Aligning the two signatures is the fix; leaving them apart would
19
+ * preserve the bug.
20
+ */
21
+ capture(to: string | string[], subject: string, body: string, html?: boolean, text?: string, cc?: string | string[], bcc?: string | string[], replyTo?: string, attachments?: string[], from?: string): SendResult;
22
+ /**
23
+ * List messages from a folder (default: inbox).
24
+ */
25
+ inbox(limit?: number, offset?: number, folder?: string): EmailMessage[];
26
+ /**
27
+ * Read a single message by ID. Searches all folders.
28
+ */
29
+ read(msgId: string): EmailMessage | null;
30
+ /**
31
+ * Count unread messages in the inbox.
32
+ */
33
+ unreadCount(): number;
34
+ /**
35
+ * Delete a message by ID. Removes from all folders.
36
+ */
37
+ delete(msgId: string): boolean;
38
+ /**
39
+ * Clear all messages from a folder, or all folders if none specified.
40
+ */
41
+ clear(folder?: string): void;
42
+ /**
43
+ * Seed the mailbox with sample messages for development.
44
+ */
45
+ seed(count?: number): void;
46
+ /**
47
+ * Count messages in a folder, or all folders if none specified.
48
+ */
49
+ count(folder?: string): {
50
+ inbox: number;
51
+ outbox: number;
52
+ total: number;
53
+ };
54
+ }