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