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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dispatch pipeline: the concerns of `dispatch`, named and extracted.
|
|
3
|
+
*
|
|
4
|
+
* `dispatch` was a 485-line closure at cyclomatic complexity 65 against a
|
|
5
|
+
* ceiling of 10, on the path of every request, nested inside `startServer`
|
|
6
|
+
* (which is why that measured 45 as well). These are its concerns as
|
|
7
|
+
* standalone functions, so each can be read and tested without standing up a
|
|
8
|
+
* server.
|
|
9
|
+
*
|
|
10
|
+
* PROLOGUE_STAGES run before anything else, in order. They are extracted FIRST
|
|
11
|
+
* because they close over nothing from `startServer` - only the raw
|
|
12
|
+
* request/response - so no context object is needed for them at all. The later
|
|
13
|
+
* stages need `router`, `staticDir`, `port` and `middleware`, and follow.
|
|
14
|
+
* `sessionAutoStart` is the one prologue stage that runs INSIDE the dispatch
|
|
15
|
+
* try-block, so a TINA4_SESSION_STRICT refusal renders a 500 like every other
|
|
16
|
+
* request error instead of rejecting `dispatch` into an unhandled rejection
|
|
17
|
+
* that takes the worker down (ADR-0021; parity with Python, where the raise
|
|
18
|
+
* leaves the request path and the ASGI server turns it into a 500).
|
|
19
|
+
*
|
|
20
|
+
* Ordering here is BEHAVIOUR, not taste:
|
|
21
|
+
* * `headStripIntercept` MUST run before anything can write. Node streams its
|
|
22
|
+
* response, so there is no single exit point to strip at - the interception
|
|
23
|
+
* IS the mechanism (ADR-0011: the CONTRACT is the outcome, and Ruby and
|
|
24
|
+
* Python satisfy it by stripping late at their single return instead).
|
|
25
|
+
* * `sessionAutoStart` wraps `end` after that, so its save-and-set-cookie
|
|
26
|
+
* runs on the real `end` rather than on the HEAD interceptor's.
|
|
27
|
+
*
|
|
28
|
+
* @see tina4-ruby/lib/tina4/dispatch_pipeline.rb - the same extraction, and
|
|
29
|
+
* the source of the stage-list-as-data pattern.
|
|
30
|
+
*/
|
|
31
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
32
|
+
import type { Tina4Request } from "./types.js";
|
|
33
|
+
/**
|
|
34
|
+
* The prologue, in order. Exported as DATA so the pipeline can be asserted and
|
|
35
|
+
* compared across frameworks without reading an implementation.
|
|
36
|
+
*/
|
|
37
|
+
export declare const PROLOGUE_STAGES: readonly ["resetRequestCaches", "headStripIntercept", "sessionAutoStart"];
|
|
38
|
+
/**
|
|
39
|
+
* After the prologue, before a route is looked up.
|
|
40
|
+
*
|
|
41
|
+
* `wrapResponseEnd` MUST come before the global pass: it installs the end()
|
|
42
|
+
* wrapper that injects the dev toolbar and captures the request, and a
|
|
43
|
+
* middleware that short-circuits still has to be captured.
|
|
44
|
+
*/
|
|
45
|
+
export declare const REQUEST_STAGES: readonly ["blockAiPortReload", "wrapResponseEnd", "runGlobalMiddlewarePass"];
|
|
46
|
+
/**
|
|
47
|
+
* A matched route, in order - and the order is BEHAVIOUR (ADR-0012):
|
|
48
|
+
* POST-MATCH globals -> auth gate -> the route's OWN middleware -> handler.
|
|
49
|
+
*
|
|
50
|
+
* The globals run BEFORE the gate so a rate limiter can throttle a brute-force
|
|
51
|
+
* login and an access log records the 401 - neither is possible if they only
|
|
52
|
+
* run on authenticated requests. The route's own middleware stays AFTER the
|
|
53
|
+
* gate, so middleware attached to a secured route never processes an
|
|
54
|
+
* unauthenticated request.
|
|
55
|
+
*
|
|
56
|
+
* `runGlobalMiddlewarePass` appears here AND in REQUEST_STAGES on purpose:
|
|
57
|
+
* one function, two phases. That split IS ADR-0012.
|
|
58
|
+
*/
|
|
59
|
+
export declare const ROUTE_STAGES: readonly ["runGlobalMiddlewarePass", "enforceRouteAuth", "runRouteMiddlewares", "invokeRouteHandler", "renderIfTemplateRoute"];
|
|
60
|
+
/**
|
|
61
|
+
* Nothing matched a route: the fallback chain, walked until one answers.
|
|
62
|
+
*
|
|
63
|
+
* Order is BEHAVIOUR: a template beats the landing page (so a project's own
|
|
64
|
+
* pages/index.twig wins at "/"), 405 beats static (a known path with the wrong
|
|
65
|
+
* method is not a missing file), and the 404 is terminal.
|
|
66
|
+
*
|
|
67
|
+
* This chain runs AFTER matching because routes beat files (ADR-0010): a file
|
|
68
|
+
* from a build step or a careless deploy must never shadow a reviewed route.
|
|
69
|
+
*
|
|
70
|
+
* server.ts holds the same order as an array of the real FUNCTIONS - that is
|
|
71
|
+
* what dispatch actually walks. dispatchPipeline.test.ts asserts the two agree,
|
|
72
|
+
* so this list cannot drift from the runner.
|
|
73
|
+
*/
|
|
74
|
+
export declare const FALLBACK_STAGES: readonly ["serveTemplateFallback", "serveLandingPage", "serveMethodNotAllowed", "serveStaticAsset", "serveNotFound"];
|
|
75
|
+
/** The catch arm. Everything above throws into this one. */
|
|
76
|
+
export declare const ERROR_STAGES: readonly ["renderDispatchError"];
|
|
77
|
+
/**
|
|
78
|
+
* Request-scoped DB query cache boundary.
|
|
79
|
+
*
|
|
80
|
+
* Clears the request-scoped cache on every live connection at the START of each
|
|
81
|
+
* request so it never serves rows across requests (persistent-mode connections
|
|
82
|
+
* are left alone). The ORM is loaded lazily and may be absent, so this is
|
|
83
|
+
* best-effort: a failure here must never break a request. Mirrors Python's
|
|
84
|
+
* dispatcher calling `Database.reset_request_caches()`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function resetRequestCaches(): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* RFC 9110 s9.3.2: the server MUST NOT send content in a HEAD response.
|
|
89
|
+
*
|
|
90
|
+
* Intercepts `write` / `end` so every code path - an explicit `Router.head()`
|
|
91
|
+
* handler, the GET auto-fallback, 405 and 404 responses - drops its body.
|
|
92
|
+
* Content-Length is preserved when present, so cache validators, link checkers
|
|
93
|
+
* and monitoring probes still see the size the equivalent GET would have sent.
|
|
94
|
+
*
|
|
95
|
+
* No-op for any method other than HEAD.
|
|
96
|
+
*
|
|
97
|
+
* @param rawReq Node's incoming message, read for the method
|
|
98
|
+
* @param rawRes Node's server response, whose write/end are replaced in place
|
|
99
|
+
*/
|
|
100
|
+
export declare function headStripIntercept(rawReq: IncomingMessage, rawRes: ServerResponse): void;
|
|
101
|
+
/**
|
|
102
|
+
* Auto-start the session: read the cookie, create the session, then save it and
|
|
103
|
+
* set the cookie when the response ends.
|
|
104
|
+
*
|
|
105
|
+
* The incoming cookie is read by the SAME configured name the write side emits
|
|
106
|
+
* (`TINA4_SESSION_NAME`, default `tina4_session`) via the shared
|
|
107
|
+
* `sessionCookieName()` resolver - otherwise a renamed cookie would be written
|
|
108
|
+
* but never read back and the session would silently never resume. A whole
|
|
109
|
+
* cookie pair is matched by its exact `name=` prefix (split on ";", trim,
|
|
110
|
+
* startsWith) so `tina4_session` never matches `tina4_session_foo=` nor a value
|
|
111
|
+
* mid-header. Parity with Python `core/server._init_session`.
|
|
112
|
+
*
|
|
113
|
+
* @param rawReq Node's incoming message, read for cookies and the proxy scheme
|
|
114
|
+
* @param rawRes Node's server response, whose `end` is wrapped
|
|
115
|
+
* @param req The Tina4 request the session is attached to
|
|
116
|
+
*/
|
|
117
|
+
export declare function sessionAutoStart(rawReq: IncomingMessage, rawRes: ServerResponse, req: Tina4Request): Promise<void>;
|
|
@@ -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,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load environment variables from a root DIRECTORY or a single .env file.
|
|
3
|
+
*
|
|
4
|
+
* Pass a **directory** and it loads `<dir>/.env.local` then `<dir>/.env`, both
|
|
5
|
+
* first-wins, which IS the precedence real-env > `.env.local` > `.env`. That is
|
|
6
|
+
* the canonical form in all four frameworks.
|
|
7
|
+
*
|
|
8
|
+
* Before this, the ordering was the CALLER's job and this doc comment was the
|
|
9
|
+
* only place it was written down: load `.env.local` first, then `.env`, both
|
|
10
|
+
* with override=false. Every caller had to remember, and getting it wrong
|
|
11
|
+
* (override=true on `.env.local`) lets a stray gitignored file clobber an
|
|
12
|
+
* explicitly set real env var such as a production TINA4_SECRET. A rule nobody
|
|
13
|
+
* can forget beats a rule written in a comment.
|
|
14
|
+
*
|
|
15
|
+
* A **file** path still works exactly as before: only that file is read, and the
|
|
16
|
+
* caller owns the ordering.
|
|
17
|
+
*
|
|
18
|
+
* By default this does NOT override existing process.env values — it is
|
|
19
|
+
* first-wins, which is how a real env var always beats both files.
|
|
20
|
+
*
|
|
21
|
+
* Resolution order when `path` is omitted:
|
|
22
|
+
* 1. `TINA4_ENV_FILE` env var (if set and non-empty) — the named file, plus
|
|
23
|
+
* `.env.local` BESIDE it, so pointing at `.env.staging` does not silently
|
|
24
|
+
* stop honouring local overrides
|
|
25
|
+
* 2. the current working directory, as a root
|
|
26
|
+
*
|
|
27
|
+
* @param path - A root directory (canonical) OR a path to a single .env file.
|
|
28
|
+
* @param override - When true, overwrite keys already present in process.env.
|
|
29
|
+
* @returns The parsed key-value pairs. For the directory form this is the merge
|
|
30
|
+
* of both files, with `.env.local` winning on a duplicate key.
|
|
31
|
+
*/
|
|
32
|
+
export declare function loadEnv(path?: string, override?: boolean): Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* Get an environment variable value with an optional default.
|
|
35
|
+
*
|
|
36
|
+
* @param key - The environment variable name.
|
|
37
|
+
* @param defaultValue - Value to return if the variable is not set.
|
|
38
|
+
* @returns The environment variable value, or the default.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getEnv(key: string, defaultValue?: string): string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Get a required environment variable. Throws if not set.
|
|
43
|
+
*
|
|
44
|
+
* @param key - The environment variable name.
|
|
45
|
+
* @returns The environment variable value.
|
|
46
|
+
* @throws Error if the variable is not set.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* Validate that required environment variables exist, and return them.
|
|
50
|
+
*
|
|
51
|
+
* Takes VARARGS and returns a map, matching Python, PHP and Ruby. It used to
|
|
52
|
+
* take one key and return that value, so checking five variables meant five
|
|
53
|
+
* calls that each failed on the first problem - an operator fixing a deployment
|
|
54
|
+
* got one name per restart instead of the whole list.
|
|
55
|
+
*
|
|
56
|
+
* @param keys - Variable names that must be set.
|
|
57
|
+
* @returns Every requested key mapped to its value.
|
|
58
|
+
* @throws Error naming ALL missing variables, not just the first.
|
|
59
|
+
*/
|
|
60
|
+
export declare function requireEnv(...keys: string[]): Record<string, string>;
|
|
61
|
+
/**
|
|
62
|
+
* Check if an environment variable exists (is defined in process.env).
|
|
63
|
+
*
|
|
64
|
+
* @param key - The environment variable name.
|
|
65
|
+
* @returns true if the variable is set, false otherwise.
|
|
66
|
+
*/
|
|
67
|
+
export declare function hasEnv(key: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Return all currently loaded environment variables.
|
|
70
|
+
*
|
|
71
|
+
* @returns A shallow copy of process.env as a record.
|
|
72
|
+
*/
|
|
73
|
+
export declare function allEnv(): Record<string, string | undefined>;
|
|
74
|
+
/**
|
|
75
|
+
* Check if a value is truthy for env boolean checks.
|
|
76
|
+
*
|
|
77
|
+
* Accepts: "true", "True", "TRUE", "1", "yes", "Yes", "YES", "on", "On", "ON".
|
|
78
|
+
* Everything else is falsy (including empty string, undefined, not set).
|
|
79
|
+
*
|
|
80
|
+
* Mirrors Python's `is_truthy()` in `tina4_python.dotenv`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function isTruthy(val: string | undefined | null): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Remove all environment variables that were loaded by loadEnv().
|
|
85
|
+
* Useful for testing. Only removes keys set by loadEnv(), not pre-existing system env vars.
|
|
86
|
+
*/
|
|
87
|
+
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;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tina4 Events — Simple observer pattern for decoupled communication.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency event system. Fire events, register listeners.
|
|
5
|
+
*
|
|
6
|
+
* Events.on("user.created", (user) => console.log(`Welcome ${user.name}!`));
|
|
7
|
+
* Events.emit("user.created", { name: "Alice", email: "alice@example.com" });
|
|
8
|
+
*
|
|
9
|
+
* One-time listeners:
|
|
10
|
+
*
|
|
11
|
+
* Events.once("app.ready", () => console.log("App started!"));
|
|
12
|
+
*/
|
|
13
|
+
export declare class Events {
|
|
14
|
+
/**
|
|
15
|
+
* Register a listener for an event.
|
|
16
|
+
* Higher priority runs first.
|
|
17
|
+
*/
|
|
18
|
+
static on(event: string, callback: (...args: unknown[]) => void, priority?: number): void;
|
|
19
|
+
/**
|
|
20
|
+
* Register a listener that fires only once then auto-removes.
|
|
21
|
+
*/
|
|
22
|
+
static once(event: string, callback: (...args: unknown[]) => void, priority?: number): void;
|
|
23
|
+
/**
|
|
24
|
+
* Remove a specific listener, or all listeners for an event.
|
|
25
|
+
*
|
|
26
|
+
* Events.off("user.created", handler) // remove specific
|
|
27
|
+
* Events.off("user.created") // remove all for event
|
|
28
|
+
*/
|
|
29
|
+
static off(event: string, callback?: (...args: unknown[]) => void): void;
|
|
30
|
+
/**
|
|
31
|
+
* Fire an event synchronously. Returns array of listener results.
|
|
32
|
+
*
|
|
33
|
+
* Listener isolation (E1): each listener call is wrapped — a listener
|
|
34
|
+
* that THROWS does NOT abort the rest of emit(). The error is LOGGED
|
|
35
|
+
* (never silent) and the failed listener contributes a `null` slot, so
|
|
36
|
+
* N listeners always yield N results in priority order; surviving
|
|
37
|
+
* listeners run regardless of an earlier throw.
|
|
38
|
+
*
|
|
39
|
+
* Pass `{ strict: true }` to RE-RAISE on the first listener error
|
|
40
|
+
* instead of isolating it (later listeners then do NOT run).
|
|
41
|
+
*
|
|
42
|
+
* once() cleanup stays correct under isolation: the one-shot listener is
|
|
43
|
+
* spliced out BEFORE its callback runs, so a throw never leaves it
|
|
44
|
+
* registered.
|
|
45
|
+
*/
|
|
46
|
+
static emit(event: string, ...args: unknown[]): unknown[];
|
|
47
|
+
static emit(event: string, options: {
|
|
48
|
+
strict?: boolean;
|
|
49
|
+
}, ...args: unknown[]): unknown[];
|
|
50
|
+
/**
|
|
51
|
+
* Emit an event and await all async listeners.
|
|
52
|
+
* Returns array of resolved results from each listener.
|
|
53
|
+
*
|
|
54
|
+
* Listener isolation (E1): identical to emit() — each awaited listener
|
|
55
|
+
* is isolated; a rejection/throw is LOGGED and contributes a `null`
|
|
56
|
+
* slot without aborting the others. `{ strict: true }` re-raises on the
|
|
57
|
+
* first error.
|
|
58
|
+
*/
|
|
59
|
+
static emitAsync(event: string, ...args: unknown[]): Promise<unknown[]>;
|
|
60
|
+
static emitAsync(event: string, options: {
|
|
61
|
+
strict?: boolean;
|
|
62
|
+
}, ...args: unknown[]): Promise<unknown[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Get all listener callbacks for an event (in priority order).
|
|
65
|
+
*/
|
|
66
|
+
static listeners(event: string): Array<(...args: unknown[]) => void>;
|
|
67
|
+
/**
|
|
68
|
+
* List all registered event names.
|
|
69
|
+
*/
|
|
70
|
+
static events(): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Remove all listeners for all events.
|
|
73
|
+
*/
|
|
74
|
+
static clear(): void;
|
|
75
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare class FakeData {
|
|
2
|
+
private rng;
|
|
3
|
+
private seeded;
|
|
4
|
+
constructor(seed?: number);
|
|
5
|
+
/** Static factory — create a seeded FakeData instance. */
|
|
6
|
+
static seed(seed: number): FakeData;
|
|
7
|
+
/** Returns a random integer in [min, max) using the instance PRNG. */
|
|
8
|
+
private randInt;
|
|
9
|
+
/** Pick a random element from an array. */
|
|
10
|
+
private pick;
|
|
11
|
+
firstName(): string;
|
|
12
|
+
lastName(): string;
|
|
13
|
+
name(): string;
|
|
14
|
+
email(): string;
|
|
15
|
+
phone(): string;
|
|
16
|
+
address(): string;
|
|
17
|
+
city(): string;
|
|
18
|
+
country(): string;
|
|
19
|
+
zipCode(): string;
|
|
20
|
+
company(): string;
|
|
21
|
+
jobTitle(): string;
|
|
22
|
+
paragraph(sentences?: number): string;
|
|
23
|
+
sentence(words?: number): string;
|
|
24
|
+
word(): string;
|
|
25
|
+
integer(min?: number, max?: number): number;
|
|
26
|
+
numeric(min?: number, max?: number, decimals?: number): number;
|
|
27
|
+
boolean(): boolean;
|
|
28
|
+
date(start?: string, end?: string): string;
|
|
29
|
+
uuid(): string;
|
|
30
|
+
url(): string;
|
|
31
|
+
ipAddress(): string;
|
|
32
|
+
colorHex(): string;
|
|
33
|
+
/** Returns fake test credit card numbers (Luhn-valid test patterns). */
|
|
34
|
+
creditCard(): string;
|
|
35
|
+
currency(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Returns multi-paragraph text.
|
|
38
|
+
* Matches Python's text() method.
|
|
39
|
+
*/
|
|
40
|
+
text(paragraphs?: number): string;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a random element from the given array.
|
|
43
|
+
* Matches Python's choice() method.
|
|
44
|
+
*/
|
|
45
|
+
choice<T>(items: T[]): T;
|
|
46
|
+
/**
|
|
47
|
+
* Run seed files from a directory. Each file should export a default async function.
|
|
48
|
+
* Returns an array of executed file paths.
|
|
49
|
+
*/
|
|
50
|
+
seedDir(seedDir?: string): Promise<string[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Run a generator function `count` times and return the results.
|
|
53
|
+
*/
|
|
54
|
+
run(fn: () => Record<string, unknown>, count?: number): Record<string, unknown>[];
|
|
55
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customer feedback widget — Tier 4 port from tina4-python.
|
|
3
|
+
*
|
|
4
|
+
* End-users of a shipped Tina4 app give UX feedback via a floating bubble
|
|
5
|
+
* widget. Widget visibility + API are gated by TWO env flags:
|
|
6
|
+
*
|
|
7
|
+
* - TINA4_ENABLE_FEEDBACK master switch (explicit opt-in)
|
|
8
|
+
* - TINA4_FEEDBACK_WHITELIST comma-separated emails / user IDs
|
|
9
|
+
*
|
|
10
|
+
* Architecture (mirrors Python `tina4_python/dev_admin/__init__.py`
|
|
11
|
+
* lines 1440-1645):
|
|
12
|
+
*
|
|
13
|
+
* 1. Framework middleware injects <script src="/__feedback/widget.js">
|
|
14
|
+
* into HTML responses for whitelisted users only.
|
|
15
|
+
* 2. Widget POSTs to /__feedback/api/turn for each conversational turn.
|
|
16
|
+
* 3. That handler verifies whitelist + rate-limit, stamps the user
|
|
17
|
+
* identity server-side (client cannot fake `sender`), then forwards
|
|
18
|
+
* to the Rust agent's /feedback/intake.
|
|
19
|
+
*
|
|
20
|
+
* The widget is for END USERS of a shipped app — the /__dev paths get
|
|
21
|
+
* skipped so the dev admin's own chat bubble doesn't sit on top of the
|
|
22
|
+
* customer feedback bubble.
|
|
23
|
+
*/
|
|
24
|
+
import type { RouteHandler, Tina4Request } from "./types.js";
|
|
25
|
+
import type { Router } from "./router.js";
|
|
26
|
+
/**
|
|
27
|
+
* Master switch — both this AND a non-empty whitelist must be set for
|
|
28
|
+
* the widget to render or the API to accept submissions. Mirrors
|
|
29
|
+
* Python's `_feedback_enabled()`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function feedbackEnabled(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Comma-separated emails / user IDs in env, lowercased + trimmed.
|
|
34
|
+
* Returns [] when the master switch is off so callers can short-circuit
|
|
35
|
+
* with a single check. Mirrors Python's `_feedback_whitelist()`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function feedbackWhitelist(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Best-effort user identity from JWT/Bearer auth. Falls back to
|
|
40
|
+
* TINA4_FEEDBACK_DEV_USER (local dev convenience — lets the framework
|
|
41
|
+
* owner test the widget without a full auth setup). Mirrors Python's
|
|
42
|
+
* `_feedback_identify_user()`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function feedbackIdentifyUser(request: Tina4Request): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Returns [allowed, userId]. Both halves are required — feature off when
|
|
47
|
+
* either is falsy. Mirrors Python's `_feedback_is_whitelisted()`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function feedbackIsWhitelisted(request: Tina4Request): [boolean, string | null];
|
|
50
|
+
/**
|
|
51
|
+
* 5 turns/hour per user, sliding window. Prunes old timestamps lazily on
|
|
52
|
+
* every call (no background task needed). Mirrors Python's
|
|
53
|
+
* `_feedback_rate_limit_ok()`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function feedbackRateLimitOk(user: string): boolean;
|
|
56
|
+
/** Test-only: clear rate-limit state between cases. Not part of public API. */
|
|
57
|
+
export declare function _resetFeedbackRateLimit(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Insert the widget <script> into HTML for whitelisted users. Called
|
|
60
|
+
* from the response pipeline right before the body is flushed. No-op if:
|
|
61
|
+
* - request path starts with /__dev or /__feedback (developer
|
|
62
|
+
* pages have their own chat trigger)
|
|
63
|
+
* - master switch / whitelist not set
|
|
64
|
+
* - user not in whitelist
|
|
65
|
+
* - html lacks </body>
|
|
66
|
+
* Idempotent — looks for the `data-tina4-feedback` marker and bails.
|
|
67
|
+
* Mirrors Python's `inject_feedback_widget()`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function injectFeedbackWidget(request: Tina4Request, html: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* POST /__feedback/api/turn — proxy one conversational turn to the Rust
|
|
72
|
+
* agent's `/feedback/intake`. Server stamps `sender` from the verified
|
|
73
|
+
* identity so the client cannot inject who they are. Mirrors Python's
|
|
74
|
+
* `_api_feedback_turn()`.
|
|
75
|
+
*/
|
|
76
|
+
export declare const handleFeedbackTurn: RouteHandler;
|
|
77
|
+
declare const WIDGET_BUNDLE_PATH: string;
|
|
78
|
+
/**
|
|
79
|
+
* GET /__feedback/widget.js — serve the widget bundle with no-cache
|
|
80
|
+
* headers so a broken bundle doesn't get stuck in browser caches.
|
|
81
|
+
* Mirrors Python's `_api_feedback_widget_js()`.
|
|
82
|
+
*/
|
|
83
|
+
export declare const handleFeedbackWidgetJs: RouteHandler;
|
|
84
|
+
/**
|
|
85
|
+
* Register the two feedback routes on a Router. Called from the dev
|
|
86
|
+
* admin setup so the routes only exist when the dev surface is
|
|
87
|
+
* enabled — production deployments without TINA4_DEBUG also skip them.
|
|
88
|
+
*/
|
|
89
|
+
export declare function registerFeedbackRoutes(router: Router): void;
|
|
90
|
+
export { WIDGET_BUNDLE_PATH };
|