tina4-nodejs 3.13.92 → 3.13.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CLAUDE.md +170 -28
  2. package/README.md +2 -2
  3. package/package.json +13 -9
  4. package/packages/cli/dist/bin.js +33126 -30055
  5. package/packages/cli/src/commands/metrics.ts +17 -11
  6. package/packages/cli/src/commands/serve.ts +10 -9
  7. package/packages/core/dist/index.js +33062 -29908
  8. package/packages/core/src/ai.ts +7 -1
  9. package/packages/core/src/auth.ts +191 -39
  10. package/packages/core/src/background.ts +19 -19
  11. package/packages/core/src/cache.ts +492 -49
  12. package/packages/core/src/devAdmin.ts +79 -32
  13. package/packages/core/src/devMailbox.ts +20 -44
  14. package/packages/core/src/dispatchPipeline.ts +285 -0
  15. package/packages/core/src/dotenv.ts +185 -40
  16. package/packages/core/src/index.ts +7 -6
  17. package/packages/core/src/logger.ts +257 -36
  18. package/packages/core/src/mcp.ts +1 -1
  19. package/packages/core/src/messenger.ts +81 -13
  20. package/packages/core/src/metrics.ts +199 -961
  21. package/packages/core/src/middleware.ts +390 -123
  22. package/packages/core/src/queue.ts +188 -32
  23. package/packages/core/src/queueBackends/kafkaBackend.ts +109 -13
  24. package/packages/core/src/queueBackends/liteBackend.ts +13 -0
  25. package/packages/core/src/queueBackends/mongoBackend.ts +101 -9
  26. package/packages/core/src/queueBackends/rabbitmqBackend.ts +22 -4
  27. package/packages/core/src/rateLimiter.ts +10 -5
  28. package/packages/core/src/request.ts +6 -9
  29. package/packages/core/src/response.ts +46 -1
  30. package/packages/core/src/router.ts +29 -4
  31. package/packages/core/src/server.ts +751 -414
  32. package/packages/core/src/session.ts +244 -27
  33. package/packages/core/src/sessionHandlers/childError.ts +72 -0
  34. package/packages/core/src/sessionHandlers/databaseHandler.ts +338 -48
  35. package/packages/core/src/sessionHandlers/memcachedHandler.ts +181 -0
  36. package/packages/core/src/sessionHandlers/mongoClient.ts +293 -202
  37. package/packages/core/src/sessionHandlers/mongoHandler.ts +88 -8
  38. package/packages/core/src/sessionHandlers/respClient.ts +16 -143
  39. package/packages/core/src/sessionHandlers/sqlClient.ts +290 -0
  40. package/packages/core/src/sessionHandlers/syncBridge.ts +190 -0
  41. package/packages/core/src/sessionHandlers/syncSocket.ts +236 -0
  42. package/packages/core/src/testClient.ts +18 -5
  43. package/packages/core/src/trustedProxy.ts +249 -0
  44. package/packages/core/src/types.ts +29 -5
  45. package/packages/core/src/websocket.ts +66 -0
  46. package/packages/frond/dist/index.js +74 -31
  47. package/packages/frond/src/engine.ts +99 -33
  48. package/packages/orm/dist/index.js +26554 -23400
  49. package/packages/orm/src/adapters/firebird.ts +183 -56
  50. package/packages/orm/src/adapters/mongodb.ts +25 -4
  51. package/packages/orm/src/adapters/mssql.ts +114 -29
  52. package/packages/orm/src/adapters/mysql.ts +103 -40
  53. package/packages/orm/src/adapters/odbc.ts +44 -21
  54. package/packages/orm/src/adapters/postgres.ts +118 -26
  55. package/packages/orm/src/adapters/sqlDialect.ts +120 -0
  56. package/packages/orm/src/adapters/sqlite.ts +64 -25
  57. package/packages/orm/src/baseModel.ts +135 -40
  58. package/packages/orm/src/cachedDatabase.ts +43 -19
  59. package/packages/orm/src/connectTimeout.ts +265 -0
  60. package/packages/orm/src/database.ts +338 -198
  61. package/packages/orm/src/databaseResult.ts +65 -13
  62. package/packages/orm/src/databaseUrl.ts +484 -0
  63. package/packages/orm/src/docstore.ts +386 -145
  64. package/packages/orm/src/index.ts +13 -3
  65. package/packages/orm/src/migration.ts +18 -3
  66. package/packages/orm/src/queryBuilder.ts +38 -4
  67. package/packages/orm/src/sqlTranslator.ts +310 -4
  68. package/packages/orm/src/types.ts +15 -4
  69. package/types/cli/src/bin.d.ts +92 -0
  70. package/types/cli/src/commands/build.d.ts +2 -0
  71. package/types/cli/src/commands/generate.d.ts +47 -0
  72. package/types/cli/src/commands/init.d.ts +1 -0
  73. package/types/cli/src/commands/metrics.d.ts +6 -0
  74. package/types/cli/src/commands/migrate.d.ts +1 -0
  75. package/types/cli/src/commands/migrateCreate.d.ts +1 -0
  76. package/types/cli/src/commands/migrateRollback.d.ts +1 -0
  77. package/types/cli/src/commands/migrateStatus.d.ts +1 -0
  78. package/types/cli/src/commands/queue.d.ts +20 -0
  79. package/types/cli/src/commands/routes.d.ts +1 -0
  80. package/types/cli/src/commands/seed.d.ts +1 -0
  81. package/types/cli/src/commands/serve.d.ts +6 -0
  82. package/types/cli/src/commands/test.d.ts +1 -0
  83. package/types/core/src/ai.d.ts +64 -0
  84. package/types/core/src/api.d.ts +262 -0
  85. package/types/core/src/auth.d.ts +177 -0
  86. package/types/core/src/authGate.d.ts +20 -0
  87. package/types/core/src/background.d.ts +34 -0
  88. package/types/core/src/cache.d.ts +163 -0
  89. package/types/core/src/constants.d.ts +38 -0
  90. package/types/core/src/container.d.ts +44 -0
  91. package/types/core/src/context/chunker.d.ts +31 -0
  92. package/types/core/src/context/index.d.ts +93 -0
  93. package/types/core/src/devAdmin.d.ts +179 -0
  94. package/types/core/src/devMailbox.d.ts +54 -0
  95. package/types/core/src/dispatchPipeline.d.ts +117 -0
  96. package/types/core/src/docs.d.ts +141 -0
  97. package/types/core/src/docsAutoDiscovery.d.ts +6 -0
  98. package/types/core/src/dotenv.d.ts +87 -0
  99. package/types/core/src/env.d.ts +28 -0
  100. package/types/core/src/errorOverlay.d.ts +36 -0
  101. package/types/core/src/events.d.ts +75 -0
  102. package/types/core/src/fakeData.d.ts +55 -0
  103. package/types/core/src/feedback.d.ts +90 -0
  104. package/types/core/src/graphql.d.ts +207 -0
  105. package/types/core/src/health.d.ts +22 -0
  106. package/types/core/src/htmlElement.d.ts +75 -0
  107. package/types/core/src/i18n.d.ts +37 -0
  108. package/types/core/src/index.d.ts +92 -0
  109. package/types/core/src/job.d.ts +39 -0
  110. package/types/core/src/logger.d.ts +200 -0
  111. package/types/core/src/mcp.d.ts +248 -0
  112. package/types/core/src/messenger.d.ts +191 -0
  113. package/types/core/src/metrics.d.ts +41 -0
  114. package/types/core/src/middleware.d.ts +330 -0
  115. package/types/core/src/mqtt.d.ts +257 -0
  116. package/types/core/src/mqttMessage.d.ts +67 -0
  117. package/types/core/src/plan.d.ts +96 -0
  118. package/types/core/src/projectIndex.d.ts +56 -0
  119. package/types/core/src/queue.d.ts +268 -0
  120. package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
  121. package/types/core/src/queueBackends/liteBackend.d.ts +128 -0
  122. package/types/core/src/queueBackends/mongoBackend.d.ts +119 -0
  123. package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
  124. package/types/core/src/rateLimiter.d.ts +49 -0
  125. package/types/core/src/request.d.ts +25 -0
  126. package/types/core/src/response.d.ts +28 -0
  127. package/types/core/src/routeDiscovery.d.ts +12 -0
  128. package/types/core/src/router.d.ts +366 -0
  129. package/types/core/src/scss.d.ts +19 -0
  130. package/types/core/src/server.d.ts +146 -0
  131. package/types/core/src/service.d.ts +115 -0
  132. package/types/core/src/session.d.ts +341 -0
  133. package/types/core/src/sessionHandlers/childError.d.ts +34 -0
  134. package/types/core/src/sessionHandlers/databaseHandler.d.ts +97 -0
  135. package/types/core/src/sessionHandlers/memcachedHandler.d.ts +60 -0
  136. package/types/core/src/sessionHandlers/mongoClient.d.ts +35 -0
  137. package/types/core/src/sessionHandlers/mongoHandler.d.ts +109 -0
  138. package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
  139. package/types/core/src/sessionHandlers/sqlClient.d.ts +39 -0
  140. package/types/core/src/sessionHandlers/syncBridge.d.ts +91 -0
  141. package/types/core/src/sessionHandlers/syncSocket.d.ts +49 -0
  142. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
  143. package/types/core/src/static.d.ts +2 -0
  144. package/types/core/src/test.d.ts +94 -0
  145. package/types/core/src/testClient.d.ts +36 -0
  146. package/types/core/src/testing.d.ts +58 -0
  147. package/types/core/src/trustedProxy.d.ts +44 -0
  148. package/types/core/src/types.d.ts +242 -0
  149. package/types/core/src/validator.d.ts +52 -0
  150. package/types/core/src/websocket.d.ts +402 -0
  151. package/types/core/src/websocketBackplane.d.ts +166 -0
  152. package/types/core/src/websocketConnection.d.ts +54 -0
  153. package/types/core/src/wsdl.d.ts +101 -0
  154. package/types/frond/src/engine.d.ts +263 -0
  155. package/types/frond/src/index.d.ts +2 -0
  156. package/types/orm/src/adapters/firebird.d.ts +183 -0
  157. package/types/orm/src/adapters/mongodb.d.ts +81 -0
  158. package/types/orm/src/adapters/mssql.d.ts +77 -0
  159. package/types/orm/src/adapters/mysql.d.ts +67 -0
  160. package/types/orm/src/adapters/odbc.d.ts +94 -0
  161. package/types/orm/src/adapters/postgres.d.ts +86 -0
  162. package/types/orm/src/adapters/sqlDialect.d.ts +71 -0
  163. package/types/orm/src/adapters/sqlite.d.ts +68 -0
  164. package/types/orm/src/autoCrud.d.ts +73 -0
  165. package/types/orm/src/baseModel.d.ts +427 -0
  166. package/types/orm/src/cachedDatabase.d.ts +190 -0
  167. package/types/orm/src/connectTimeout.d.ts +100 -0
  168. package/types/orm/src/database.d.ts +655 -0
  169. package/types/orm/src/databaseResult.d.ts +109 -0
  170. package/types/orm/src/databaseUrl.d.ts +125 -0
  171. package/types/orm/src/docstore.d.ts +241 -0
  172. package/types/orm/src/fakeData.d.ts +22 -0
  173. package/types/orm/src/index.d.ts +43 -0
  174. package/types/orm/src/migration.d.ts +275 -0
  175. package/types/orm/src/model.d.ts +7 -0
  176. package/types/orm/src/query.d.ts +14 -0
  177. package/types/orm/src/queryBuilder.d.ts +193 -0
  178. package/types/orm/src/realtime/index.d.ts +7 -0
  179. package/types/orm/src/realtime/models/attachment.d.ts +43 -0
  180. package/types/orm/src/realtime/models/channel.d.ts +32 -0
  181. package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
  182. package/types/orm/src/realtime/models/message.d.ts +36 -0
  183. package/types/orm/src/realtime/models/workspace.d.ts +26 -0
  184. package/types/orm/src/realtime/realtime.d.ts +24 -0
  185. package/types/orm/src/realtime/storage.d.ts +61 -0
  186. package/types/orm/src/seeder.d.ts +118 -0
  187. package/types/orm/src/sqlTranslator.d.ts +258 -0
  188. package/types/orm/src/types.d.ts +148 -0
  189. package/types/orm/src/validation.d.ts +6 -0
  190. package/types/swagger/src/generator.d.ts +46 -0
  191. package/types/swagger/src/index.d.ts +2 -0
  192. package/types/swagger/src/ui.d.ts +11 -0
  193. package/packages/core/src/sessionHandlers/redisHandler.ts +0 -206
@@ -0,0 +1 @@
1
+ export declare function createMigration(description?: string): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function migrateRollback(migrationDir?: string): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function migrateStatus(migrationDir?: string): Promise<void>;
@@ -0,0 +1,20 @@
1
+ /** A per-job handler declared by a consumer module (receives the job payload). */
2
+ export type QueueHandler = (payload: unknown) => unknown | Promise<unknown>;
3
+ /**
4
+ * Return the per-job handler that a consumer module declares for `topic`.
5
+ *
6
+ * A consumer module (e.g. the one `generate queue <topic>` scaffolds) exposes a
7
+ * default-export config; when its `topic` matches, `queue work` drives the
8
+ * consumer through that config's per-job `handle` callable — so the worker owns
9
+ * the poll loop (honouring --poll and the bounded --once drain) instead of the
10
+ * consumer's own endless loop. Returns the callable, or null when no consumer in
11
+ * `servicesDir` targets this topic. Mirrors Python's _resolve_queue_handler.
12
+ */
13
+ export declare function resolveQueueHandler(servicesDir: string, topic: string): Promise<QueueHandler | null>;
14
+ /** Subcommand names, in order — surfaced in `commands --json` for the tina4 client. */
15
+ export declare const QUEUE_SUBCOMMAND_NAMES: string[];
16
+ /**
17
+ * Top-level queue command: run workers and manage jobs. Dispatches to the
18
+ * subcommand handlers above; unknown / missing subcommands fail loud (exit 1).
19
+ */
20
+ export declare function queueCommand(args?: string[]): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function listRoutes(): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function runSeeds(seedPath?: string): Promise<void>;
@@ -0,0 +1,6 @@
1
+ export interface ServeOptions {
2
+ port?: number;
3
+ noBrowser?: boolean;
4
+ noReload?: boolean;
5
+ }
6
+ export declare function serveProject(options: ServeOptions): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare function runTests(testPath?: string): Promise<void>;
@@ -0,0 +1,64 @@
1
+ export interface AiTool {
2
+ name: string;
3
+ description: string;
4
+ contextFile: string;
5
+ configDir: string | null;
6
+ }
7
+ export declare const AI_TOOLS: AiTool[];
8
+ export declare const DEV_SKILL = "tina4-developer-nodejs";
9
+ /**
10
+ * Install the Tina4 SKILL.md skills into the project AND the global
11
+ * ~/.claude/skills, fetched from the release ref matching this framework
12
+ * version. Returns the skills that were fully installed. Network-dependent —
13
+ * on a fetch failure the skill is skipped, never fatal.
14
+ */
15
+ export declare function installSkills(root?: string, targets?: string[]): string[];
16
+ /**
17
+ * Check if a tool's context file already exists.
18
+ */
19
+ export declare function isInstalled(root: string, tool: AiTool): boolean;
20
+ /**
21
+ * Print the numbered menu and read user input via readline.
22
+ * Returns a promise that resolves to the user's selection string.
23
+ */
24
+ export declare function showMenu(root?: string): Promise<string>;
25
+ /**
26
+ * Install context files for the selected tools.
27
+ *
28
+ * selection: comma-separated numbers like "1,2,3" or "all"
29
+ * Returns list of created/updated file paths.
30
+ */
31
+ export declare function installSelected(root: string, selection: string): string[];
32
+ /**
33
+ * Install context for all AI tools (non-interactive).
34
+ */
35
+ export declare function installAll(root?: string): string[];
36
+ /** Return [start, end] markers for a context file. */
37
+ export declare function markersFor(contextFile: string): [string, string];
38
+ /** Return the marker-bracketed Tina4 skill registration block. */
39
+ export declare function skillBlock(contextFile: string): string;
40
+ /** True iff both start and end markers appear in order. */
41
+ export declare function hasMarkers(existing: string, start: string, end: string): boolean;
42
+ /** Replace the bracketed block in `existing` with `block`. */
43
+ export declare function replaceMarkerBlock(existing: string, block: string, start: string, end: string): string;
44
+ /**
45
+ * True if the file starts with a header the pre-v3.13.9 installer
46
+ * wrote. Used to migrate one-time off the old clobber-style install.
47
+ */
48
+ export declare function looksLikeOldFrameworkInstall(existing: string): boolean;
49
+ /**
50
+ * Write the context file non-destructively. Returns a human-readable
51
+ * action verb for the caller's log line.
52
+ *
53
+ * Four branches:
54
+ * 1. Doesn't exist \u2192 write framework guide + skill block
55
+ * 2. Has markers \u2192 refresh just the skill block (idempotent)
56
+ * 3. Old header \u2192 migrate: replace old dump with new guide + block
57
+ * 4. User content \u2192 append the skill block, preserve everything else
58
+ */
59
+ export declare function writeOrMerge(contextPath: string, contextFile: string, frameworkGuide: string): string;
60
+ /**
61
+ * Generate the Tina4 context document for a specific AI tool.
62
+ */
63
+ export declare function generateContext(toolName?: string): string;
64
+ export type { AiTool as AiToolType };
@@ -0,0 +1,262 @@
1
+ export interface ApiResult {
2
+ http_code: number | null;
3
+ body: unknown;
4
+ headers: Record<string, string>;
5
+ error: string | null;
6
+ }
7
+ /**
8
+ * Result of {@link Api.download}. There is no `body` field — the response
9
+ * body went to disk. `path` is the destination on success and `null` on any
10
+ * error (missing dest, HTTP error status, transport failure); the file is not
11
+ * written on error. Keeps `http_code` (snake_case) for parity with
12
+ * {@link ApiResult} and the Python/PHP/Ruby `download` return.
13
+ */
14
+ export interface DownloadResult {
15
+ http_code: number | null;
16
+ headers: Record<string, string>;
17
+ error: string | null;
18
+ path: string | null;
19
+ }
20
+ /**
21
+ * An injectable transport seam (constructor option `transport`). When supplied
22
+ * it fully REPLACES the node:http/https network call. Called as
23
+ * `(method, url, headers, body, timeout)` and must return the same result
24
+ * shape every verb returns (`{ http_code, body, headers, error }`); may be sync
25
+ * or async.
26
+ *
27
+ * NOTE: Tina4's own test suite must NEVER inject a fake/canned transport — the
28
+ * no-mock rule stands, so framework tests always exercise the real network path
29
+ * against a real local server. This seam exists purely so *application*
30
+ * developers can unit-test code that calls an `Api` instance without a live
31
+ * server.
32
+ */
33
+ export type ApiTransport = (method: string, url: string, headers: Record<string, string>, body: Buffer | null, timeout: number) => ApiResult | Promise<ApiResult>;
34
+ /**
35
+ * Options for {@link Api.upload}. Supply the file EITHER as `filePath` (a file
36
+ * on disk) OR as `fileBytes` + `filename` (an in-memory payload) — a caller
37
+ * never needs a temp file.
38
+ */
39
+ export interface UploadOptions {
40
+ /** A file on disk. `filename` defaults to its basename. */
41
+ filePath?: string;
42
+ /** The form field the file is sent under (default `"file"`). */
43
+ fieldName?: string;
44
+ /** Additional text parts of the multipart body. */
45
+ extraFields?: Record<string, string>;
46
+ /** Extra per-call headers merged onto the request. */
47
+ headers?: Record<string, string>;
48
+ /** An in-memory payload (Buffer or string). Requires `filename` for a name. */
49
+ fileBytes?: Buffer | string;
50
+ /** Filename used in the Content-Disposition part header. */
51
+ filename?: string;
52
+ }
53
+ /**
54
+ * Constructor options for {@link Api}. Used as the second argument to
55
+ * `new Api(url, { ... })` — cross-framework parity with Python
56
+ * `Api(bearer_token=, ...)` kwargs added in 3.13.x.
57
+ */
58
+ export interface ApiOptions {
59
+ authHeader?: string;
60
+ timeout?: number;
61
+ ignoreSsl?: boolean;
62
+ /** Positive form of ignoreSsl — `verifySsl: false` disables verification. */
63
+ verifySsl?: boolean;
64
+ bearerToken?: string;
65
+ username?: string;
66
+ password?: string;
67
+ headers?: Record<string, string>;
68
+ /**
69
+ * Maximum automatic retries on a transient failure (default 0 = off, so
70
+ * existing callers are unaffected). When > 0, a transport error or a
71
+ * retryable status (429/5xx) is retried up to this many times with
72
+ * exponential backoff. NOTE: a retried non-idempotent request (POST/…)
73
+ * may be re-sent — retries are opt-in for that reason.
74
+ */
75
+ maxRetries?: number;
76
+ /** Base backoff in seconds, doubling each attempt (default 0.5). */
77
+ retryBackoff?: number;
78
+ /**
79
+ * Injectable transport seam (default undefined = the real network path).
80
+ * When supplied it REPLACES the node:http/https call. See {@link ApiTransport}.
81
+ * Tina4's own suite never injects it (no-mock rule) — it exists so
82
+ * application developers can unit-test their own code.
83
+ */
84
+ transport?: ApiTransport;
85
+ /**
86
+ * Opt-in per-client, in-memory cookie jar (default false = off, zero
87
+ * behaviour change). When true, `Set-Cookie` response headers are parsed and
88
+ * the accumulated `Cookie` header is sent on subsequent requests. Not
89
+ * persisted; scoped to this instance.
90
+ */
91
+ cookies?: boolean;
92
+ }
93
+ export declare class Api {
94
+ private baseUrl;
95
+ private headers;
96
+ private timeout;
97
+ private authHeader;
98
+ private ignoreSsl;
99
+ private maxRetries;
100
+ private retryBackoff;
101
+ private transportFn?;
102
+ private cookiesEnabled;
103
+ private cookies;
104
+ /**
105
+ * Construct an Api client.
106
+ *
107
+ * Two construction styles supported:
108
+ *
109
+ * // Legacy positional form
110
+ * new Api("https://api.example.com", "Bearer token", 30);
111
+ *
112
+ * // 3.13.1: ergonomic options bag (recommended) — cross-framework
113
+ * // parity with Python tina4_python.api.Api kwargs.
114
+ * new Api("https://api.example.com", { bearerToken: "sk-abc" });
115
+ * new Api("https://api.example.com", { username: "u", password: "p" });
116
+ * new Api("https://api.example.com", { headers: { "X-Tenant": "acme" } });
117
+ * new Api("https://self-signed.local", { verifySsl: false });
118
+ *
119
+ * Bearer wins over basic-auth when both passed. `verifySsl: false` is
120
+ * the positive form of `ignoreSsl: true`; `ignoreSsl` wins when both
121
+ * supplied for backward compatibility.
122
+ *
123
+ * `maxRetries` (default 0 = off) enables automatic retry with
124
+ * exponential backoff (`retryBackoff` seconds base, doubling each
125
+ * attempt) on a transport error or a retryable status (429/5xx). A
126
+ * retried non-idempotent request (POST/…) may be re-sent — retries are
127
+ * opt-in for that reason.
128
+ *
129
+ * new Api("https://api.example.com", { maxRetries: 3, retryBackoff: 0.5 });
130
+ *
131
+ * `transport` (default undefined = the real network path) is an injectable
132
+ * seam so USERS can unit-test their own code; `cookies` (default false)
133
+ * turns on a per-client, in-memory cookie jar.
134
+ */
135
+ constructor(baseUrl?: string, authHeaderOrOptions?: string | ApiOptions, timeout?: number);
136
+ /**
137
+ * Add custom headers to all subsequent requests.
138
+ */
139
+ addHeaders(headers: Record<string, string>): void;
140
+ /**
141
+ * Set Bearer token authentication.
142
+ */
143
+ setBearerToken(token: string): void;
144
+ /**
145
+ * Set Basic authentication.
146
+ */
147
+ setBasicAuth(username: string, password: string): void;
148
+ /**
149
+ * Disable SSL certificate verification (dev/self-signed certs only).
150
+ */
151
+ setIgnoreSsl(ignore: boolean): void;
152
+ /**
153
+ * HTTP GET request.
154
+ */
155
+ get(path: string, params?: Record<string, string>): Promise<ApiResult>;
156
+ /**
157
+ * HTTP POST request.
158
+ */
159
+ post(path: string, body?: unknown, contentType?: string): Promise<ApiResult>;
160
+ /**
161
+ * HTTP PUT request.
162
+ */
163
+ put(path: string, body?: unknown, contentType?: string): Promise<ApiResult>;
164
+ /**
165
+ * HTTP PATCH request.
166
+ */
167
+ patch(path: string, body?: unknown, contentType?: string): Promise<ApiResult>;
168
+ /**
169
+ * HTTP DELETE request.
170
+ */
171
+ delete(path: string, body?: unknown): Promise<ApiResult>;
172
+ /**
173
+ * Generic request method — public entry point for any HTTP method.
174
+ */
175
+ sendRequest(method: string, path: string, body?: unknown, contentType?: string): Promise<ApiResult>;
176
+ /**
177
+ * POST a `multipart/form-data` body — a file plus optional text fields.
178
+ *
179
+ * Two ways to supply the file, so a caller never needs a temp file:
180
+ *
181
+ * - `filePath` — a file on disk. `filename` defaults to its basename.
182
+ * - `fileBytes` + `filename` — an in-memory payload (Buffer or string).
183
+ *
184
+ * `fieldName` (default `"file"`) is the form field the file is sent under.
185
+ * `extraFields` become additional text parts. `headers` are extra per-call
186
+ * headers merged onto the request. The part's Content-Type is guessed from
187
+ * the filename (falling back to `application/octet-stream`).
188
+ *
189
+ * Returns the standard {@link ApiResult}. A missing file or no source given
190
+ * returns a clean error result (`http_code` null, `error` set) — it does NOT
191
+ * throw. Retry/backoff (if configured) applies, exactly like the verbs.
192
+ *
193
+ * await api.upload("/avatars", { filePath: "/tmp/me.png" });
194
+ * await api.upload("/avatars", { fileBytes: raw, filename: "me.png",
195
+ * extraFields: { user_id: "42" } });
196
+ */
197
+ upload(path: string, opts?: UploadOptions): Promise<ApiResult>;
198
+ /**
199
+ * Stream a GET response body to `destPath` in chunks.
200
+ *
201
+ * The body is written to disk `DOWNLOAD_CHUNK_SIZE` bytes at a time instead
202
+ * of being buffered whole in memory — safe for large payloads. Redirect
203
+ * following, the cross-origin auth strip, the cookie jar, and the SSL flag
204
+ * all apply, exactly like the other verbs.
205
+ *
206
+ * Returns {@link DownloadResult} — there is no `body` field (it went to
207
+ * disk). `path` is `destPath` on success and `null` on any error (missing
208
+ * dest, HTTP error status, or a transport failure); the destination file is
209
+ * not written on error.
210
+ */
211
+ download(path: string, destPath: string, params?: Record<string, string>): Promise<DownloadResult>;
212
+ private buildUrl;
213
+ /**
214
+ * Build the request headers (auth + cookie jar + extras) and serialize the
215
+ * body to a Buffer. Shared by every verb, upload, and download so the wire
216
+ * shape is identical and the transport seam sees exactly what the network
217
+ * path would.
218
+ */
219
+ private buildRequest;
220
+ /**
221
+ * Execute the request with opt-in retry/backoff.
222
+ *
223
+ * With `maxRetries` > 0, a transport failure (`http_code` null) or a
224
+ * retryable status (429/5xx) is retried up to `maxRetries` times with
225
+ * exponential backoff; any other outcome (2xx, 3xx, other 4xx) returns
226
+ * at once. A retried non-idempotent request may be re-sent — retries
227
+ * are opt-in for that reason.
228
+ */
229
+ private execute;
230
+ /** A single HTTP attempt — returns the standardized result. */
231
+ private attempt;
232
+ /**
233
+ * Invoke a user-injected transport and normalize its result. The transport
234
+ * is called with `(method, url, headers, body, timeout)` and its returned
235
+ * `Set-Cookie` headers (if any) feed the cookie jar.
236
+ */
237
+ private callTransport;
238
+ /**
239
+ * Perform the network request, following up to `redirectsLeft` redirects.
240
+ *
241
+ * node:http/https `request` does NOT auto-follow redirects. On a 3xx with a
242
+ * Location, this drains the intermediate response and re-issues to the new
243
+ * URL: 301/302/303 on a non-GET/HEAD become GET (body dropped, urllib
244
+ * behaviour); 307/308 preserve method + body. When the redirect target is a
245
+ * DIFFERENT origin, the Authorization and Cookie headers are stripped so a
246
+ * bearer token / session cookie never leaks to a host you didn't
247
+ * authenticate to.
248
+ */
249
+ private performRequest;
250
+ /** Buffer a response body, parse JSON if possible, and store cookies. */
251
+ private readResponse;
252
+ /** The accumulated `Cookie` request header, or null when the jar is empty. */
253
+ private cookieHeader;
254
+ /**
255
+ * Parse `Set-Cookie` response headers into the jar (when enabled). Only the
256
+ * leading `name=value` pair of each is kept (Path/HttpOnly/Expires ignored);
257
+ * a later value for the same name overwrites an earlier one.
258
+ */
259
+ private storeCookies;
260
+ /** Store cookies from a plain header record (the transport seam path). */
261
+ private storeCookiesFromRecord;
262
+ }
@@ -0,0 +1,177 @@
1
+ import type { Middleware } from "./types.js";
2
+ /**
3
+ * Ensure a usable TINA4_SECRET exists. Run ONCE at server boot, after env load
4
+ * and before auth is used. Mirrors Python's `ensure_dev_secret()`.
5
+ *
6
+ * Order:
7
+ * 1. TINA4_SECRET already set → no-op (return null).
8
+ * 2. NOT dev, OR CI, OR production → emit the actionable warning, return null.
9
+ * NEVER generates or persists a secret in CI / production / non-dev.
10
+ * 3. Otherwise (dev, not CI, not prod, blank secret) → generate a 32-byte hex
11
+ * secret, set it in process.env for THIS run immediately, then try to append
12
+ * it to <cwd>/.env.local (create if missing; never touch .env). On a write
13
+ * failure keep the in-memory secret and warn — boot must never crash.
14
+ *
15
+ * @param cwd - Directory to write .env.local into. Tests pass a temp dir; production passes nothing.
16
+ * @returns The newly-generated secret, or null when nothing was generated.
17
+ */
18
+ export declare function ensureDevSecret(cwd?: string): string | null;
19
+ /**
20
+ * Can this runtime actually sign and verify `algorithm` right now?
21
+ *
22
+ * The cross-framework capability check — same question, same answer shape, in
23
+ * all four frameworks. HMAC answers `true` everywhere. RS256 answers `true`
24
+ * only where the runtime ships asymmetric crypto natively (node:crypto here,
25
+ * core ext-openssl in PHP, the stdlib openssl gem in Ruby) and `false` in
26
+ * tina4-python. An algorithm Tina4 does not know at all answers `false`.
27
+ */
28
+ export declare function algorithmAvailable(algorithm: string): boolean;
29
+ /** Every algorithm this runtime can sign and verify right now, in advertised order. */
30
+ export declare function availableAlgorithms(): string[];
31
+ /**
32
+ * Seconds of clock skew tolerated on the "nbf" (not-before) claim.
33
+ *
34
+ * Without this, a token minted on one host and validated on another a second
35
+ * behind is rejected for no real reason; RFC 7519 explicitly allows "a small
36
+ * leeway". Same value as the Python master's `_JWT_LEEWAY_SECONDS`.
37
+ */
38
+ export declare const JWT_LEEWAY_SECONDS = 60;
39
+ /**
40
+ * Pick the JWT algorithm: explicit argument, else TINA4_JWT_ALGORITHM, else HS256.
41
+ *
42
+ * Throws when asked for an algorithm Tina4 does not know (naming the known set,
43
+ * what is available here, and the env var), and throws again — with the runtime's
44
+ * own reason and a remedy — when it knows the algorithm but this build cannot
45
+ * provide it. A silent downgrade to HS256 is the whole bug in python#106, and a
46
+ * silent downgrade from RS256 would be worse: it would quietly turn asymmetric
47
+ * verification into a shared secret.
48
+ *
49
+ * @param algorithm - Explicit algorithm; wins over the environment when given.
50
+ */
51
+ export declare function resolveAlgorithm(algorithm?: string): string;
52
+ /**
53
+ * Create a signed JWT token.
54
+ *
55
+ * Secret is always read from `process.env.TINA4_SECRET`.
56
+ * Algorithm is read from `process.env.TINA4_JWT_ALGORITHM` (default "HS256").
57
+ * HS256 / HS384 / HS512 is the cross-framework standard; RS256 is an opt-in
58
+ * extra that Node provides from builtin node:crypto (pass the PEM private key
59
+ * as the secret). An unknown algorithm, or one this runtime cannot provide,
60
+ * throws — see `resolveAlgorithm`.
61
+ *
62
+ * The header's `alg` is always the algorithm that actually signed the token.
63
+ *
64
+ * No `nbf` (not-before) claim is stamped — parity with Python and PHP. Pass your
65
+ * own `nbf` in the payload to post-date a token; `validToken` enforces it.
66
+ *
67
+ * @param payload - Claims to encode (e.g. `{ userId: 1, role: "admin" }`)
68
+ * @param secretOrExpiresIn - Signing secret string, OR expiresIn number in MINUTES (back-compat with old 2-arg form)
69
+ * @param expiresIn - Lifetime in MINUTES (default 60). `0` ⇒ no `exp` claim (non-expiring). Only used when secret is a string.
70
+ * @param algorithm - Overrides TINA4_JWT_ALGORITHM for this call.
71
+ * @returns Signed JWT string: header.payload.signature
72
+ * @throws When the resolved algorithm is not one Tina4 can sign.
73
+ */
74
+ export declare function getToken(payload: Record<string, unknown>, secretOrExpiresIn?: string | number, expiresIn?: number, algorithm?: string): string;
75
+ /**
76
+ * Validate a JWT token. Returns the decoded payload on success, `null` if
77
+ * invalid/expired/malformed.
78
+ *
79
+ * 3.13.0 — return type changed from `boolean` to `Record<string, unknown> | null`.
80
+ * Matches the convention used by `jsonwebtoken` and the Python / PHP / Ruby
81
+ * Auth.validToken signatures shipped at the same time. Legacy
82
+ * `if (validToken(t))` patterns keep working because a non-null object is
83
+ * truthy and null is falsy.
84
+ *
85
+ * Secret is read from `process.env.TINA4_SECRET` when not passed explicitly.
86
+ * Algorithm is read from `process.env.TINA4_JWT_ALGORITHM` (default "HS256").
87
+ *
88
+ * Checks, in order: the header's `alg` must BE the expected algorithm (blocks alg
89
+ * substitution, including `alg: "none"`, before any signature work), then the
90
+ * signature, then `exp`, then `nbf` (with `JWT_LEEWAY_SECONDS` of clock skew).
91
+ */
92
+ export declare function validToken(token: string, secret?: string, algorithm?: string): Record<string, unknown> | null;
93
+ /**
94
+ * Get the JWT payload WITHOUT verifying signature or expiration.
95
+ */
96
+ export declare function getPayload(token: string): Record<string, unknown> | null;
97
+ /**
98
+ * Hash a password using PBKDF2-SHA256.
99
+ *
100
+ * @param password - Plaintext password
101
+ * @param salt - Hex-encoded salt (auto-generated if omitted)
102
+ * @param iterations - PBKDF2 iterations (default 260000)
103
+ * @returns Format: `pbkdf2_sha256$iterations$salt$hash` (all hex-encoded)
104
+ */
105
+ export declare function hashPassword(password: string, salt?: string, iterations?: number): string;
106
+ /**
107
+ * Check a password against a PBKDF2 hash string.
108
+ * Supports both $ and : delimiters for backward compatibility.
109
+ */
110
+ export declare function checkPassword(password: string, hash: string): boolean;
111
+ /**
112
+ * Auth middleware that extracts and verifies a Bearer JWT from the
113
+ * Authorization header. On success, attaches the decoded payload to
114
+ * `(request as any).auth`. On failure, sends a 401 JSON response.
115
+ *
116
+ * @param secret - Signing secret / PEM public key (default: TINA4_SECRET env var).
117
+ * @param algorithm - JWT algorithm. Omit it to honour TINA4_JWT_ALGORITHM (then
118
+ * HS256). It used to default to the literal "HS256", which SHADOWED the env
119
+ * var: an app on TINA4_JWT_ALGORITHM=HS512 minted HS512 tokens and this
120
+ * middleware verified them as HS256, rejecting every valid token.
121
+ */
122
+ export declare function authMiddleware(secret?: string, algorithm?: string): Middleware;
123
+ /**
124
+ * Refresh a JWT token — validate the existing token then re-sign
125
+ * with a fresh expiry.
126
+ *
127
+ * Secret is always read from `process.env.TINA4_SECRET`.
128
+ *
129
+ * @param token - Existing JWT to refresh
130
+ * @param expiresIn - New lifetime in MINUTES (default 60)
131
+ * @returns New signed JWT string, or null if the input token is invalid/expired
132
+ */
133
+ export declare function refreshToken(token: string, expiresIn?: number): string | null;
134
+ /**
135
+ * Extract a Bearer token from request headers and validate it.
136
+ *
137
+ * @param headers - Object with header keys (e.g. `{ authorization: "Bearer ..." }`)
138
+ * @param secret - HMAC secret or PEM public key
139
+ * @param algorithm - Omit it to honour TINA4_JWT_ALGORITHM (then HS256). HS256 /
140
+ * HS384 / HS512 everywhere; RS256 where the runtime provides it (it does here).
141
+ * @returns Decoded payload, or null if missing/invalid
142
+ */
143
+ export declare function authenticateRequest(headers: Record<string, string | string[] | undefined>, secret?: string, algorithm?: string): Record<string, unknown> | null;
144
+ /**
145
+ * Compare an API key against an expected value.
146
+ * If `expected` is omitted, falls back to the `TINA4_API_KEY` env var.
147
+ *
148
+ * Uses constant-time comparison to prevent timing attacks.
149
+ *
150
+ * @param provided - The API key provided by the caller
151
+ * @param expected - The correct API key (defaults to `process.env.TINA4_API_KEY`)
152
+ * @returns true if the keys match
153
+ */
154
+ export declare function validateApiKey(provided: string, expected?: string): boolean;
155
+ /**
156
+ * Auth class that wraps the standalone auth functions so both patterns work:
157
+ *
158
+ * import { Auth } from "tina4-nodejs";
159
+ * const token = Auth.getToken(payload, secret);
160
+ *
161
+ * import { getToken } from "tina4-nodejs";
162
+ * const token = getToken(payload, secret);
163
+ */
164
+ export declare class Auth {
165
+ static getToken: typeof getToken;
166
+ static validToken: typeof validToken;
167
+ static resolveAlgorithm: typeof resolveAlgorithm;
168
+ static algorithmAvailable: typeof algorithmAvailable;
169
+ static availableAlgorithms: typeof availableAlgorithms;
170
+ static getPayload: typeof getPayload;
171
+ static hashPassword: typeof hashPassword;
172
+ static checkPassword: typeof checkPassword;
173
+ static authMiddleware: typeof authMiddleware;
174
+ static refreshToken: typeof refreshToken;
175
+ static authenticateRequest: typeof authenticateRequest;
176
+ static validateApiKey: typeof validateApiKey;
177
+ }
@@ -0,0 +1,20 @@
1
+ import type { Tina4Request, Tina4Response } from "./types.js";
2
+ /** Just the auth-relevant fields of a matched route. */
3
+ export interface AuthGateRoute {
4
+ secure?: boolean;
5
+ noAuth?: boolean;
6
+ }
7
+ /**
8
+ * Enforce auth for a matched route.
9
+ *
10
+ * Returns `true` when the request is REJECTED — a 401 has already been written
11
+ * to `res.raw` and the caller must stop (not run the handler). Returns `false`
12
+ * when the route is public OR a valid token was presented (in which case
13
+ * `req.user` is populated and, for a body formToken, a `FreshToken` header is
14
+ * set). Auth is enforced only for a route that is `secure` and not `noAuth`,
15
+ * and never for `/__dev` dev-admin routes.
16
+ *
17
+ * Token sources, in priority order: `Authorization: Bearer` header, a
18
+ * `formToken` in the parsed body, then a session token.
19
+ */
20
+ export declare function enforceRouteAuth(req: Tina4Request, res: Tina4Response, match: AuthGateRoute, isDevAdmin: boolean): boolean;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Background tasks — periodic callbacks that run alongside the HTTP server.
3
+ *
4
+ * Mirrors Python's `tina4_python.core.server.background(fn, interval=1.0)`.
5
+ * Use this instead of `setInterval` directly, so timers integrate with the
6
+ * server lifecycle and clear cleanly on graceful shutdown (SIGTERM/SIGINT)
7
+ * or when `stopAllBackgroundTasks()` is called.
8
+ *
9
+ * import { background } from "@tina4/core";
10
+ *
11
+ * background(() => processQueue(), 2); // every 2 seconds
12
+ * background(async () => await healthCheck(), 30); // async also fine
13
+ *
14
+ * Errors thrown from a callback are caught and logged so a single failing
15
+ * task cannot bring down the rest of the timer wheel.
16
+ */
17
+ /**
18
+ * Register a callback to run periodically alongside the HTTP server.
19
+ *
20
+ * @param callback Function to call (sync or async, no arguments).
21
+ * @param intervalSeconds Seconds between invocations (default: 1).
22
+ * @returns A handle whose `stop()` clears just this one task.
23
+ */
24
+ export declare function background(callback: () => unknown | Promise<unknown>, intervalSeconds?: number): {
25
+ stop: () => void;
26
+ };
27
+ /**
28
+ * Clear every registered background task. Called by the server's graceful
29
+ * shutdown (its first step on SIGTERM/SIGINT) and by its `close()`, so both a
30
+ * signal and a manual shutdown stop the timer wheel along with the listeners.
31
+ */
32
+ export declare function stopAllBackgroundTasks(): void;
33
+ /** Number of currently-registered background tasks (test helper). */
34
+ export declare function backgroundTaskCount(): number;