@jini-ai/http-kit 0.2.1
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/LICENSE +201 -0
- package/README.md +107 -0
- package/dist/active-context.d.ts +99 -0
- package/dist/active-context.d.ts.map +1 -0
- package/dist/active-context.js +77 -0
- package/dist/active-context.js.map +1 -0
- package/dist/adapter.d.ts +36 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +92 -0
- package/dist/adapter.js.map +1 -0
- package/dist/agents.d.ts +55 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +23 -0
- package/dist/agents.js.map +1 -0
- package/dist/api-security-middleware.d.ts +146 -0
- package/dist/api-security-middleware.d.ts.map +1 -0
- package/dist/api-security-middleware.js +276 -0
- package/dist/api-security-middleware.js.map +1 -0
- package/dist/attachments.d.ts +317 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +664 -0
- package/dist/attachments.js.map +1 -0
- package/dist/cancel-owned-runs.d.ts +44 -0
- package/dist/cancel-owned-runs.d.ts.map +1 -0
- package/dist/cancel-owned-runs.js +35 -0
- package/dist/cancel-owned-runs.js.map +1 -0
- package/dist/compat.d.ts +22 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +17 -0
- package/dist/compat.js.map +1 -0
- package/dist/component-catalog.d.ts +74 -0
- package/dist/component-catalog.d.ts.map +1 -0
- package/dist/component-catalog.js +74 -0
- package/dist/component-catalog.js.map +1 -0
- package/dist/connectors.d.ts +165 -0
- package/dist/connectors.d.ts.map +1 -0
- package/dist/connectors.js +474 -0
- package/dist/connectors.js.map +1 -0
- package/dist/daemon-status.d.ts +72 -0
- package/dist/daemon-status.d.ts.map +1 -0
- package/dist/daemon-status.js +60 -0
- package/dist/daemon-status.js.map +1 -0
- package/dist/db-ops.d.ts +116 -0
- package/dist/db-ops.d.ts.map +1 -0
- package/dist/db-ops.js +191 -0
- package/dist/db-ops.js.map +1 -0
- package/dist/delegated-tools.d.ts +46 -0
- package/dist/delegated-tools.d.ts.map +1 -0
- package/dist/delegated-tools.js +155 -0
- package/dist/delegated-tools.js.map +1 -0
- package/dist/express/run-stream.d.ts +15 -0
- package/dist/express/run-stream.d.ts.map +1 -0
- package/dist/express/run-stream.js +11 -0
- package/dist/express/run-stream.js.map +1 -0
- package/dist/express-index.d.ts +32 -0
- package/dist/express-index.d.ts.map +1 -0
- package/dist/express-index.js +14 -0
- package/dist/express-index.js.map +1 -0
- package/dist/fastify/adapter.d.ts +31 -0
- package/dist/fastify/adapter.d.ts.map +1 -0
- package/dist/fastify/adapter.js +64 -0
- package/dist/fastify/adapter.js.map +1 -0
- package/dist/fastify/agents.d.ts +13 -0
- package/dist/fastify/agents.d.ts.map +1 -0
- package/dist/fastify/agents.js +7 -0
- package/dist/fastify/agents.js.map +1 -0
- package/dist/fastify/api-security-middleware.d.ts +64 -0
- package/dist/fastify/api-security-middleware.d.ts.map +1 -0
- package/dist/fastify/api-security-middleware.js +139 -0
- package/dist/fastify/api-security-middleware.js.map +1 -0
- package/dist/fastify/compat.d.ts +22 -0
- package/dist/fastify/compat.d.ts.map +1 -0
- package/dist/fastify/compat.js +16 -0
- package/dist/fastify/compat.js.map +1 -0
- package/dist/fastify/daemon-status.d.ts +22 -0
- package/dist/fastify/daemon-status.d.ts.map +1 -0
- package/dist/fastify/daemon-status.js +9 -0
- package/dist/fastify/daemon-status.js.map +1 -0
- package/dist/fastify/host-tools.d.ts +13 -0
- package/dist/fastify/host-tools.d.ts.map +1 -0
- package/dist/fastify/host-tools.js +8 -0
- package/dist/fastify/host-tools.js.map +1 -0
- package/dist/fastify/index.d.ts +36 -0
- package/dist/fastify/index.d.ts.map +1 -0
- package/dist/fastify/index.js +18 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/fastify/local-daemon-request.d.ts +43 -0
- package/dist/fastify/local-daemon-request.d.ts.map +1 -0
- package/dist/fastify/local-daemon-request.js +155 -0
- package/dist/fastify/local-daemon-request.js.map +1 -0
- package/dist/fastify/origin.d.ts +21 -0
- package/dist/fastify/origin.d.ts.map +1 -0
- package/dist/fastify/origin.js +14 -0
- package/dist/fastify/origin.js.map +1 -0
- package/dist/fastify/request.d.ts +20 -0
- package/dist/fastify/request.d.ts.map +1 -0
- package/dist/fastify/request.js +25 -0
- package/dist/fastify/request.js.map +1 -0
- package/dist/fastify/response.d.ts +20 -0
- package/dist/fastify/response.d.ts.map +1 -0
- package/dist/fastify/response.js +41 -0
- package/dist/fastify/response.js.map +1 -0
- package/dist/fastify/route-registration-guard.d.ts +70 -0
- package/dist/fastify/route-registration-guard.d.ts.map +1 -0
- package/dist/fastify/route-registration-guard.js +69 -0
- package/dist/fastify/route-registration-guard.js.map +1 -0
- package/dist/fastify/run-stream.d.ts +18 -0
- package/dist/fastify/run-stream.d.ts.map +1 -0
- package/dist/fastify/run-stream.js +10 -0
- package/dist/fastify/run-stream.js.map +1 -0
- package/dist/fastify/runs.d.ts +17 -0
- package/dist/fastify/runs.d.ts.map +1 -0
- package/dist/fastify/runs.js +33 -0
- package/dist/fastify/runs.js.map +1 -0
- package/dist/frontend-control.d.ts +131 -0
- package/dist/frontend-control.d.ts.map +1 -0
- package/dist/frontend-control.js +77 -0
- package/dist/frontend-control.js.map +1 -0
- package/dist/frontend-sessions.d.ts +100 -0
- package/dist/frontend-sessions.d.ts.map +1 -0
- package/dist/frontend-sessions.js +180 -0
- package/dist/frontend-sessions.js.map +1 -0
- package/dist/health.d.ts +91 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +53 -0
- package/dist/health.js.map +1 -0
- package/dist/host-tools.d.ts +174 -0
- package/dist/host-tools.d.ts.map +1 -0
- package/dist/host-tools.js +338 -0
- package/dist/host-tools.js.map +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/local-daemon-request.d.ts +44 -0
- package/dist/local-daemon-request.d.ts.map +1 -0
- package/dist/local-daemon-request.js +145 -0
- package/dist/local-daemon-request.js.map +1 -0
- package/dist/media.d.ts +131 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +352 -0
- package/dist/media.js.map +1 -0
- package/dist/memory.d.ts +230 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +331 -0
- package/dist/memory.js.map +1 -0
- package/dist/model-proxy.d.ts +45 -0
- package/dist/model-proxy.d.ts.map +1 -0
- package/dist/model-proxy.js +619 -0
- package/dist/model-proxy.js.map +1 -0
- package/dist/origin-validation.d.ts +64 -0
- package/dist/origin-validation.d.ts.map +1 -0
- package/dist/origin-validation.js +226 -0
- package/dist/origin-validation.js.map +1 -0
- package/dist/origin.d.ts +32 -0
- package/dist/origin.d.ts.map +1 -0
- package/dist/origin.js +14 -0
- package/dist/origin.js.map +1 -0
- package/dist/pack-http.d.ts +30 -0
- package/dist/pack-http.d.ts.map +1 -0
- package/dist/pack-http.js +12 -0
- package/dist/pack-http.js.map +1 -0
- package/dist/raw-sse.d.ts +44 -0
- package/dist/raw-sse.d.ts.map +1 -0
- package/dist/raw-sse.js +93 -0
- package/dist/raw-sse.js.map +1 -0
- package/dist/remote-run-events.d.ts +66 -0
- package/dist/remote-run-events.d.ts.map +1 -0
- package/dist/remote-run-events.js +230 -0
- package/dist/remote-run-events.js.map +1 -0
- package/dist/request.d.ts +19 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +25 -0
- package/dist/request.js.map +1 -0
- package/dist/research.d.ts +42 -0
- package/dist/research.d.ts.map +1 -0
- package/dist/research.js +316 -0
- package/dist/research.js.map +1 -0
- package/dist/response.d.ts +14 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +45 -0
- package/dist/response.js.map +1 -0
- package/dist/route-manifest.d.ts +31 -0
- package/dist/route-manifest.d.ts.map +1 -0
- package/dist/route-manifest.js +103 -0
- package/dist/route-manifest.js.map +1 -0
- package/dist/route-registration-guard.d.ts +65 -0
- package/dist/route-registration-guard.d.ts.map +1 -0
- package/dist/route-registration-guard.js +71 -0
- package/dist/route-registration-guard.js.map +1 -0
- package/dist/routines.d.ts +114 -0
- package/dist/routines.d.ts.map +1 -0
- package/dist/routines.js +320 -0
- package/dist/routines.js.map +1 -0
- package/dist/run-stream.d.ts +60 -0
- package/dist/run-stream.d.ts.map +1 -0
- package/dist/run-stream.js +108 -0
- package/dist/run-stream.js.map +1 -0
- package/dist/runs.d.ts +79 -0
- package/dist/runs.d.ts.map +1 -0
- package/dist/runs.js +232 -0
- package/dist/runs.js.map +1 -0
- package/dist/sse.d.ts +139 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +157 -0
- package/dist/sse.js.map +1 -0
- package/dist/terminals.d.ts +125 -0
- package/dist/terminals.d.ts.map +1 -0
- package/dist/terminals.js +349 -0
- package/dist/terminals.js.map +1 -0
- package/dist/tool-catalog.d.ts +68 -0
- package/dist/tool-catalog.d.ts.map +1 -0
- package/dist/tool-catalog.js +68 -0
- package/dist/tool-catalog.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace-root.d.ts +69 -0
- package/dist/workspace-root.d.ts.map +1 -0
- package/dist/workspace-root.js +63 -0
- package/dist/workspace-root.js.map +1 -0
- package/dist/xai.d.ts +86 -0
- package/dist/xai.d.ts.map +1 -0
- package/dist/xai.js +668 -0
- package/dist/xai.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module connectors
|
|
3
|
+
*
|
|
4
|
+
* `POST/GET /api/connectors/{auth,storage,payments,db,realtime}/...` — JSON transport over five
|
|
5
|
+
* narrow provider ports. The ports live here because they are the exact behavior this transport
|
|
6
|
+
* consumes; concrete adapters such as `@jini-ai/capability-providers` satisfy them structurally at a
|
|
7
|
+
* product composition root. That dependency direction is deliberate: locked `@jini-ai/http-kit` must not
|
|
8
|
+
* point down into an incubating implementation package.
|
|
9
|
+
*
|
|
10
|
+
* **SEC-005 throughout**: every provider call is wrapped so a raw Stripe/SQL/JWT/WebSocket error
|
|
11
|
+
* never reaches the HTTP caller verbatim — matching `media.ts`/`delegated-tools.ts`'s
|
|
12
|
+
* `reportInternalError` precedent exactly (a correlation-id-bearing generic `INTERNAL_ERROR`, the
|
|
13
|
+
* real error only reaching a host-owned sink).
|
|
14
|
+
*
|
|
15
|
+
* **`NOT_CONFIGURED` (503)**: every route's very first check is whether its one required
|
|
16
|
+
* capability slot (`deps.auth`/`deps.storage`/`deps.payments`/`deps.db`/`deps.realtime`) is even
|
|
17
|
+
* supplied — all five are independently optional on {@link ConnectorsHttpDeps}, and
|
|
18
|
+
* `@jini-ai/server`'s zero-config default (see that package's `create-local-node-daemon.ts` wiring)
|
|
19
|
+
* leaves every slot unconfigured. A request against an unconfigured capability gets a clean 503
|
|
20
|
+
* before touching anything else, never a crash or a fabricated result — the same "capability exists
|
|
21
|
+
* and is reachable but inert until a host configures it" shape `host-tools.ts#denyAllWorkspaceRoots`/
|
|
22
|
+
* `db-ops.ts#denyAllDaemonDbPolicy` already established for other zero-config-default route packs.
|
|
23
|
+
*
|
|
24
|
+
* **Wire shapes, chosen for this route pack specifically (the ports themselves have no opinion on
|
|
25
|
+
* HTTP transport):**
|
|
26
|
+
* - `StorageProvider.put`/`.get` deal in raw `Uint8Array` — JSON has no binary type, so this pack
|
|
27
|
+
* base64-encodes on the wire (`dataBase64` request/response field), the same encoding
|
|
28
|
+
* `media.ts#runMediaGenerationInBackground` already uses for generated bytes.
|
|
29
|
+
* - `AuthProvider.verifySession` takes a bearer token; the session-verification route accepts it in
|
|
30
|
+
* a POST JSON body. Credentials do not belong in URLs, where browser history, reverse proxies,
|
|
31
|
+
* and access logs commonly retain them.
|
|
32
|
+
* - `DbProvider.query`'s optional `where` filter is a JSON-encoded string in the `?where=` query
|
|
33
|
+
* parameter (`{"status":"active"}`), decoded and validated as a plain object before being handed
|
|
34
|
+
* to the provider.
|
|
35
|
+
* - `RealtimeProvider.subscribe` has no route here — see the realtime section below for why.
|
|
36
|
+
*/
|
|
37
|
+
import { randomUUID } from 'node:crypto';
|
|
38
|
+
import { createApiError } from '@jini-ai/protocol';
|
|
39
|
+
import { defineJsonRoute, mountJsonRoute } from './adapter.js';
|
|
40
|
+
import { validationError } from './request.js';
|
|
41
|
+
import { err, ok } from './types.js';
|
|
42
|
+
function defaultInternalErrorSink(context) {
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.error(`[@jini-ai/http-kit] internal error (connectors/${context.source}.${context.operation}, correlationId=${context.correlationId})`, context.error);
|
|
45
|
+
}
|
|
46
|
+
function notConfiguredError(capability) {
|
|
47
|
+
return createApiError('NOT_CONFIGURED', `${capability} provider not configured`);
|
|
48
|
+
}
|
|
49
|
+
/** Runs one provider call, converting any thrown error into a redacted, correlation-id-bearing `INTERNAL_ERROR` (SEC-005) instead of letting it reach the HTTP caller verbatim. */
|
|
50
|
+
async function guardedCall(deps, source, operation, fn) {
|
|
51
|
+
try {
|
|
52
|
+
return ok(await fn());
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const correlationId = randomUUID();
|
|
56
|
+
const sink = deps.onInternalError ?? defaultInternalErrorSink;
|
|
57
|
+
sink({ source, operation, correlationId, error });
|
|
58
|
+
return err(createApiError('INTERNAL_ERROR', 'an internal error occurred', { requestId: correlationId }));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function isRecord(value) {
|
|
62
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
63
|
+
}
|
|
64
|
+
function nonEmptyString(value) {
|
|
65
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : null;
|
|
66
|
+
}
|
|
67
|
+
function firstQueryValue(raw) {
|
|
68
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
69
|
+
return typeof value === 'string' ? value : undefined;
|
|
70
|
+
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// auth
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
function parseAuthCredentials(input) {
|
|
75
|
+
if (!isRecord(input.body))
|
|
76
|
+
return err(validationError('body must be a JSON object'));
|
|
77
|
+
const email = nonEmptyString(input.body.email);
|
|
78
|
+
if (!email)
|
|
79
|
+
return err(validationError('email must be a non-empty string', [{ path: 'email', message: 'required non-empty string' }]));
|
|
80
|
+
const password = nonEmptyString(input.body.password);
|
|
81
|
+
if (!password)
|
|
82
|
+
return err(validationError('password must be a non-empty string', [{ path: 'password', message: 'required non-empty string' }]));
|
|
83
|
+
return ok({ email, password });
|
|
84
|
+
}
|
|
85
|
+
function parseAuthToken(input) {
|
|
86
|
+
if (!isRecord(input.body))
|
|
87
|
+
return err(validationError('body must be a JSON object'));
|
|
88
|
+
const token = nonEmptyString(input.body.token);
|
|
89
|
+
if (!token)
|
|
90
|
+
return err(validationError('token must be a non-empty string', [{ path: 'token', message: 'required non-empty string' }]));
|
|
91
|
+
return ok(token);
|
|
92
|
+
}
|
|
93
|
+
export const connectorsAuthSignUpRoute = defineJsonRoute({
|
|
94
|
+
method: 'post',
|
|
95
|
+
path: '/api/connectors/auth/signup',
|
|
96
|
+
requireSameOrigin: true,
|
|
97
|
+
parse: parseAuthCredentials,
|
|
98
|
+
handle: async (credentials, deps) => {
|
|
99
|
+
if (!deps.auth)
|
|
100
|
+
return err(notConfiguredError('auth'));
|
|
101
|
+
const result = await guardedCall(deps, 'auth', 'signUp', () => deps.auth.signUp(credentials));
|
|
102
|
+
return result.ok ? ok({ user: result.value }) : result;
|
|
103
|
+
},
|
|
104
|
+
successStatus: 201,
|
|
105
|
+
});
|
|
106
|
+
export const connectorsAuthSignInRoute = defineJsonRoute({
|
|
107
|
+
method: 'post',
|
|
108
|
+
path: '/api/connectors/auth/signin',
|
|
109
|
+
requireSameOrigin: true,
|
|
110
|
+
parse: parseAuthCredentials,
|
|
111
|
+
handle: async (credentials, deps) => {
|
|
112
|
+
if (!deps.auth)
|
|
113
|
+
return err(notConfiguredError('auth'));
|
|
114
|
+
const result = await guardedCall(deps, 'auth', 'signIn', () => deps.auth.signIn(credentials));
|
|
115
|
+
return result.ok ? ok({ session: result.value }) : result;
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
export const connectorsAuthSignOutRoute = defineJsonRoute({
|
|
119
|
+
method: 'post',
|
|
120
|
+
path: '/api/connectors/auth/signout',
|
|
121
|
+
requireSameOrigin: true,
|
|
122
|
+
parse: parseAuthToken,
|
|
123
|
+
handle: async (token, deps) => {
|
|
124
|
+
if (!deps.auth)
|
|
125
|
+
return err(notConfiguredError('auth'));
|
|
126
|
+
const result = await guardedCall(deps, 'auth', 'signOut', () => deps.auth.signOut(token));
|
|
127
|
+
return result.ok ? ok({ ok: true }) : result;
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
export const connectorsAuthSessionRoute = defineJsonRoute({
|
|
131
|
+
method: 'post',
|
|
132
|
+
path: '/api/connectors/auth/session',
|
|
133
|
+
requireSameOrigin: true,
|
|
134
|
+
parse: parseAuthToken,
|
|
135
|
+
handle: async (token, deps) => {
|
|
136
|
+
if (!deps.auth)
|
|
137
|
+
return err(notConfiguredError('auth'));
|
|
138
|
+
const result = await guardedCall(deps, 'auth', 'verifySession', () => deps.auth.verifySession(token));
|
|
139
|
+
return result.ok ? ok({ user: result.value }) : result;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// storage
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
function parseStorageKey(input) {
|
|
146
|
+
const key = input.params.key;
|
|
147
|
+
return typeof key === 'string' && key.length > 0 ? ok(key) : err(validationError('key must be a non-empty path parameter'));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Strict base64 well-formedness check.
|
|
151
|
+
*
|
|
152
|
+
* `Buffer.from(value, 'base64')` cannot be used as the validator here because it never rejects
|
|
153
|
+
* anything: it silently skips every character outside the alphabet and returns whatever it managed
|
|
154
|
+
* to decode. `"!!!!"` decodes to zero bytes, and a payload truncated in transit decodes to a
|
|
155
|
+
* shorter one — both of which would then be written over whatever already lived at that key. A
|
|
156
|
+
* storage `put` that quietly persists the wrong bytes is worse than one that refuses them, so this
|
|
157
|
+
* insists on a canonical encoding: alphabet only, at most two trailing pad characters, a length
|
|
158
|
+
* that is a whole number of 4-character groups, and at least one real data character.
|
|
159
|
+
*/
|
|
160
|
+
const BASE64_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
161
|
+
function isWellFormedBase64(value) {
|
|
162
|
+
if (value.length === 0 || value.length % 4 !== 0)
|
|
163
|
+
return false;
|
|
164
|
+
return BASE64_PATTERN.test(value);
|
|
165
|
+
}
|
|
166
|
+
function parseStoragePut(input) {
|
|
167
|
+
const keyResult = parseStorageKey(input);
|
|
168
|
+
if (!keyResult.ok)
|
|
169
|
+
return keyResult;
|
|
170
|
+
if (!isRecord(input.body))
|
|
171
|
+
return err(validationError('body must be a JSON object'));
|
|
172
|
+
const dataBase64 = input.body.dataBase64;
|
|
173
|
+
if (typeof dataBase64 !== 'string' || !isWellFormedBase64(dataBase64)) {
|
|
174
|
+
return err(validationError('dataBase64 must be a non-empty base64-encoded string', [{ path: 'dataBase64', message: 'required base64 string' }]));
|
|
175
|
+
}
|
|
176
|
+
const contentType = input.body.contentType;
|
|
177
|
+
if (contentType !== undefined && typeof contentType !== 'string') {
|
|
178
|
+
return err(validationError('contentType must be a string when provided'));
|
|
179
|
+
}
|
|
180
|
+
return ok({ key: keyResult.value, dataBase64, ...(contentType !== undefined ? { contentType: contentType } : {}) });
|
|
181
|
+
}
|
|
182
|
+
function parseStorageListQuery(input) {
|
|
183
|
+
const prefix = firstQueryValue(input.query.prefix);
|
|
184
|
+
return ok(prefix);
|
|
185
|
+
}
|
|
186
|
+
export const connectorsStoragePutRoute = defineJsonRoute({
|
|
187
|
+
method: 'put',
|
|
188
|
+
path: '/api/connectors/storage/:key',
|
|
189
|
+
requireSameOrigin: true,
|
|
190
|
+
parse: parseStoragePut,
|
|
191
|
+
handle: async ({ key, dataBase64, contentType }, deps) => {
|
|
192
|
+
if (!deps.storage)
|
|
193
|
+
return err(notConfiguredError('storage'));
|
|
194
|
+
const options = contentType !== undefined ? { contentType } : undefined;
|
|
195
|
+
const result = await guardedCall(deps, 'storage', 'put', () => deps.storage.put(key, Buffer.from(dataBase64, 'base64'), options));
|
|
196
|
+
return result.ok ? ok({ object: result.value }) : result;
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
export const connectorsStorageGetRoute = defineJsonRoute({
|
|
200
|
+
method: 'get',
|
|
201
|
+
path: '/api/connectors/storage/:key',
|
|
202
|
+
parse: parseStorageKey,
|
|
203
|
+
handle: async (key, deps) => {
|
|
204
|
+
if (!deps.storage)
|
|
205
|
+
return err(notConfiguredError('storage'));
|
|
206
|
+
const result = await guardedCall(deps, 'storage', 'get', () => deps.storage.get(key));
|
|
207
|
+
if (!result.ok)
|
|
208
|
+
return result;
|
|
209
|
+
if (result.value === null)
|
|
210
|
+
return err(createApiError('NOT_FOUND', 'storage object not found'));
|
|
211
|
+
return ok({ dataBase64: Buffer.from(result.value).toString('base64') });
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
export const connectorsStorageDeleteRoute = defineJsonRoute({
|
|
215
|
+
method: 'delete',
|
|
216
|
+
path: '/api/connectors/storage/:key',
|
|
217
|
+
requireSameOrigin: true,
|
|
218
|
+
parse: parseStorageKey,
|
|
219
|
+
handle: async (key, deps) => {
|
|
220
|
+
if (!deps.storage)
|
|
221
|
+
return err(notConfiguredError('storage'));
|
|
222
|
+
const result = await guardedCall(deps, 'storage', 'delete', () => deps.storage.delete(key));
|
|
223
|
+
return result.ok ? ok({ ok: true }) : result;
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
export const connectorsStorageListRoute = defineJsonRoute({
|
|
227
|
+
method: 'get',
|
|
228
|
+
path: '/api/connectors/storage',
|
|
229
|
+
parse: parseStorageListQuery,
|
|
230
|
+
handle: async (prefix, deps) => {
|
|
231
|
+
if (!deps.storage)
|
|
232
|
+
return err(notConfiguredError('storage'));
|
|
233
|
+
const result = await guardedCall(deps, 'storage', 'list', () => deps.storage.list(prefix));
|
|
234
|
+
return result.ok ? ok({ objects: result.value }) : result;
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// payments
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
function parseChargeInput(input) {
|
|
241
|
+
if (!isRecord(input.body))
|
|
242
|
+
return err(validationError('body must be a JSON object'));
|
|
243
|
+
const amountCents = input.body.amountCents;
|
|
244
|
+
// Cents are a whole, positive unit. `isFinite` alone let `-125.5` reach `payments.charge()`,
|
|
245
|
+
// where a negative amount is a refund nobody requested and a fractional one is rounded by the
|
|
246
|
+
// provider in a way the caller cannot predict — and neither is recoverable once the charge
|
|
247
|
+
// exists. `isSafeInteger` also rejects magnitudes past the point where JSON round-trips stop
|
|
248
|
+
// being exact, which at a money boundary is a value nobody should be allowed to guess at.
|
|
249
|
+
if (typeof amountCents !== 'number' || !Number.isSafeInteger(amountCents) || amountCents <= 0) {
|
|
250
|
+
return err(validationError('amountCents must be a positive whole number of cents', [{ path: 'amountCents', message: 'required positive integer' }]));
|
|
251
|
+
}
|
|
252
|
+
const currency = nonEmptyString(input.body.currency);
|
|
253
|
+
if (!currency)
|
|
254
|
+
return err(validationError('currency must be a non-empty string', [{ path: 'currency', message: 'required non-empty string' }]));
|
|
255
|
+
const customerRef = nonEmptyString(input.body.customerRef);
|
|
256
|
+
if (!customerRef) {
|
|
257
|
+
return err(validationError('customerRef must be a non-empty string', [{ path: 'customerRef', message: 'required non-empty string' }]));
|
|
258
|
+
}
|
|
259
|
+
const description = input.body.description;
|
|
260
|
+
if (description !== undefined && typeof description !== 'string') {
|
|
261
|
+
return err(validationError('description must be a string when provided'));
|
|
262
|
+
}
|
|
263
|
+
return ok({ amountCents, currency, customerRef, ...(description !== undefined ? { description: description } : {}) });
|
|
264
|
+
}
|
|
265
|
+
function parseChargeId(input) {
|
|
266
|
+
const id = input.params.id;
|
|
267
|
+
return typeof id === 'string' && id.length > 0 ? ok(id) : err(validationError('id must be a non-empty path parameter'));
|
|
268
|
+
}
|
|
269
|
+
export const connectorsPaymentsChargeRoute = defineJsonRoute({
|
|
270
|
+
method: 'post',
|
|
271
|
+
path: '/api/connectors/payments/charge',
|
|
272
|
+
requireSameOrigin: true,
|
|
273
|
+
parse: parseChargeInput,
|
|
274
|
+
handle: async (input, deps) => {
|
|
275
|
+
if (!deps.payments)
|
|
276
|
+
return err(notConfiguredError('payments'));
|
|
277
|
+
const result = await guardedCall(deps, 'payments', 'charge', () => deps.payments.charge(input));
|
|
278
|
+
return result.ok ? ok({ charge: result.value }) : result;
|
|
279
|
+
},
|
|
280
|
+
successStatus: 201,
|
|
281
|
+
});
|
|
282
|
+
export const connectorsPaymentsGetRoute = defineJsonRoute({
|
|
283
|
+
method: 'get',
|
|
284
|
+
path: '/api/connectors/payments/:id',
|
|
285
|
+
parse: parseChargeId,
|
|
286
|
+
handle: async (id, deps) => {
|
|
287
|
+
if (!deps.payments)
|
|
288
|
+
return err(notConfiguredError('payments'));
|
|
289
|
+
const result = await guardedCall(deps, 'payments', 'getCharge', () => deps.payments.getCharge(id));
|
|
290
|
+
if (!result.ok)
|
|
291
|
+
return result;
|
|
292
|
+
if (result.value === null)
|
|
293
|
+
return err(createApiError('NOT_FOUND', 'charge not found'));
|
|
294
|
+
return ok({ charge: result.value });
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
export const connectorsPaymentsRefundRoute = defineJsonRoute({
|
|
298
|
+
method: 'post',
|
|
299
|
+
path: '/api/connectors/payments/:id/refund',
|
|
300
|
+
requireSameOrigin: true,
|
|
301
|
+
parse: parseChargeId,
|
|
302
|
+
handle: async (id, deps) => {
|
|
303
|
+
if (!deps.payments)
|
|
304
|
+
return err(notConfiguredError('payments'));
|
|
305
|
+
const result = await guardedCall(deps, 'payments', 'refund', () => deps.payments.refund(id));
|
|
306
|
+
return result.ok ? ok({ charge: result.value }) : result;
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// db
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
function parseDbCollection(input) {
|
|
313
|
+
const collection = input.params.collection;
|
|
314
|
+
return typeof collection === 'string' && collection.length > 0
|
|
315
|
+
? ok(collection)
|
|
316
|
+
: err(validationError('collection must be a non-empty path parameter'));
|
|
317
|
+
}
|
|
318
|
+
function parseDbInsert(input) {
|
|
319
|
+
const collectionResult = parseDbCollection(input);
|
|
320
|
+
if (!collectionResult.ok)
|
|
321
|
+
return collectionResult;
|
|
322
|
+
if (!isRecord(input.body))
|
|
323
|
+
return err(validationError('body must be a JSON object'));
|
|
324
|
+
const id = input.body.id;
|
|
325
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
326
|
+
return err(validationError('id must be a non-empty string field', [{ path: 'id', message: 'required non-empty string' }]));
|
|
327
|
+
}
|
|
328
|
+
return ok({ collection: collectionResult.value, record: input.body });
|
|
329
|
+
}
|
|
330
|
+
function parseDbCollectionId(input) {
|
|
331
|
+
const collectionResult = parseDbCollection(input);
|
|
332
|
+
if (!collectionResult.ok)
|
|
333
|
+
return collectionResult;
|
|
334
|
+
const id = input.params.id;
|
|
335
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
336
|
+
return err(validationError('id must be a non-empty path parameter'));
|
|
337
|
+
return ok({ collection: collectionResult.value, id });
|
|
338
|
+
}
|
|
339
|
+
function parseDbUpdate(input) {
|
|
340
|
+
const parsed = parseDbCollectionId(input);
|
|
341
|
+
if (!parsed.ok)
|
|
342
|
+
return parsed;
|
|
343
|
+
if (!isRecord(input.body))
|
|
344
|
+
return err(validationError('body must be a JSON object'));
|
|
345
|
+
return ok({ ...parsed.value, patch: input.body });
|
|
346
|
+
}
|
|
347
|
+
function parseDbQueryRequest(input) {
|
|
348
|
+
const collectionResult = parseDbCollection(input);
|
|
349
|
+
if (!collectionResult.ok)
|
|
350
|
+
return collectionResult;
|
|
351
|
+
const whereRaw = firstQueryValue(input.query.where);
|
|
352
|
+
if (whereRaw === undefined)
|
|
353
|
+
return ok({ collection: collectionResult.value });
|
|
354
|
+
let parsedWhere;
|
|
355
|
+
try {
|
|
356
|
+
parsedWhere = JSON.parse(whereRaw);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return err(validationError('where must be valid JSON when provided'));
|
|
360
|
+
}
|
|
361
|
+
if (!isRecord(parsedWhere))
|
|
362
|
+
return err(validationError('where must be a JSON object when provided'));
|
|
363
|
+
return ok({ collection: collectionResult.value, query: { where: parsedWhere } });
|
|
364
|
+
}
|
|
365
|
+
export const connectorsDbInsertRoute = defineJsonRoute({
|
|
366
|
+
method: 'post',
|
|
367
|
+
path: '/api/connectors/db/:collection',
|
|
368
|
+
requireSameOrigin: true,
|
|
369
|
+
parse: parseDbInsert,
|
|
370
|
+
handle: async ({ collection, record }, deps) => {
|
|
371
|
+
if (!deps.db)
|
|
372
|
+
return err(notConfiguredError('db'));
|
|
373
|
+
const result = await guardedCall(deps, 'db', 'insert', () => deps.db.insert(collection, record));
|
|
374
|
+
return result.ok ? ok({ record: result.value }) : result;
|
|
375
|
+
},
|
|
376
|
+
successStatus: 201,
|
|
377
|
+
});
|
|
378
|
+
export const connectorsDbGetRoute = defineJsonRoute({
|
|
379
|
+
method: 'get',
|
|
380
|
+
path: '/api/connectors/db/:collection/:id',
|
|
381
|
+
parse: parseDbCollectionId,
|
|
382
|
+
handle: async ({ collection, id }, deps) => {
|
|
383
|
+
if (!deps.db)
|
|
384
|
+
return err(notConfiguredError('db'));
|
|
385
|
+
const result = await guardedCall(deps, 'db', 'get', () => deps.db.get(collection, id));
|
|
386
|
+
if (!result.ok)
|
|
387
|
+
return result;
|
|
388
|
+
if (result.value === null)
|
|
389
|
+
return err(createApiError('NOT_FOUND', 'record not found'));
|
|
390
|
+
return ok({ record: result.value });
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
export const connectorsDbUpdateRoute = defineJsonRoute({
|
|
394
|
+
method: 'patch',
|
|
395
|
+
path: '/api/connectors/db/:collection/:id',
|
|
396
|
+
requireSameOrigin: true,
|
|
397
|
+
parse: parseDbUpdate,
|
|
398
|
+
handle: async ({ collection, id, patch }, deps) => {
|
|
399
|
+
if (!deps.db)
|
|
400
|
+
return err(notConfiguredError('db'));
|
|
401
|
+
const result = await guardedCall(deps, 'db', 'update', () => deps.db.update(collection, id, patch));
|
|
402
|
+
if (!result.ok)
|
|
403
|
+
return result;
|
|
404
|
+
if (result.value === null)
|
|
405
|
+
return err(createApiError('NOT_FOUND', 'record not found'));
|
|
406
|
+
return ok({ record: result.value });
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
export const connectorsDbDeleteRoute = defineJsonRoute({
|
|
410
|
+
method: 'delete',
|
|
411
|
+
path: '/api/connectors/db/:collection/:id',
|
|
412
|
+
requireSameOrigin: true,
|
|
413
|
+
parse: parseDbCollectionId,
|
|
414
|
+
handle: async ({ collection, id }, deps) => {
|
|
415
|
+
if (!deps.db)
|
|
416
|
+
return err(notConfiguredError('db'));
|
|
417
|
+
const result = await guardedCall(deps, 'db', 'delete', () => deps.db.delete(collection, id));
|
|
418
|
+
return result.ok ? ok({ ok: true }) : result;
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
export const connectorsDbQueryRoute = defineJsonRoute({
|
|
422
|
+
method: 'get',
|
|
423
|
+
path: '/api/connectors/db/:collection',
|
|
424
|
+
parse: parseDbQueryRequest,
|
|
425
|
+
handle: async ({ collection, query }, deps) => {
|
|
426
|
+
if (!deps.db)
|
|
427
|
+
return err(notConfiguredError('db'));
|
|
428
|
+
const result = await guardedCall(deps, 'db', 'query', () => deps.db.query(collection, query));
|
|
429
|
+
return result.ok ? ok({ records: result.value }) : result;
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
function parseRealtimePublish(input) {
|
|
433
|
+
const channel = input.params.channel;
|
|
434
|
+
if (typeof channel !== 'string' || channel.length === 0) {
|
|
435
|
+
return err(validationError('channel must be a non-empty path parameter'));
|
|
436
|
+
}
|
|
437
|
+
if (!isRecord(input.body) || !('event' in input.body)) {
|
|
438
|
+
return err(validationError('body must be a JSON object with an event field', [{ path: 'event', message: 'required' }]));
|
|
439
|
+
}
|
|
440
|
+
return ok({ channel, event: input.body.event });
|
|
441
|
+
}
|
|
442
|
+
export const connectorsRealtimePublishRoute = defineJsonRoute({
|
|
443
|
+
method: 'post',
|
|
444
|
+
path: '/api/connectors/realtime/:channel/publish',
|
|
445
|
+
requireSameOrigin: true,
|
|
446
|
+
parse: parseRealtimePublish,
|
|
447
|
+
handle: async ({ channel, event }, deps) => {
|
|
448
|
+
if (!deps.realtime)
|
|
449
|
+
return err(notConfiguredError('realtime'));
|
|
450
|
+
const result = await guardedCall(deps, 'realtime', 'publish', () => deps.realtime.publish(channel, event));
|
|
451
|
+
return result.ok ? ok({ ok: true }) : result;
|
|
452
|
+
},
|
|
453
|
+
});
|
|
454
|
+
/** Mounts every connectors route on `app`. A pack's `http(app, services)` calls this directly. */
|
|
455
|
+
export function registerConnectorsRoutes(app, deps, adapter) {
|
|
456
|
+
mountJsonRoute(app, connectorsAuthSignUpRoute, deps, adapter);
|
|
457
|
+
mountJsonRoute(app, connectorsAuthSignInRoute, deps, adapter);
|
|
458
|
+
mountJsonRoute(app, connectorsAuthSignOutRoute, deps, adapter);
|
|
459
|
+
mountJsonRoute(app, connectorsAuthSessionRoute, deps, adapter);
|
|
460
|
+
mountJsonRoute(app, connectorsStoragePutRoute, deps, adapter);
|
|
461
|
+
mountJsonRoute(app, connectorsStorageGetRoute, deps, adapter);
|
|
462
|
+
mountJsonRoute(app, connectorsStorageDeleteRoute, deps, adapter);
|
|
463
|
+
mountJsonRoute(app, connectorsStorageListRoute, deps, adapter);
|
|
464
|
+
mountJsonRoute(app, connectorsPaymentsChargeRoute, deps, adapter);
|
|
465
|
+
mountJsonRoute(app, connectorsPaymentsGetRoute, deps, adapter);
|
|
466
|
+
mountJsonRoute(app, connectorsPaymentsRefundRoute, deps, adapter);
|
|
467
|
+
mountJsonRoute(app, connectorsDbInsertRoute, deps, adapter);
|
|
468
|
+
mountJsonRoute(app, connectorsDbGetRoute, deps, adapter);
|
|
469
|
+
mountJsonRoute(app, connectorsDbUpdateRoute, deps, adapter);
|
|
470
|
+
mountJsonRoute(app, connectorsDbDeleteRoute, deps, adapter);
|
|
471
|
+
mountJsonRoute(app, connectorsDbQueryRoute, deps, adapter);
|
|
472
|
+
mountJsonRoute(app, connectorsRealtimePublishRoute, deps, adapter);
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=connectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectors.js","sourceRoot":"","sources":["../src/connectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module daemon-status
|
|
3
|
+
*
|
|
4
|
+
* Generic daemon status + shutdown routes, ported from an origin daemon's
|
|
5
|
+
* status/shutdown route pair — see `source-map.md`'s routes-classification
|
|
6
|
+
* table for the full origin file's MIXED verdict and exact provenance. Only
|
|
7
|
+
* the product-neutral half of that file is here: the origin's plugin-count
|
|
8
|
+
* field, a product-specific config-dir path, and a sandbox-mode flag were all
|
|
9
|
+
* dropped rather than carried over, since none of those concepts exist in the
|
|
10
|
+
* engine kernel. Everything a caller needs is injected via `DaemonStatusDeps`
|
|
11
|
+
* rather than read from globals, so this module has no dependency on any
|
|
12
|
+
* particular process/runtime wiring.
|
|
13
|
+
*/
|
|
14
|
+
import type { Express } from 'express';
|
|
15
|
+
import { type AdapterContext } from './adapter.js';
|
|
16
|
+
/**
|
|
17
|
+
* Everything the two routes below need, supplied by the caller. `requestShutdown`
|
|
18
|
+
* is a callback rather than this module calling `process.emit('SIGTERM')`
|
|
19
|
+
* directly, because whether that actually terminates the process depends on a
|
|
20
|
+
* listener the caller (not this package) is responsible for registering — see
|
|
21
|
+
* the origin file's own comment on this being a best-effort signal, not a
|
|
22
|
+
* guaranteed one.
|
|
23
|
+
*/
|
|
24
|
+
export interface DaemonStatusDeps {
|
|
25
|
+
/** Resolves the running daemon's version string. May be sync or async. */
|
|
26
|
+
getVersion: () => Promise<string> | string;
|
|
27
|
+
/** The host the daemon is bound to, echoed back verbatim. */
|
|
28
|
+
host: string;
|
|
29
|
+
/** Returns the daemon's resolved listen port. */
|
|
30
|
+
getPort: () => number;
|
|
31
|
+
/** The daemon's data directory, echoed back verbatim. */
|
|
32
|
+
dataDir: string;
|
|
33
|
+
/** Returns whether a shutdown has already been requested. */
|
|
34
|
+
isShuttingDown: () => boolean;
|
|
35
|
+
/** Invoked (after the response is sent) when a shutdown is requested. */
|
|
36
|
+
requestShutdown: () => void;
|
|
37
|
+
}
|
|
38
|
+
export interface DaemonStatusResponse {
|
|
39
|
+
ok: true;
|
|
40
|
+
version: string;
|
|
41
|
+
host: string;
|
|
42
|
+
port: number;
|
|
43
|
+
dataDir: string;
|
|
44
|
+
shuttingDown: boolean;
|
|
45
|
+
pid: number;
|
|
46
|
+
}
|
|
47
|
+
export interface DaemonShutdownResponse {
|
|
48
|
+
ok: true;
|
|
49
|
+
scheduled: true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* `GET /api/daemon/status` — an operator-detail endpoint callers can poll to read the daemon's
|
|
53
|
+
* version/host/port/data-dir/shutdown state. **Not the liveness/readiness contract** — this route
|
|
54
|
+
* has no dedicated always-open exemption in `api-security-middleware.ts`'s `OPEN_PROBE_PATHS` the
|
|
55
|
+
* way `health.ts`'s six routes do, and was never *documented* as one even though nothing here
|
|
56
|
+
* technically gated it same-origin either. A monitoring probe should poll `GET /health`/`GET
|
|
57
|
+
* /ready` (`health.ts`) instead — those are purpose-built for that job (plain liveness vs. a real,
|
|
58
|
+
* injectable readiness check) and are guaranteed reachable without a bearer token or an `Origin`
|
|
59
|
+
* header. This route is still useful for a human/CLI wanting the richer operator detail below.
|
|
60
|
+
*/
|
|
61
|
+
export declare const daemonStatusRoute: import("./types.js").JsonRouteSpec<void, DaemonStatusResponse, DaemonStatusDeps>;
|
|
62
|
+
/**
|
|
63
|
+
* `POST /api/daemon/shutdown` — schedules a graceful shutdown. Responds
|
|
64
|
+
* immediately (matching the origin's behavior) and defers the actual
|
|
65
|
+
* `requestShutdown()` call via `setImmediate` so the response has already been
|
|
66
|
+
* written before whatever the caller's shutdown callback does takes effect.
|
|
67
|
+
* Gated same-origin: this is a control-plane action, not a public read.
|
|
68
|
+
*/
|
|
69
|
+
export declare const daemonShutdownRoute: import("./types.js").JsonRouteSpec<void, DaemonShutdownResponse, DaemonStatusDeps>;
|
|
70
|
+
/** Mounts both daemon-status routes on `app`. A pack's `http(app, services)` calls this directly. */
|
|
71
|
+
export declare function registerDaemonStatusRoutes(app: Express, deps: DaemonStatusDeps, adapter: AdapterContext): void;
|
|
72
|
+
//# sourceMappingURL=daemon-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-status.d.ts","sourceRoot":"","sources":["../src/daemon-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAGpF;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC3C,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,OAAO,CAAC;IAC9B,yEAAyE;IACzE,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,IAAI,CAAC;IACT,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,kFAgB5B,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,oFAgB9B,CAAC;AAEH,qGAAqG;AACrG,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,cAAc,GACtB,IAAI,CAGN"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { defineJsonRoute, mountJsonRoute } from './adapter.js';
|
|
2
|
+
import { ok } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* `GET /api/daemon/status` — an operator-detail endpoint callers can poll to read the daemon's
|
|
5
|
+
* version/host/port/data-dir/shutdown state. **Not the liveness/readiness contract** — this route
|
|
6
|
+
* has no dedicated always-open exemption in `api-security-middleware.ts`'s `OPEN_PROBE_PATHS` the
|
|
7
|
+
* way `health.ts`'s six routes do, and was never *documented* as one even though nothing here
|
|
8
|
+
* technically gated it same-origin either. A monitoring probe should poll `GET /health`/`GET
|
|
9
|
+
* /ready` (`health.ts`) instead — those are purpose-built for that job (plain liveness vs. a real,
|
|
10
|
+
* injectable readiness check) and are guaranteed reachable without a bearer token or an `Origin`
|
|
11
|
+
* header. This route is still useful for a human/CLI wanting the richer operator detail below.
|
|
12
|
+
*/
|
|
13
|
+
export const daemonStatusRoute = defineJsonRoute({
|
|
14
|
+
method: 'get',
|
|
15
|
+
path: '/api/daemon/status',
|
|
16
|
+
parse: () => ok(undefined),
|
|
17
|
+
handle: async (_input, deps) => {
|
|
18
|
+
const version = await deps.getVersion();
|
|
19
|
+
return ok({
|
|
20
|
+
ok: true,
|
|
21
|
+
version,
|
|
22
|
+
host: deps.host,
|
|
23
|
+
port: deps.getPort(),
|
|
24
|
+
dataDir: deps.dataDir,
|
|
25
|
+
shuttingDown: deps.isShuttingDown(),
|
|
26
|
+
pid: process.pid,
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* `POST /api/daemon/shutdown` — schedules a graceful shutdown. Responds
|
|
32
|
+
* immediately (matching the origin's behavior) and defers the actual
|
|
33
|
+
* `requestShutdown()` call via `setImmediate` so the response has already been
|
|
34
|
+
* written before whatever the caller's shutdown callback does takes effect.
|
|
35
|
+
* Gated same-origin: this is a control-plane action, not a public read.
|
|
36
|
+
*/
|
|
37
|
+
export const daemonShutdownRoute = defineJsonRoute({
|
|
38
|
+
method: 'post',
|
|
39
|
+
path: '/api/daemon/shutdown',
|
|
40
|
+
requireSameOrigin: true,
|
|
41
|
+
parse: () => ok(undefined),
|
|
42
|
+
handle: (_input, deps) => {
|
|
43
|
+
setImmediate(() => {
|
|
44
|
+
try {
|
|
45
|
+
deps.requestShutdown();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Best-effort: if the caller's shutdown wiring is already gone, there's
|
|
49
|
+
// nothing left for this route to do about it.
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return ok({ ok: true, scheduled: true });
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
/** Mounts both daemon-status routes on `app`. A pack's `http(app, services)` calls this directly. */
|
|
56
|
+
export function registerDaemonStatusRoutes(app, deps, adapter) {
|
|
57
|
+
mountJsonRoute(app, daemonStatusRoute, deps, adapter);
|
|
58
|
+
mountJsonRoute(app, daemonShutdownRoute, deps, adapter);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=daemon-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-status.js","sourceRoot":"","sources":["../src/daemon-status.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAwChC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAA+C;IAC7F,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;YACR,EAAE,EAAE,IAAI;YACR,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE;YACpB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAiD;IACjG,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,sBAAsB;IAC5B,iBAAiB,EAAE,IAAI;IACvB,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;QACvB,YAAY,CAAC,GAAG,EAAE;YAChB,IAAI,CAAC;gBACH,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,wEAAwE;gBACxE,8CAA8C;YAChD,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;CACF,CAAC,CAAC;AAEH,qGAAqG;AACrG,MAAM,UAAU,0BAA0B,CACxC,GAAY,EACZ,IAAsB,EACtB,OAAuB;IAEvB,cAAc,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC"}
|