tina4-nodejs 3.13.92 → 3.13.94
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 +16 -3
- package/README.md +1 -1
- package/package.json +12 -9
- package/packages/cli/dist/bin.js +1260 -969
- package/packages/core/dist/index.js +1260 -969
- package/packages/core/src/devMailbox.ts +20 -44
- package/packages/core/src/index.ts +2 -2
- package/packages/core/src/messenger.ts +72 -0
- package/packages/core/src/queueBackends/kafkaBackend.ts +108 -12
- package/packages/core/src/sessionHandlers/childError.ts +72 -0
- package/packages/core/src/sessionHandlers/mongoClient.ts +9 -3
- package/packages/core/src/sessionHandlers/redisHandler.ts +18 -5
- package/packages/core/src/sessionHandlers/respClient.ts +5 -1
- package/packages/frond/dist/index.js +74 -31
- package/packages/frond/src/engine.ts +99 -33
- package/packages/orm/dist/index.js +3055 -2764
- package/packages/orm/src/adapters/sqlite.ts +4 -1
- package/packages/orm/src/database.ts +108 -8
- 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 +154 -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 +160 -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/docs.d.ts +141 -0
- package/types/core/src/docsAutoDiscovery.d.ts +6 -0
- package/types/core/src/dotenv.d.ts +65 -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 +93 -0
- package/types/core/src/job.d.ts +39 -0
- package/types/core/src/logger.d.ts +123 -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 +77 -0
- package/types/core/src/middleware.d.ts +207 -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 +219 -0
- package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
- package/types/core/src/queueBackends/liteBackend.d.ts +119 -0
- package/types/core/src/queueBackends/mongoBackend.d.ts +97 -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 +355 -0
- package/types/core/src/scss.d.ts +19 -0
- package/types/core/src/server.d.ts +131 -0
- package/types/core/src/service.d.ts +115 -0
- package/types/core/src/session.d.ts +256 -0
- package/types/core/src/sessionHandlers/childError.d.ts +34 -0
- package/types/core/src/sessionHandlers/databaseHandler.d.ts +42 -0
- package/types/core/src/sessionHandlers/mongoClient.d.ts +24 -0
- package/types/core/src/sessionHandlers/mongoHandler.d.ts +61 -0
- package/types/core/src/sessionHandlers/redisHandler.d.ts +60 -0
- package/types/core/src/sessionHandlers/respClient.d.ts +22 -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/types.d.ts +219 -0
- package/types/core/src/validator.d.ts +52 -0
- package/types/core/src/websocket.d.ts +376 -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 +138 -0
- package/types/orm/src/adapters/mongodb.d.ts +81 -0
- package/types/orm/src/adapters/mssql.d.ts +70 -0
- package/types/orm/src/adapters/mysql.d.ts +66 -0
- package/types/orm/src/adapters/odbc.d.ts +97 -0
- package/types/orm/src/adapters/postgres.d.ts +85 -0
- package/types/orm/src/adapters/sqlite.d.ts +56 -0
- package/types/orm/src/autoCrud.d.ts +73 -0
- package/types/orm/src/baseModel.d.ts +391 -0
- package/types/orm/src/cachedDatabase.d.ts +177 -0
- package/types/orm/src/database.d.ts +609 -0
- package/types/orm/src/databaseResult.d.ts +85 -0
- package/types/orm/src/docstore.d.ts +182 -0
- package/types/orm/src/fakeData.d.ts +22 -0
- package/types/orm/src/index.d.ts +40 -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 +173 -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 +134 -0
- package/types/orm/src/types.d.ts +138 -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
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tina4 Live API RAG — `Docs` module.
|
|
3
|
+
*
|
|
4
|
+
* Walks framework packages (`@tina4/core`, `@tina4/orm`, `@tina4/swagger`,
|
|
5
|
+
* `@tina4/frond`) and the user project's `src/` tree via lightweight TS
|
|
6
|
+
* regex parsing (no AST — works on .ts files without importing them, so
|
|
7
|
+
* user-code import errors don't break reflection).
|
|
8
|
+
*
|
|
9
|
+
* Exposes ranked search, class/method specs, a flat index, MCP-style
|
|
10
|
+
* static mirrors, and a Markdown drift/sync helper. Zero new runtime
|
|
11
|
+
* dependencies — Node stdlib only.
|
|
12
|
+
*
|
|
13
|
+
* Spec: plan/v3/22-LIVE-API-RAG.md
|
|
14
|
+
*
|
|
15
|
+
* Method names follow Tina4 Node.js convention (camelCase) — see PHP
|
|
16
|
+
* `Tina4\Docs` and Python `tina4_python.docs.Docs` for parity references.
|
|
17
|
+
*/
|
|
18
|
+
export interface DocsHit {
|
|
19
|
+
fqn: string;
|
|
20
|
+
kind: "class" | "method" | "function" | "property";
|
|
21
|
+
name: string;
|
|
22
|
+
signature: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
file: string;
|
|
25
|
+
line: number;
|
|
26
|
+
version: string;
|
|
27
|
+
source: "framework" | "user" | "vendor";
|
|
28
|
+
visibility: "public" | "protected" | "private";
|
|
29
|
+
static?: boolean;
|
|
30
|
+
class?: string;
|
|
31
|
+
score: number;
|
|
32
|
+
}
|
|
33
|
+
export interface MethodSpec {
|
|
34
|
+
name: string;
|
|
35
|
+
fqn: string;
|
|
36
|
+
class: string;
|
|
37
|
+
kind: "method";
|
|
38
|
+
signature: string;
|
|
39
|
+
summary: string;
|
|
40
|
+
docblock: string;
|
|
41
|
+
file: string;
|
|
42
|
+
line: number;
|
|
43
|
+
visibility: "public" | "protected" | "private";
|
|
44
|
+
static: boolean;
|
|
45
|
+
source: "framework" | "user" | "vendor";
|
|
46
|
+
version: string;
|
|
47
|
+
params: Array<{
|
|
48
|
+
name: string;
|
|
49
|
+
type: string;
|
|
50
|
+
default?: string | null;
|
|
51
|
+
}>;
|
|
52
|
+
return: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ClassSpec {
|
|
55
|
+
fqn: string;
|
|
56
|
+
kind: "class";
|
|
57
|
+
name: string;
|
|
58
|
+
file: string;
|
|
59
|
+
line: number;
|
|
60
|
+
summary: string;
|
|
61
|
+
docblock: string;
|
|
62
|
+
source: "framework" | "user" | "vendor";
|
|
63
|
+
version: string;
|
|
64
|
+
methods: Array<Omit<MethodSpec, "params" | "return"> & {
|
|
65
|
+
params?: unknown[];
|
|
66
|
+
return?: string;
|
|
67
|
+
}>;
|
|
68
|
+
properties: unknown[];
|
|
69
|
+
}
|
|
70
|
+
export interface IndexEntry {
|
|
71
|
+
fqn: string;
|
|
72
|
+
kind: "class" | "method" | "function" | "property";
|
|
73
|
+
name: string;
|
|
74
|
+
signature: string;
|
|
75
|
+
summary: string;
|
|
76
|
+
file: string;
|
|
77
|
+
line: number;
|
|
78
|
+
version: string;
|
|
79
|
+
source: "framework" | "user" | "vendor";
|
|
80
|
+
visibility: "public" | "protected" | "private";
|
|
81
|
+
static?: boolean;
|
|
82
|
+
class?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface DriftHit {
|
|
85
|
+
method: string;
|
|
86
|
+
line: number;
|
|
87
|
+
block: string;
|
|
88
|
+
}
|
|
89
|
+
export declare class Docs {
|
|
90
|
+
private projectRoot;
|
|
91
|
+
private frameworkRoots;
|
|
92
|
+
private version;
|
|
93
|
+
private indexCache;
|
|
94
|
+
private frameworkEntries;
|
|
95
|
+
private userEntries;
|
|
96
|
+
private userMtime;
|
|
97
|
+
private frameworkMtime;
|
|
98
|
+
constructor(projectRoot: string);
|
|
99
|
+
/**
|
|
100
|
+
* Search the merged framework + user index for query-matching entities.
|
|
101
|
+
* Source filter accepts `all` (default), `framework`, `user`, `vendor`.
|
|
102
|
+
* Private/underscore methods are excluded unless `includePrivate=true`.
|
|
103
|
+
*/
|
|
104
|
+
search(query: string, k?: number, source?: string, includePrivate?: boolean): DocsHit[];
|
|
105
|
+
/**
|
|
106
|
+
* Resolve a class by exact FQN, documented public import path, or bare name.
|
|
107
|
+
*
|
|
108
|
+
* Node stores the bare class name as the FQN (`Database`), but a developer
|
|
109
|
+
* reading the docs may type the published path (`@tina4/orm.Database`,
|
|
110
|
+
* `orm/Database`) or just `Database`. Match exactly first, then by class
|
|
111
|
+
* name (last path segment), disambiguating by requiring the given segments
|
|
112
|
+
* to appear in the stored FQN/file (framework + shortest wins). Unknown
|
|
113
|
+
* names stay `null` — no false positives.
|
|
114
|
+
*/
|
|
115
|
+
private resolveClassEntry;
|
|
116
|
+
/**
|
|
117
|
+
* Return the full spec for a single class, or `null` if not found.
|
|
118
|
+
*/
|
|
119
|
+
classSpec(fqn: string): ClassSpec | null;
|
|
120
|
+
/**
|
|
121
|
+
* Return the spec for a single method, or `null` if unknown.
|
|
122
|
+
*/
|
|
123
|
+
methodSpec(classFqn: string, methodName: string): MethodSpec | null;
|
|
124
|
+
/**
|
|
125
|
+
* Flat list of every reflected entity (classes + methods + functions),
|
|
126
|
+
* user + framework. Vendor entries are included here for completeness.
|
|
127
|
+
*/
|
|
128
|
+
index(): IndexEntry[];
|
|
129
|
+
static mcpSearch(query: string, k?: number, projectRoot?: string, source?: string, includePrivate?: boolean): DocsHit[];
|
|
130
|
+
static mcpMethod(classFqn: string, name: string, projectRoot?: string): MethodSpec | null;
|
|
131
|
+
static mcpClass(fqn: string, projectRoot?: string): ClassSpec | null;
|
|
132
|
+
static checkDocs(mdPath: string, projectRoot?: string): {
|
|
133
|
+
drift: DriftHit[];
|
|
134
|
+
};
|
|
135
|
+
static syncDocs(mdPath: string, projectRoot?: string): void;
|
|
136
|
+
private static cached;
|
|
137
|
+
private ensureIndex;
|
|
138
|
+
private maxMtime;
|
|
139
|
+
private scoreEntry;
|
|
140
|
+
private renderGeneratedBlock;
|
|
141
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load environment variables from a .env file into process.env.
|
|
3
|
+
*
|
|
4
|
+
* By default does NOT override existing process.env values — it is first-wins:
|
|
5
|
+
* a key is only set if it is not already present. This is how real env vars
|
|
6
|
+
* always win. To get the precedence real-env > `.env.local` > `.env`, load
|
|
7
|
+
* `.env.local` FIRST then `.env`, both with override=false (the default): the
|
|
8
|
+
* real env (already present) wins over both, `.env.local` fills local-only keys,
|
|
9
|
+
* and `.env` fills the rest. Do NOT load `.env.local` with override=true — that
|
|
10
|
+
* would let a stray gitignored `.env.local` clobber an explicitly set real env
|
|
11
|
+
* var (e.g. a production TINA4_SECRET).
|
|
12
|
+
*
|
|
13
|
+
* Resolution order for the env file path:
|
|
14
|
+
* 1. Explicit `path` argument
|
|
15
|
+
* 2. `TINA4_ENV_FILE` env var (if set and non-empty)
|
|
16
|
+
* 3. `.env` in the current working directory
|
|
17
|
+
*
|
|
18
|
+
* @param path - Path to the .env file. Optional override.
|
|
19
|
+
* @param override - When true, overwrite keys already present in process.env.
|
|
20
|
+
* @returns The parsed key-value pairs, or an empty object if the file doesn't exist.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadEnv(path?: string, override?: boolean): Record<string, string>;
|
|
23
|
+
/**
|
|
24
|
+
* Get an environment variable value with an optional default.
|
|
25
|
+
*
|
|
26
|
+
* @param key - The environment variable name.
|
|
27
|
+
* @param defaultValue - Value to return if the variable is not set.
|
|
28
|
+
* @returns The environment variable value, or the default.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getEnv(key: string, defaultValue?: string): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get a required environment variable. Throws if not set.
|
|
33
|
+
*
|
|
34
|
+
* @param key - The environment variable name.
|
|
35
|
+
* @returns The environment variable value.
|
|
36
|
+
* @throws Error if the variable is not set.
|
|
37
|
+
*/
|
|
38
|
+
export declare function requireEnv(key: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Check if an environment variable exists (is defined in process.env).
|
|
41
|
+
*
|
|
42
|
+
* @param key - The environment variable name.
|
|
43
|
+
* @returns true if the variable is set, false otherwise.
|
|
44
|
+
*/
|
|
45
|
+
export declare function hasEnv(key: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Return all currently loaded environment variables.
|
|
48
|
+
*
|
|
49
|
+
* @returns A shallow copy of process.env as a record.
|
|
50
|
+
*/
|
|
51
|
+
export declare function allEnv(): Record<string, string | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a value is truthy for env boolean checks.
|
|
54
|
+
*
|
|
55
|
+
* Accepts: "true", "True", "TRUE", "1", "yes", "Yes", "YES", "on", "On", "ON".
|
|
56
|
+
* Everything else is falsy (including empty string, undefined, not set).
|
|
57
|
+
*
|
|
58
|
+
* Mirrors Python's `is_truthy()` in `tina4_python.dotenv`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function isTruthy(val: string | undefined | null): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Remove all environment variables that were loaded by loadEnv().
|
|
63
|
+
* Useful for testing. Only removes keys set by loadEnv(), not pre-existing system env vars.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resetEnv(): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed environment-variable helpers.
|
|
3
|
+
*
|
|
4
|
+
* All methods are static so callers can write `Env.bool(...)` without
|
|
5
|
+
* instantiating anything — matching the Python/PHP/Ruby ports.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Env {
|
|
8
|
+
/**
|
|
9
|
+
* Read `name` and coerce to bool.
|
|
10
|
+
*
|
|
11
|
+
* Truthy values (case-insensitive after trim): `1`, `true`, `on`, `yes`,
|
|
12
|
+
* `y`, `t`. Falsy: `0`, `false`, `off`, `no`, `n`, `f`, empty string.
|
|
13
|
+
* Anything else returns the `defaultValue` — never throws.
|
|
14
|
+
*/
|
|
15
|
+
static bool(name: string, defaultValue?: boolean): boolean;
|
|
16
|
+
/** Read `name` and coerce to int. Returns `defaultValue` on parse failure. */
|
|
17
|
+
static int(name: string, defaultValue?: number): number;
|
|
18
|
+
/** Read `name` and coerce to float. Returns `defaultValue` on parse failure. */
|
|
19
|
+
static float(name: string, defaultValue?: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Read `name` as a string. Returns `defaultValue` if unset.
|
|
22
|
+
*
|
|
23
|
+
* Whitespace is preserved — this is a pass-through for the raw env value.
|
|
24
|
+
* `Env.str("PATH")` is exactly `process.env.PATH ?? ""` with a more
|
|
25
|
+
* discoverable name.
|
|
26
|
+
*/
|
|
27
|
+
static str(name: string, defaultValue?: string): string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tina4 Debug — Rich error overlay for development mode.
|
|
3
|
+
*
|
|
4
|
+
* Renders a professional, syntax-highlighted HTML error page when an unhandled
|
|
5
|
+
* exception occurs in a route handler.
|
|
6
|
+
*
|
|
7
|
+
* import { renderErrorOverlay, renderProductionError, isDebugMode } from "./errorOverlay.js";
|
|
8
|
+
*
|
|
9
|
+
* try {
|
|
10
|
+
* await handler(req, res);
|
|
11
|
+
* } catch (err) {
|
|
12
|
+
* const html = isDebugMode()
|
|
13
|
+
* ? renderErrorOverlay(err as Error, req)
|
|
14
|
+
* : renderProductionError();
|
|
15
|
+
* res.html(html, 500);
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* Only activate when TINA4_DEBUG is true.
|
|
19
|
+
* In production, call renderProductionError() instead.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Render a rich HTML error overlay.
|
|
23
|
+
*
|
|
24
|
+
* @param error - The caught error.
|
|
25
|
+
* @param request - Optional request object with method, url, headers, etc.
|
|
26
|
+
* @returns Complete HTML page string.
|
|
27
|
+
*/
|
|
28
|
+
export declare function renderErrorOverlay(error: Error, request?: any): string;
|
|
29
|
+
/**
|
|
30
|
+
* Render a safe, generic error page for production.
|
|
31
|
+
*/
|
|
32
|
+
export declare function renderProductionError(statusCode?: number, message?: string, path?: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Check if TINA4_DEBUG is enabled.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isDebugMode(): boolean;
|