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.
- package/CLAUDE.md +170 -28
- package/README.md +2 -2
- package/package.json +13 -9
- package/packages/cli/dist/bin.js +33126 -30055
- package/packages/cli/src/commands/metrics.ts +17 -11
- package/packages/cli/src/commands/serve.ts +10 -9
- package/packages/core/dist/index.js +33062 -29908
- package/packages/core/src/ai.ts +7 -1
- package/packages/core/src/auth.ts +191 -39
- package/packages/core/src/background.ts +19 -19
- package/packages/core/src/cache.ts +492 -49
- package/packages/core/src/devAdmin.ts +79 -32
- package/packages/core/src/devMailbox.ts +20 -44
- package/packages/core/src/dispatchPipeline.ts +285 -0
- package/packages/core/src/dotenv.ts +185 -40
- package/packages/core/src/index.ts +7 -6
- package/packages/core/src/logger.ts +257 -36
- package/packages/core/src/mcp.ts +1 -1
- package/packages/core/src/messenger.ts +81 -13
- package/packages/core/src/metrics.ts +199 -961
- package/packages/core/src/middleware.ts +390 -123
- package/packages/core/src/queue.ts +188 -32
- package/packages/core/src/queueBackends/kafkaBackend.ts +109 -13
- package/packages/core/src/queueBackends/liteBackend.ts +13 -0
- package/packages/core/src/queueBackends/mongoBackend.ts +101 -9
- package/packages/core/src/queueBackends/rabbitmqBackend.ts +22 -4
- package/packages/core/src/rateLimiter.ts +10 -5
- package/packages/core/src/request.ts +6 -9
- package/packages/core/src/response.ts +46 -1
- package/packages/core/src/router.ts +29 -4
- package/packages/core/src/server.ts +751 -414
- package/packages/core/src/session.ts +244 -27
- package/packages/core/src/sessionHandlers/childError.ts +72 -0
- package/packages/core/src/sessionHandlers/databaseHandler.ts +338 -48
- package/packages/core/src/sessionHandlers/memcachedHandler.ts +181 -0
- package/packages/core/src/sessionHandlers/mongoClient.ts +293 -202
- package/packages/core/src/sessionHandlers/mongoHandler.ts +88 -8
- package/packages/core/src/sessionHandlers/respClient.ts +16 -143
- package/packages/core/src/sessionHandlers/sqlClient.ts +290 -0
- package/packages/core/src/sessionHandlers/syncBridge.ts +190 -0
- package/packages/core/src/sessionHandlers/syncSocket.ts +236 -0
- package/packages/core/src/testClient.ts +18 -5
- package/packages/core/src/trustedProxy.ts +249 -0
- package/packages/core/src/types.ts +29 -5
- package/packages/core/src/websocket.ts +66 -0
- package/packages/frond/dist/index.js +74 -31
- package/packages/frond/src/engine.ts +99 -33
- package/packages/orm/dist/index.js +26554 -23400
- package/packages/orm/src/adapters/firebird.ts +183 -56
- package/packages/orm/src/adapters/mongodb.ts +25 -4
- package/packages/orm/src/adapters/mssql.ts +114 -29
- package/packages/orm/src/adapters/mysql.ts +103 -40
- package/packages/orm/src/adapters/odbc.ts +44 -21
- package/packages/orm/src/adapters/postgres.ts +118 -26
- package/packages/orm/src/adapters/sqlDialect.ts +120 -0
- package/packages/orm/src/adapters/sqlite.ts +64 -25
- package/packages/orm/src/baseModel.ts +135 -40
- package/packages/orm/src/cachedDatabase.ts +43 -19
- package/packages/orm/src/connectTimeout.ts +265 -0
- package/packages/orm/src/database.ts +338 -198
- package/packages/orm/src/databaseResult.ts +65 -13
- package/packages/orm/src/databaseUrl.ts +484 -0
- package/packages/orm/src/docstore.ts +386 -145
- package/packages/orm/src/index.ts +13 -3
- package/packages/orm/src/migration.ts +18 -3
- package/packages/orm/src/queryBuilder.ts +38 -4
- package/packages/orm/src/sqlTranslator.ts +310 -4
- package/packages/orm/src/types.ts +15 -4
- package/types/cli/src/bin.d.ts +92 -0
- package/types/cli/src/commands/build.d.ts +2 -0
- package/types/cli/src/commands/generate.d.ts +47 -0
- package/types/cli/src/commands/init.d.ts +1 -0
- package/types/cli/src/commands/metrics.d.ts +6 -0
- package/types/cli/src/commands/migrate.d.ts +1 -0
- package/types/cli/src/commands/migrateCreate.d.ts +1 -0
- package/types/cli/src/commands/migrateRollback.d.ts +1 -0
- package/types/cli/src/commands/migrateStatus.d.ts +1 -0
- package/types/cli/src/commands/queue.d.ts +20 -0
- package/types/cli/src/commands/routes.d.ts +1 -0
- package/types/cli/src/commands/seed.d.ts +1 -0
- package/types/cli/src/commands/serve.d.ts +6 -0
- package/types/cli/src/commands/test.d.ts +1 -0
- package/types/core/src/ai.d.ts +64 -0
- package/types/core/src/api.d.ts +262 -0
- package/types/core/src/auth.d.ts +177 -0
- package/types/core/src/authGate.d.ts +20 -0
- package/types/core/src/background.d.ts +34 -0
- package/types/core/src/cache.d.ts +163 -0
- package/types/core/src/constants.d.ts +38 -0
- package/types/core/src/container.d.ts +44 -0
- package/types/core/src/context/chunker.d.ts +31 -0
- package/types/core/src/context/index.d.ts +93 -0
- package/types/core/src/devAdmin.d.ts +179 -0
- package/types/core/src/devMailbox.d.ts +54 -0
- package/types/core/src/dispatchPipeline.d.ts +117 -0
- package/types/core/src/docs.d.ts +141 -0
- package/types/core/src/docsAutoDiscovery.d.ts +6 -0
- package/types/core/src/dotenv.d.ts +87 -0
- package/types/core/src/env.d.ts +28 -0
- package/types/core/src/errorOverlay.d.ts +36 -0
- package/types/core/src/events.d.ts +75 -0
- package/types/core/src/fakeData.d.ts +55 -0
- package/types/core/src/feedback.d.ts +90 -0
- package/types/core/src/graphql.d.ts +207 -0
- package/types/core/src/health.d.ts +22 -0
- package/types/core/src/htmlElement.d.ts +75 -0
- package/types/core/src/i18n.d.ts +37 -0
- package/types/core/src/index.d.ts +92 -0
- package/types/core/src/job.d.ts +39 -0
- package/types/core/src/logger.d.ts +200 -0
- package/types/core/src/mcp.d.ts +248 -0
- package/types/core/src/messenger.d.ts +191 -0
- package/types/core/src/metrics.d.ts +41 -0
- package/types/core/src/middleware.d.ts +330 -0
- package/types/core/src/mqtt.d.ts +257 -0
- package/types/core/src/mqttMessage.d.ts +67 -0
- package/types/core/src/plan.d.ts +96 -0
- package/types/core/src/projectIndex.d.ts +56 -0
- package/types/core/src/queue.d.ts +268 -0
- package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
- package/types/core/src/queueBackends/liteBackend.d.ts +128 -0
- package/types/core/src/queueBackends/mongoBackend.d.ts +119 -0
- package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
- package/types/core/src/rateLimiter.d.ts +49 -0
- package/types/core/src/request.d.ts +25 -0
- package/types/core/src/response.d.ts +28 -0
- package/types/core/src/routeDiscovery.d.ts +12 -0
- package/types/core/src/router.d.ts +366 -0
- package/types/core/src/scss.d.ts +19 -0
- package/types/core/src/server.d.ts +146 -0
- package/types/core/src/service.d.ts +115 -0
- package/types/core/src/session.d.ts +341 -0
- package/types/core/src/sessionHandlers/childError.d.ts +34 -0
- package/types/core/src/sessionHandlers/databaseHandler.d.ts +97 -0
- package/types/core/src/sessionHandlers/memcachedHandler.d.ts +60 -0
- package/types/core/src/sessionHandlers/mongoClient.d.ts +35 -0
- package/types/core/src/sessionHandlers/mongoHandler.d.ts +109 -0
- package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
- package/types/core/src/sessionHandlers/sqlClient.d.ts +39 -0
- package/types/core/src/sessionHandlers/syncBridge.d.ts +91 -0
- package/types/core/src/sessionHandlers/syncSocket.d.ts +49 -0
- package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
- package/types/core/src/static.d.ts +2 -0
- package/types/core/src/test.d.ts +94 -0
- package/types/core/src/testClient.d.ts +36 -0
- package/types/core/src/testing.d.ts +58 -0
- package/types/core/src/trustedProxy.d.ts +44 -0
- package/types/core/src/types.d.ts +242 -0
- package/types/core/src/validator.d.ts +52 -0
- package/types/core/src/websocket.d.ts +402 -0
- package/types/core/src/websocketBackplane.d.ts +166 -0
- package/types/core/src/websocketConnection.d.ts +54 -0
- package/types/core/src/wsdl.d.ts +101 -0
- package/types/frond/src/engine.d.ts +263 -0
- package/types/frond/src/index.d.ts +2 -0
- package/types/orm/src/adapters/firebird.d.ts +183 -0
- package/types/orm/src/adapters/mongodb.d.ts +81 -0
- package/types/orm/src/adapters/mssql.d.ts +77 -0
- package/types/orm/src/adapters/mysql.d.ts +67 -0
- package/types/orm/src/adapters/odbc.d.ts +94 -0
- package/types/orm/src/adapters/postgres.d.ts +86 -0
- package/types/orm/src/adapters/sqlDialect.d.ts +71 -0
- package/types/orm/src/adapters/sqlite.d.ts +68 -0
- package/types/orm/src/autoCrud.d.ts +73 -0
- package/types/orm/src/baseModel.d.ts +427 -0
- package/types/orm/src/cachedDatabase.d.ts +190 -0
- package/types/orm/src/connectTimeout.d.ts +100 -0
- package/types/orm/src/database.d.ts +655 -0
- package/types/orm/src/databaseResult.d.ts +109 -0
- package/types/orm/src/databaseUrl.d.ts +125 -0
- package/types/orm/src/docstore.d.ts +241 -0
- package/types/orm/src/fakeData.d.ts +22 -0
- package/types/orm/src/index.d.ts +43 -0
- package/types/orm/src/migration.d.ts +275 -0
- package/types/orm/src/model.d.ts +7 -0
- package/types/orm/src/query.d.ts +14 -0
- package/types/orm/src/queryBuilder.d.ts +193 -0
- package/types/orm/src/realtime/index.d.ts +7 -0
- package/types/orm/src/realtime/models/attachment.d.ts +43 -0
- package/types/orm/src/realtime/models/channel.d.ts +32 -0
- package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
- package/types/orm/src/realtime/models/message.d.ts +36 -0
- package/types/orm/src/realtime/models/workspace.d.ts +26 -0
- package/types/orm/src/realtime/realtime.d.ts +24 -0
- package/types/orm/src/realtime/storage.d.ts +61 -0
- package/types/orm/src/seeder.d.ts +118 -0
- package/types/orm/src/sqlTranslator.d.ts +258 -0
- package/types/orm/src/types.d.ts +148 -0
- package/types/orm/src/validation.d.ts +6 -0
- package/types/swagger/src/generator.d.ts +46 -0
- package/types/swagger/src/index.d.ts +2 -0
- package/types/swagger/src/ui.d.ts +11 -0
- 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
|
+
}
|