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.
Files changed (134) hide show
  1. package/CLAUDE.md +16 -3
  2. package/README.md +1 -1
  3. package/package.json +12 -9
  4. package/packages/cli/dist/bin.js +1260 -969
  5. package/packages/core/dist/index.js +1260 -969
  6. package/packages/core/src/devMailbox.ts +20 -44
  7. package/packages/core/src/index.ts +2 -2
  8. package/packages/core/src/messenger.ts +72 -0
  9. package/packages/core/src/queueBackends/kafkaBackend.ts +108 -12
  10. package/packages/core/src/sessionHandlers/childError.ts +72 -0
  11. package/packages/core/src/sessionHandlers/mongoClient.ts +9 -3
  12. package/packages/core/src/sessionHandlers/redisHandler.ts +18 -5
  13. package/packages/core/src/sessionHandlers/respClient.ts +5 -1
  14. package/packages/frond/dist/index.js +74 -31
  15. package/packages/frond/src/engine.ts +99 -33
  16. package/packages/orm/dist/index.js +3055 -2764
  17. package/packages/orm/src/adapters/sqlite.ts +4 -1
  18. package/packages/orm/src/database.ts +108 -8
  19. package/types/cli/src/bin.d.ts +92 -0
  20. package/types/cli/src/commands/build.d.ts +2 -0
  21. package/types/cli/src/commands/generate.d.ts +47 -0
  22. package/types/cli/src/commands/init.d.ts +1 -0
  23. package/types/cli/src/commands/metrics.d.ts +6 -0
  24. package/types/cli/src/commands/migrate.d.ts +1 -0
  25. package/types/cli/src/commands/migrateCreate.d.ts +1 -0
  26. package/types/cli/src/commands/migrateRollback.d.ts +1 -0
  27. package/types/cli/src/commands/migrateStatus.d.ts +1 -0
  28. package/types/cli/src/commands/queue.d.ts +20 -0
  29. package/types/cli/src/commands/routes.d.ts +1 -0
  30. package/types/cli/src/commands/seed.d.ts +1 -0
  31. package/types/cli/src/commands/serve.d.ts +6 -0
  32. package/types/cli/src/commands/test.d.ts +1 -0
  33. package/types/core/src/ai.d.ts +64 -0
  34. package/types/core/src/api.d.ts +262 -0
  35. package/types/core/src/auth.d.ts +154 -0
  36. package/types/core/src/authGate.d.ts +20 -0
  37. package/types/core/src/background.d.ts +34 -0
  38. package/types/core/src/cache.d.ts +160 -0
  39. package/types/core/src/constants.d.ts +38 -0
  40. package/types/core/src/container.d.ts +44 -0
  41. package/types/core/src/context/chunker.d.ts +31 -0
  42. package/types/core/src/context/index.d.ts +93 -0
  43. package/types/core/src/devAdmin.d.ts +179 -0
  44. package/types/core/src/devMailbox.d.ts +54 -0
  45. package/types/core/src/docs.d.ts +141 -0
  46. package/types/core/src/docsAutoDiscovery.d.ts +6 -0
  47. package/types/core/src/dotenv.d.ts +65 -0
  48. package/types/core/src/env.d.ts +28 -0
  49. package/types/core/src/errorOverlay.d.ts +36 -0
  50. package/types/core/src/events.d.ts +75 -0
  51. package/types/core/src/fakeData.d.ts +55 -0
  52. package/types/core/src/feedback.d.ts +90 -0
  53. package/types/core/src/graphql.d.ts +207 -0
  54. package/types/core/src/health.d.ts +22 -0
  55. package/types/core/src/htmlElement.d.ts +75 -0
  56. package/types/core/src/i18n.d.ts +37 -0
  57. package/types/core/src/index.d.ts +93 -0
  58. package/types/core/src/job.d.ts +39 -0
  59. package/types/core/src/logger.d.ts +123 -0
  60. package/types/core/src/mcp.d.ts +248 -0
  61. package/types/core/src/messenger.d.ts +191 -0
  62. package/types/core/src/metrics.d.ts +77 -0
  63. package/types/core/src/middleware.d.ts +207 -0
  64. package/types/core/src/mqtt.d.ts +257 -0
  65. package/types/core/src/mqttMessage.d.ts +67 -0
  66. package/types/core/src/plan.d.ts +96 -0
  67. package/types/core/src/projectIndex.d.ts +56 -0
  68. package/types/core/src/queue.d.ts +219 -0
  69. package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
  70. package/types/core/src/queueBackends/liteBackend.d.ts +119 -0
  71. package/types/core/src/queueBackends/mongoBackend.d.ts +97 -0
  72. package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
  73. package/types/core/src/rateLimiter.d.ts +49 -0
  74. package/types/core/src/request.d.ts +25 -0
  75. package/types/core/src/response.d.ts +28 -0
  76. package/types/core/src/routeDiscovery.d.ts +12 -0
  77. package/types/core/src/router.d.ts +355 -0
  78. package/types/core/src/scss.d.ts +19 -0
  79. package/types/core/src/server.d.ts +131 -0
  80. package/types/core/src/service.d.ts +115 -0
  81. package/types/core/src/session.d.ts +256 -0
  82. package/types/core/src/sessionHandlers/childError.d.ts +34 -0
  83. package/types/core/src/sessionHandlers/databaseHandler.d.ts +42 -0
  84. package/types/core/src/sessionHandlers/mongoClient.d.ts +24 -0
  85. package/types/core/src/sessionHandlers/mongoHandler.d.ts +61 -0
  86. package/types/core/src/sessionHandlers/redisHandler.d.ts +60 -0
  87. package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
  88. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
  89. package/types/core/src/static.d.ts +2 -0
  90. package/types/core/src/test.d.ts +94 -0
  91. package/types/core/src/testClient.d.ts +36 -0
  92. package/types/core/src/testing.d.ts +58 -0
  93. package/types/core/src/types.d.ts +219 -0
  94. package/types/core/src/validator.d.ts +52 -0
  95. package/types/core/src/websocket.d.ts +376 -0
  96. package/types/core/src/websocketBackplane.d.ts +166 -0
  97. package/types/core/src/websocketConnection.d.ts +54 -0
  98. package/types/core/src/wsdl.d.ts +101 -0
  99. package/types/frond/src/engine.d.ts +263 -0
  100. package/types/frond/src/index.d.ts +2 -0
  101. package/types/orm/src/adapters/firebird.d.ts +138 -0
  102. package/types/orm/src/adapters/mongodb.d.ts +81 -0
  103. package/types/orm/src/adapters/mssql.d.ts +70 -0
  104. package/types/orm/src/adapters/mysql.d.ts +66 -0
  105. package/types/orm/src/adapters/odbc.d.ts +97 -0
  106. package/types/orm/src/adapters/postgres.d.ts +85 -0
  107. package/types/orm/src/adapters/sqlite.d.ts +56 -0
  108. package/types/orm/src/autoCrud.d.ts +73 -0
  109. package/types/orm/src/baseModel.d.ts +391 -0
  110. package/types/orm/src/cachedDatabase.d.ts +177 -0
  111. package/types/orm/src/database.d.ts +609 -0
  112. package/types/orm/src/databaseResult.d.ts +85 -0
  113. package/types/orm/src/docstore.d.ts +182 -0
  114. package/types/orm/src/fakeData.d.ts +22 -0
  115. package/types/orm/src/index.d.ts +40 -0
  116. package/types/orm/src/migration.d.ts +275 -0
  117. package/types/orm/src/model.d.ts +7 -0
  118. package/types/orm/src/query.d.ts +14 -0
  119. package/types/orm/src/queryBuilder.d.ts +173 -0
  120. package/types/orm/src/realtime/index.d.ts +7 -0
  121. package/types/orm/src/realtime/models/attachment.d.ts +43 -0
  122. package/types/orm/src/realtime/models/channel.d.ts +32 -0
  123. package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
  124. package/types/orm/src/realtime/models/message.d.ts +36 -0
  125. package/types/orm/src/realtime/models/workspace.d.ts +26 -0
  126. package/types/orm/src/realtime/realtime.d.ts +24 -0
  127. package/types/orm/src/realtime/storage.d.ts +61 -0
  128. package/types/orm/src/seeder.d.ts +118 -0
  129. package/types/orm/src/sqlTranslator.d.ts +134 -0
  130. package/types/orm/src/types.d.ts +138 -0
  131. package/types/orm/src/validation.d.ts +6 -0
  132. package/types/swagger/src/generator.d.ts +46 -0
  133. package/types/swagger/src/index.d.ts +2 -0
  134. 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,6 @@
1
+ /**
2
+ * Write `.tina4/mcp.json` and (if `.git/` exists) append `.tina4/` to .gitignore.
3
+ *
4
+ * Returns true if the discovery file was written or updated.
5
+ */
6
+ export declare function writeMcpDiscovery(projectRoot: string, port: number): boolean;
@@ -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;