@fuzdev/fuz_app 0.118.0 → 0.120.0
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/dist/actions/CLAUDE.md +301 -73
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +16 -1
- package/dist/actions/connection_closer.d.ts +136 -51
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +133 -34
- package/dist/actions/register_action_ws.d.ts +176 -24
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +581 -241
- package/dist/actions/register_ws_endpoint.d.ts +1 -0
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +1 -0
- package/dist/actions/socket.svelte.d.ts +43 -9
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +59 -8
- package/dist/actions/transports.d.ts +55 -1
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +55 -1
- package/dist/actions/transports_ws_auth_guard.d.ts +53 -67
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +87 -111
- package/dist/actions/transports_ws_backend.d.ts +212 -30
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +327 -70
- package/dist/actions/ws_endpoint_spec.d.ts +26 -13
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +113 -32
- package/dist/auth/account_actions.d.ts +12 -18
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +47 -33
- package/dist/auth/account_routes.d.ts +5 -11
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +40 -36
- package/dist/auth/account_schema.d.ts +27 -0
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +22 -0
- package/dist/auth/admin_actions.d.ts +8 -17
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +33 -21
- package/dist/auth/api_token_queries.d.ts +23 -2
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +39 -3
- package/dist/auth/audit_emitter.d.ts +61 -38
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +57 -14
- package/dist/auth/audit_log_route_schema.js +7 -7
- package/dist/auth/audit_log_routes.d.ts +31 -6
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +85 -11
- package/dist/auth/audit_log_schema.d.ts +48 -0
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +58 -0
- package/dist/auth/cleanup.d.ts +203 -28
- package/dist/auth/cleanup.d.ts.map +1 -1
- package/dist/auth/cleanup.js +222 -26
- package/dist/auth/deps.d.ts +31 -3
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/auth/resolved_auth.d.ts +105 -0
- package/dist/auth/resolved_auth.d.ts.map +1 -0
- package/dist/auth/resolved_auth.js +124 -0
- package/dist/auth/session_middleware.d.ts +8 -1
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +9 -3
- package/dist/auth/session_queries.d.ts +31 -6
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +31 -6
- package/dist/auth/standard_rpc_actions.d.ts +9 -9
- package/dist/auth/standard_rpc_actions.d.ts.map +1 -1
- package/dist/auth/standard_rpc_actions.js +3 -3
- package/dist/db/CLAUDE.md +19 -8
- package/dist/db/fact_disk_storage.d.ts +10 -8
- package/dist/db/fact_disk_storage.d.ts.map +1 -1
- package/dist/db/fact_disk_storage.js +13 -17
- package/dist/db/fact_store.d.ts +39 -38
- package/dist/db/fact_store.d.ts.map +1 -1
- package/dist/db/fact_store.js +48 -86
- package/dist/db/file_fact_url.d.ts +6 -6
- package/dist/db/file_fact_url.js +6 -6
- package/dist/db/status.d.ts +58 -1
- package/dist/db/status.d.ts.map +1 -1
- package/dist/db/status.js +205 -77
- package/dist/http/CLAUDE.md +7 -3
- package/dist/http/db_routes.d.ts +6 -2
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +2 -2
- package/dist/periodic.d.ts +80 -0
- package/dist/periodic.d.ts.map +1 -0
- package/dist/periodic.js +122 -0
- package/dist/realtime/sse_auth_guard.d.ts +79 -49
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +103 -73
- package/dist/realtime/subscriber_registry.d.ts +119 -8
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +184 -25
- package/dist/server/app_backend.d.ts +12 -1
- package/dist/server/app_backend.d.ts.map +1 -1
- package/dist/server/app_backend.js +5 -2
- package/dist/server/app_server.d.ts +55 -15
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +41 -13
- package/dist/server/serve_fact_route.d.ts +10 -7
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +11 -8
- package/dist/testing/CLAUDE.md +140 -48
- package/dist/testing/app_server.d.ts +2 -2
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +11 -2
- package/dist/testing/audit_drift_guard.d.ts +1 -48
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +0 -42
- package/dist/testing/connection_closer_helpers.d.ts +9 -22
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +11 -17
- package/dist/testing/cross_backend/capabilities.d.ts +67 -13
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +27 -12
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +21 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +13 -4
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +4 -1
- package/dist/testing/cross_backend/session_cap.d.ts +13 -0
- package/dist/testing/cross_backend/session_cap.d.ts.map +1 -1
- package/dist/testing/cross_backend/session_cap.js +55 -19
- package/dist/testing/cross_backend/sse_round_trip.d.ts +10 -2
- package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/sse_round_trip.js +93 -26
- package/dist/testing/cross_backend/testing_server_bun.js +4 -4
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +10 -2
- package/dist/testing/cross_backend/ws_connection_cap.d.ts +35 -0
- package/dist/testing/cross_backend/ws_connection_cap.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_connection_cap.js +131 -0
- package/dist/testing/cross_backend/ws_round_trip.d.ts +2 -1
- package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +156 -19
- package/dist/testing/sse_round_trip.d.ts +6 -4
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/stubs.d.ts +1 -1
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +6 -4
- package/dist/testing/transports/sse_transport.d.ts +1 -1
- package/dist/testing/transports/ws_client.d.ts +7 -0
- package/dist/testing/transports/ws_client.d.ts.map +1 -1
- package/dist/testing/transports/ws_raw_client.d.ts +51 -0
- package/dist/testing/transports/ws_raw_client.d.ts.map +1 -0
- package/dist/testing/transports/ws_raw_client.js +156 -0
- package/dist/testing/transports/ws_transport.d.ts +28 -0
- package/dist/testing/transports/ws_transport.d.ts.map +1 -1
- package/dist/testing/transports/ws_transport.js +45 -1
- package/dist/testing/ws_round_trip.d.ts +8 -3
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +19 -4
- package/dist/ui/AdminAccounts.svelte +4 -3
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminOverview.svelte +3 -1
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
- package/dist/ui/CLAUDE.md +22 -6
- package/dist/ui/admin_accounts_state.svelte.d.ts +15 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +16 -0
- package/dist/ui/auth_state.svelte.d.ts +25 -1
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +28 -1
- package/package.json +2 -2
- package/dist/server/file_fact_fetcher.d.ts +0 -42
- package/dist/server/file_fact_fetcher.d.ts.map +0 -1
- package/dist/server/file_fact_fetcher.js +0 -60
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filesystem CAS for
|
|
2
|
+
* Filesystem CAS for fact bytes stored outside Postgres — the disk half of
|
|
3
3
|
* `PgFactStore`, threaded over the injectable `runtime/*Deps` rather than raw
|
|
4
4
|
* `node:fs`, so it runs unchanged under Node, Deno, and a mock runtime.
|
|
5
5
|
*
|
|
@@ -204,27 +204,23 @@ export const write_fact_bytes_to_disk = async (deps, facts_dir, hash, bytes) =>
|
|
|
204
204
|
return mint_file_fact_url(shard, rest);
|
|
205
205
|
};
|
|
206
206
|
/**
|
|
207
|
-
*
|
|
208
|
-
* writers above produce,
|
|
209
|
-
*
|
|
210
|
-
*
|
|
207
|
+
* Read a disk-backed fact's bytes from the `<facts_dir>/<shard>/<rest>` layout
|
|
208
|
+
* the writers above produce, addressed by the row's `file:<shard>/<rest>`
|
|
209
|
+
* `external_url`. The only read of external bytes `PgFactStore.get` performs.
|
|
210
|
+
* Does NOT verify hash content — `PgFactStore.get` calls
|
|
211
|
+
* `fact_hash_verify(hash, bytes)` on the result and returns `null` on mismatch.
|
|
211
212
|
*
|
|
212
213
|
* Defense at the read seam is the `FILE_FACT_URL_PATTERN` regex (via
|
|
213
214
|
* `parse_file_fact_url`) — `..` segments, foreign schemes, and non-hex chars
|
|
214
215
|
* fail before any disk access.
|
|
216
|
+
*
|
|
217
|
+
* @throws Error when `url` is not a `file:<shard>/<rest>` URL, or when the read fails
|
|
215
218
|
*/
|
|
216
|
-
export const
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return join(facts_dir, parsed.shard, parsed.rest);
|
|
222
|
-
};
|
|
223
|
-
return {
|
|
224
|
-
fetch_bytes: (url) => deps.read_file(resolve_path(url)),
|
|
225
|
-
// `async` funnels a synchronous `resolve_path` throw into a rejection.
|
|
226
|
-
fetch_stream: async (url) => deps.read_file_stream(resolve_path(url))
|
|
227
|
-
};
|
|
219
|
+
export const read_fact_bytes_from_disk = async (deps, facts_dir, url) => {
|
|
220
|
+
const parsed = parse_file_fact_url(url);
|
|
221
|
+
if (!parsed)
|
|
222
|
+
throw new Error('invalid file fact url');
|
|
223
|
+
return deps.read_file(join(facts_dir, parsed.shard, parsed.rest));
|
|
228
224
|
};
|
|
229
225
|
/**
|
|
230
226
|
* Reap stale temp files left under `<facts_dir>/.tmp/` by a hard crash (SIGKILL
|
package/dist/db/fact_store.d.ts
CHANGED
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
* Wraps the raw queries in `db/fact_queries.ts` with the lifecycle the
|
|
5
5
|
* `FactStore` interface promises:
|
|
6
6
|
*
|
|
7
|
-
* - sync hash on `put
|
|
8
|
-
* the caller-supplied `size`)
|
|
7
|
+
* - sync hash on `put`; `put_stream` hashes as it streams
|
|
9
8
|
* - idempotent insert (`ON CONFLICT DO NOTHING` in the queries layer)
|
|
10
9
|
* - JSON ref auto-extraction when `content_type` signals JSON and the
|
|
11
10
|
* caller didn't pass an explicit `refs` array
|
|
12
|
-
* - verify-on-read for
|
|
11
|
+
* - verify-on-read for disk-backed content; embedded reads skip verify
|
|
13
12
|
* because PG storage IS the hash table
|
|
14
|
-
* - mismatched
|
|
13
|
+
* - mismatched disk bytes return `null` + log warning (treat as
|
|
15
14
|
* unavailable; GC / repair is a separate concern)
|
|
16
15
|
*
|
|
17
16
|
* Embedded vs disk split: writes route by size. Bytes `<= embedded_threshold`
|
|
@@ -19,10 +18,20 @@
|
|
|
19
18
|
* `<facts_dir>/<shard>/<rest>` (`db/fact_disk_storage.ts`) and the row records a
|
|
20
19
|
* `file:<shard>/<rest>` `external_url`. `put` takes fully-buffered bytes;
|
|
21
20
|
* `put_stream` is the bounded-memory streaming twin (hash BLAKE3 + SHA-256 in
|
|
22
|
-
* one pass, spill past the threshold, enforce `max_bytes` / `ENOSPC`).
|
|
23
|
-
* `disk_root` + `fs` (the `runtime/*Deps`)
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* one pass, spill past the threshold, enforce `max_bytes` / `ENOSPC`). `put`
|
|
22
|
+
* needs `disk_root` + `fs` (the `runtime/*Deps`) for the over-threshold path
|
|
23
|
+
* only: without them the store has nowhere to put bytes it cannot embed, and an
|
|
24
|
+
* oversize `put` throws. `put_stream` needs `fs` for a body of any size — with
|
|
25
|
+
* none it throws before reading the stream — and `disk_root` for the
|
|
26
|
+
* over-threshold spill: with none, a body that passes the threshold throws
|
|
27
|
+
* `PayloadTooLargeError`.
|
|
28
|
+
*
|
|
29
|
+
* Every `external_url` the store writes is a `file:<shard>/<rest>` URL into its
|
|
30
|
+
* own disk CAS, and that CAS is the only place `get` reads external bytes from
|
|
31
|
+
* — the store makes no network request. The column is free text
|
|
32
|
+
* (`query_put_fact` inserts what it is given), so `get` treats a row whose
|
|
33
|
+
* `external_url` has any other shape, and any external row on a store with no
|
|
34
|
+
* disk CAS configured, as unavailable: a warning and `null`.
|
|
26
35
|
*
|
|
27
36
|
* @module
|
|
28
37
|
*/
|
|
@@ -33,13 +42,6 @@ import type { FactMeta, FactPutOptions, FactStore, PutStreamOutcome } from '@fuz
|
|
|
33
42
|
import { type FactDiskStorageDeps } from './fact_disk_storage.js';
|
|
34
43
|
/** Default embedded-vs-referenced cutoff (1 MiB). */
|
|
35
44
|
export declare const FACT_EMBEDDED_THRESHOLD_DEFAULT: number;
|
|
36
|
-
/** Fetcher abstraction so tests can stub external URL retrieval. */
|
|
37
|
-
export interface FactExternalFetcher {
|
|
38
|
-
fetch_stream: (url: string) => Promise<ReadableStream<Uint8Array>>;
|
|
39
|
-
fetch_bytes: (url: string) => Promise<Uint8Array>;
|
|
40
|
-
}
|
|
41
|
-
/** Default fetcher backed by `globalThis.fetch`. */
|
|
42
|
-
export declare const create_default_fetcher: () => FactExternalFetcher;
|
|
43
45
|
/**
|
|
44
46
|
* Construction-time deps for `PgFactStore`.
|
|
45
47
|
*
|
|
@@ -52,18 +54,19 @@ export declare const create_default_fetcher: () => FactExternalFetcher;
|
|
|
52
54
|
*
|
|
53
55
|
* `disk_root` is the facts directory backing the `<shard>/<rest>` disk CAS;
|
|
54
56
|
* `fs` supplies the filesystem capabilities (a `RuntimeDeps` satisfies it).
|
|
55
|
-
* When both are set, oversize `put` + `put_stream` write to disk and
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
57
|
+
* When both are set, oversize `put` + `put_stream` write to disk and `get`
|
|
58
|
+
* reads disk-backed facts from it. When either is unset the store writes
|
|
59
|
+
* embedded rows only and `get` returns `null` for an external row: an oversize
|
|
60
|
+
* `put` throws; `put_stream` throws for a body of any size when `fs` is unset,
|
|
61
|
+
* and with `fs` but no `disk_root` throws `PayloadTooLargeError` for a body
|
|
62
|
+
* that passes the threshold. `log` is optional — its call sites are the
|
|
63
|
+
* warnings on the paths where `get` returns `null` for an external row.
|
|
60
64
|
*/
|
|
61
65
|
export interface PgFactStoreDeps {
|
|
62
66
|
deps: QueryDeps;
|
|
63
67
|
embedded_threshold?: number;
|
|
64
68
|
disk_root?: string;
|
|
65
69
|
fs?: FactDiskStorageDeps;
|
|
66
|
-
fetcher?: FactExternalFetcher;
|
|
67
70
|
log?: Logger;
|
|
68
71
|
}
|
|
69
72
|
/**
|
|
@@ -77,8 +80,8 @@ export declare class PgFactStore implements FactStore {
|
|
|
77
80
|
* Store fully-buffered bytes, routing by size: `<= embedded_threshold` into
|
|
78
81
|
* the PG `bytes` column; larger into the disk CAS (when `disk_root` + `fs`
|
|
79
82
|
* are configured) at `<facts_dir>/<shard>/<rest>` with a `file:` URL. Oversize
|
|
80
|
-
* without a disk root throws
|
|
81
|
-
*
|
|
83
|
+
* without a disk root throws: the store has nowhere to put bytes it cannot
|
|
84
|
+
* embed. Idempotent — `ON CONFLICT DO NOTHING` + content-addressed disk
|
|
82
85
|
* filenames make a re-write a no-op.
|
|
83
86
|
*/
|
|
84
87
|
put(bytes: Uint8Array, options?: FactPutOptions): Promise<FactHash>;
|
|
@@ -101,16 +104,14 @@ export declare class PgFactStore implements FactStore {
|
|
|
101
104
|
*/
|
|
102
105
|
put_stream(stream: ReadableStream<Uint8Array>, max_bytes: number, options?: FactPutOptions): Promise<PutStreamOutcome>;
|
|
103
106
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*
|
|
112
|
-
* reads fetch + verify and return `null` (with a warning log) when
|
|
113
|
-
* the bytes don't match the stored hash.
|
|
107
|
+
* Retrieve bytes. Embedded reads return PG bytes directly. An external
|
|
108
|
+
* read comes from the disk CAS and nowhere else: the bytes at the row's
|
|
109
|
+
* `file:<shard>/<rest>` URL are read and verified against the hash.
|
|
110
|
+
*
|
|
111
|
+
* Returns `null`, with a warning log, for an external row the store cannot
|
|
112
|
+
* serve — an `external_url` that is not a `file:<shard>/<rest>` URL, no disk
|
|
113
|
+
* CAS configured (`disk_root` + `fs`), a failed disk read, or bytes that
|
|
114
|
+
* don't match the hash. Never makes a network request.
|
|
114
115
|
*/
|
|
115
116
|
get(hash: FactHash): Promise<Uint8Array | null>;
|
|
116
117
|
has(hash: FactHash): Promise<boolean>;
|
|
@@ -126,11 +127,11 @@ export declare class PgFactStore implements FactStore {
|
|
|
126
127
|
* NOT verify the fact is unreferenced — that policy lives one layer
|
|
127
128
|
* up (the orphan-fact admin surface in the consumer; a future GC walker).
|
|
128
129
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
130
|
+
* The disk file of a disk-backed fact is NOT unlinked — that is the
|
|
131
|
+
* caller's responsibility, using the returned `external_url` (when
|
|
132
|
+
* non-null): a `file:<shard>/<rest>` URL names
|
|
133
|
+
* `<disk_root>/<shard>/<rest>`. The value is the row's free text — parse
|
|
134
|
+
* it with `parse_file_fact_url` before joining a path.
|
|
134
135
|
*
|
|
135
136
|
* @returns `{size, external_url}` for the deleted row, or `null` if
|
|
136
137
|
* no row matched the hash.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_store.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fact_store.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAOtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EACX,QAAQ,EACR,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,MAAM,gCAAgC,CAAC;AAYxC,OAAO,EAIN,KAAK,mBAAmB,EACxB,MAAM,wBAAwB,CAAC;AAEhC,qDAAqD;AACrD,eAAO,MAAM,+BAA+B,QAAc,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,mBAAmB,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,qBAAa,WAAY,YAAW,SAAS;;gBAOhC,OAAO,EAAE,eAAe;IAQpC;;;;;;;OAOG;IACG,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IA+BzE;;;;;;;;;;;;;;;;OAgBG;IACG,UAAU,CACf,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,CAAC;IA6B5B;;;;;;;;;OASG;IACG,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0C/C,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAWlD,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAIxD;;;;;;;;;;;;;;;;;;OAkBG;IACG,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAG3F"}
|
package/dist/db/fact_store.js
CHANGED
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
* Wraps the raw queries in `db/fact_queries.ts` with the lifecycle the
|
|
5
5
|
* `FactStore` interface promises:
|
|
6
6
|
*
|
|
7
|
-
* - sync hash on `put
|
|
8
|
-
* the caller-supplied `size`)
|
|
7
|
+
* - sync hash on `put`; `put_stream` hashes as it streams
|
|
9
8
|
* - idempotent insert (`ON CONFLICT DO NOTHING` in the queries layer)
|
|
10
9
|
* - JSON ref auto-extraction when `content_type` signals JSON and the
|
|
11
10
|
* caller didn't pass an explicit `refs` array
|
|
12
|
-
* - verify-on-read for
|
|
11
|
+
* - verify-on-read for disk-backed content; embedded reads skip verify
|
|
13
12
|
* because PG storage IS the hash table
|
|
14
|
-
* - mismatched
|
|
13
|
+
* - mismatched disk bytes return `null` + log warning (treat as
|
|
15
14
|
* unavailable; GC / repair is a separate concern)
|
|
16
15
|
*
|
|
17
16
|
* Embedded vs disk split: writes route by size. Bytes `<= embedded_threshold`
|
|
@@ -19,39 +18,30 @@
|
|
|
19
18
|
* `<facts_dir>/<shard>/<rest>` (`db/fact_disk_storage.ts`) and the row records a
|
|
20
19
|
* `file:<shard>/<rest>` `external_url`. `put` takes fully-buffered bytes;
|
|
21
20
|
* `put_stream` is the bounded-memory streaming twin (hash BLAKE3 + SHA-256 in
|
|
22
|
-
* one pass, spill past the threshold, enforce `max_bytes` / `ENOSPC`).
|
|
23
|
-
* `disk_root` + `fs` (the `runtime/*Deps`)
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* one pass, spill past the threshold, enforce `max_bytes` / `ENOSPC`). `put`
|
|
22
|
+
* needs `disk_root` + `fs` (the `runtime/*Deps`) for the over-threshold path
|
|
23
|
+
* only: without them the store has nowhere to put bytes it cannot embed, and an
|
|
24
|
+
* oversize `put` throws. `put_stream` needs `fs` for a body of any size — with
|
|
25
|
+
* none it throws before reading the stream — and `disk_root` for the
|
|
26
|
+
* over-threshold spill: with none, a body that passes the threshold throws
|
|
27
|
+
* `PayloadTooLargeError`.
|
|
28
|
+
*
|
|
29
|
+
* Every `external_url` the store writes is a `file:<shard>/<rest>` URL into its
|
|
30
|
+
* own disk CAS, and that CAS is the only place `get` reads external bytes from
|
|
31
|
+
* — the store makes no network request. The column is free text
|
|
32
|
+
* (`query_put_fact` inserts what it is given), so `get` treats a row whose
|
|
33
|
+
* `external_url` has any other shape, and any external row on a store with no
|
|
34
|
+
* disk CAS configured, as unavailable: a warning and `null`.
|
|
26
35
|
*
|
|
27
36
|
* @module
|
|
28
37
|
*/
|
|
29
38
|
import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
30
|
-
import { fact_hash_bytes,
|
|
39
|
+
import { fact_hash_bytes, fact_hash_verify, fact_hash_extract_refs } from '@fuzdev/fuz_util/fact_hash.ts';
|
|
31
40
|
import { query_delete_fact, query_get_fact, query_get_fact_meta, query_get_fact_refs, query_has_fact, query_put_fact, query_put_fact_refs } from './fact_queries.js';
|
|
32
|
-
import {
|
|
41
|
+
import { is_file_fact_url } from './file_fact_url.js';
|
|
42
|
+
import { read_fact_bytes_from_disk, stream_fact_to_disk, write_fact_bytes_to_disk } from './fact_disk_storage.js';
|
|
33
43
|
/** Default embedded-vs-referenced cutoff (1 MiB). */
|
|
34
44
|
export const FACT_EMBEDDED_THRESHOLD_DEFAULT = 1024 * 1024;
|
|
35
|
-
/** Default fetcher backed by `globalThis.fetch`. */
|
|
36
|
-
export const create_default_fetcher = () => ({
|
|
37
|
-
fetch_stream: async (url) => {
|
|
38
|
-
const response = await fetch(url);
|
|
39
|
-
if (!response.ok) {
|
|
40
|
-
throw new Error(`fact fetch failed: ${response.status} ${url}`);
|
|
41
|
-
}
|
|
42
|
-
if (!response.body) {
|
|
43
|
-
throw new Error(`fact fetch returned no body: ${url}`);
|
|
44
|
-
}
|
|
45
|
-
return response.body;
|
|
46
|
-
},
|
|
47
|
-
fetch_bytes: async (url) => {
|
|
48
|
-
const response = await fetch(url);
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
throw new Error(`fact fetch failed: ${response.status} ${url}`);
|
|
51
|
-
}
|
|
52
|
-
return new Uint8Array(await response.arrayBuffer());
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
45
|
/**
|
|
56
46
|
* PG-backed `FactStore`. Delegates to `db/fact_queries.ts` for I/O and adds
|
|
57
47
|
* the lifecycle layer described in the module doc.
|
|
@@ -61,26 +51,20 @@ export class PgFactStore {
|
|
|
61
51
|
#embedded_threshold;
|
|
62
52
|
#disk_root;
|
|
63
53
|
#fs;
|
|
64
|
-
#fetcher;
|
|
65
54
|
#log;
|
|
66
55
|
constructor(options) {
|
|
67
56
|
this.#deps = options.deps;
|
|
68
57
|
this.#embedded_threshold = options.embedded_threshold ?? FACT_EMBEDDED_THRESHOLD_DEFAULT;
|
|
69
58
|
this.#disk_root = options.disk_root;
|
|
70
59
|
this.#fs = options.fs;
|
|
71
|
-
this.#fetcher =
|
|
72
|
-
options.fetcher ??
|
|
73
|
-
(options.disk_root !== undefined && options.fs !== undefined
|
|
74
|
-
? create_disk_fact_fetcher(options.fs, options.disk_root)
|
|
75
|
-
: create_default_fetcher());
|
|
76
60
|
this.#log = options.log;
|
|
77
61
|
}
|
|
78
62
|
/**
|
|
79
63
|
* Store fully-buffered bytes, routing by size: `<= embedded_threshold` into
|
|
80
64
|
* the PG `bytes` column; larger into the disk CAS (when `disk_root` + `fs`
|
|
81
65
|
* are configured) at `<facts_dir>/<shard>/<rest>` with a `file:` URL. Oversize
|
|
82
|
-
* without a disk root throws
|
|
83
|
-
*
|
|
66
|
+
* without a disk root throws: the store has nowhere to put bytes it cannot
|
|
67
|
+
* embed. Idempotent — `ON CONFLICT DO NOTHING` + content-addressed disk
|
|
84
68
|
* filenames make a re-write a no-op.
|
|
85
69
|
*/
|
|
86
70
|
async put(bytes, options) {
|
|
@@ -89,7 +73,7 @@ export class PgFactStore {
|
|
|
89
73
|
let row_external_url;
|
|
90
74
|
if (bytes.length > this.#embedded_threshold) {
|
|
91
75
|
if (this.#disk_root === undefined || this.#fs === undefined) {
|
|
92
|
-
throw new Error(`fact bytes exceed embedded threshold (${bytes.length} > ${this.#embedded_threshold});
|
|
76
|
+
throw new Error(`fact bytes exceed embedded threshold (${bytes.length} > ${this.#embedded_threshold}) and no disk CAS is configured; set disk_root and fs to store them on disk`);
|
|
93
77
|
}
|
|
94
78
|
row_bytes = null;
|
|
95
79
|
row_external_url = await write_fact_bytes_to_disk(this.#fs, this.#disk_root, hash, bytes);
|
|
@@ -147,33 +131,14 @@ export class PgFactStore {
|
|
|
147
131
|
return { hash: streamed.hash, sha256: streamed.sha256, size: streamed.size };
|
|
148
132
|
}
|
|
149
133
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (byte_count !== size) {
|
|
159
|
-
throw new Error(`fact size mismatch for ${url}: caller declared ${size}, streamed ${byte_count}`);
|
|
160
|
-
}
|
|
161
|
-
const inserted = await query_put_fact(this.#deps, {
|
|
162
|
-
hash,
|
|
163
|
-
bytes: null,
|
|
164
|
-
external_url: url,
|
|
165
|
-
content_type: options?.content_type ?? null,
|
|
166
|
-
size
|
|
167
|
-
});
|
|
168
|
-
if (inserted && options?.refs && options.refs.length > 0) {
|
|
169
|
-
await query_put_fact_refs(this.#deps, hash, options.refs);
|
|
170
|
-
}
|
|
171
|
-
return hash;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Retrieve bytes. Embedded reads return PG bytes directly; external
|
|
175
|
-
* reads fetch + verify and return `null` (with a warning log) when
|
|
176
|
-
* the bytes don't match the stored hash.
|
|
134
|
+
* Retrieve bytes. Embedded reads return PG bytes directly. An external
|
|
135
|
+
* read comes from the disk CAS and nowhere else: the bytes at the row's
|
|
136
|
+
* `file:<shard>/<rest>` URL are read and verified against the hash.
|
|
137
|
+
*
|
|
138
|
+
* Returns `null`, with a warning log, for an external row the store cannot
|
|
139
|
+
* serve — an `external_url` that is not a `file:<shard>/<rest>` URL, no disk
|
|
140
|
+
* CAS configured (`disk_root` + `fs`), a failed disk read, or bytes that
|
|
141
|
+
* don't match the hash. Never makes a network request.
|
|
177
142
|
*/
|
|
178
143
|
async get(hash) {
|
|
179
144
|
const row = await query_get_fact(this.#deps, hash);
|
|
@@ -185,12 +150,22 @@ export class PgFactStore {
|
|
|
185
150
|
if (row.external_url === null) {
|
|
186
151
|
return null;
|
|
187
152
|
}
|
|
153
|
+
// the URL is not echoed — the column is free text, so its shape and
|
|
154
|
+
// length are whatever the row's writer chose
|
|
155
|
+
if (!is_file_fact_url(row.external_url)) {
|
|
156
|
+
this.#log?.warn(`PgFactStore.get external_url for ${hash} is not a file:<shard>/<rest> URL; treating as not-found`);
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (this.#disk_root === undefined || this.#fs === undefined) {
|
|
160
|
+
this.#log?.warn(`PgFactStore.get ${hash} is disk-backed and no disk CAS is configured (disk_root + fs); treating as not-found`);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
188
163
|
let bytes;
|
|
189
164
|
try {
|
|
190
|
-
bytes = await this.#
|
|
165
|
+
bytes = await read_fact_bytes_from_disk(this.#fs, this.#disk_root, row.external_url);
|
|
191
166
|
}
|
|
192
167
|
catch (err) {
|
|
193
|
-
this.#log?.warn(`PgFactStore.get
|
|
168
|
+
this.#log?.warn(`PgFactStore.get disk read failed for ${hash} at ${row.external_url}:`, to_error_message(err));
|
|
194
169
|
return null;
|
|
195
170
|
}
|
|
196
171
|
if (!fact_hash_verify(hash, bytes)) {
|
|
@@ -226,11 +201,11 @@ export class PgFactStore {
|
|
|
226
201
|
* NOT verify the fact is unreferenced — that policy lives one layer
|
|
227
202
|
* up (the orphan-fact admin surface in the consumer; a future GC walker).
|
|
228
203
|
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
204
|
+
* The disk file of a disk-backed fact is NOT unlinked — that is the
|
|
205
|
+
* caller's responsibility, using the returned `external_url` (when
|
|
206
|
+
* non-null): a `file:<shard>/<rest>` URL names
|
|
207
|
+
* `<disk_root>/<shard>/<rest>`. The value is the row's free text — parse
|
|
208
|
+
* it with `parse_file_fact_url` before joining a path.
|
|
234
209
|
*
|
|
235
210
|
* @returns `{size, external_url}` for the deleted row, or `null` if
|
|
236
211
|
* no row matched the hash.
|
|
@@ -260,19 +235,6 @@ const resolve_refs = (bytes, options) => {
|
|
|
260
235
|
}
|
|
261
236
|
return fact_hash_extract_refs(value);
|
|
262
237
|
};
|
|
263
|
-
/** Hash a stream while counting bytes. Lets `put_ref` verify size in one pass. */
|
|
264
|
-
const hash_counted_stream = async (stream) => {
|
|
265
|
-
let byte_count = 0;
|
|
266
|
-
const counting = new TransformStream({
|
|
267
|
-
transform(chunk, controller) {
|
|
268
|
-
byte_count += chunk.length;
|
|
269
|
-
controller.enqueue(chunk);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
const piped = stream.pipeThrough(counting);
|
|
273
|
-
const hash = await fact_hash_stream(piped);
|
|
274
|
-
return { hash, byte_count };
|
|
275
|
-
};
|
|
276
238
|
/**
|
|
277
239
|
* Coerce whatever the driver returns for BYTEA into a `Uint8Array`.
|
|
278
240
|
*
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Canonical filesystem-fact URL shape + on-disk layout.
|
|
3
3
|
*
|
|
4
|
-
* `external_url` on the
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
4
|
+
* `external_url` on the `fact` row is free text (`string | null`), but the
|
|
5
|
+
* only shape `PgFactStore` writes, reads, or serves is the filesystem-minted
|
|
6
|
+
* one — any other reads as unavailable. Those URLs are exactly
|
|
7
7
|
* `file:<shard>/<rest>` where `<shard>` is the first 2 hex chars of the
|
|
8
8
|
* blake3 digest and `<rest>` the remaining 62 — files land at
|
|
9
9
|
* `<facts_dir>/<shard>/<rest>` after the writer atomically temp+renames
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Centralizing the regex + the `fact_disk_path` split keeps the shape in one
|
|
13
13
|
* place: `PgFactStore`'s disk CAS (`db/fact_disk_storage.ts`), the
|
|
14
|
-
* `serve_fact_route` defense-in-depth check, and the
|
|
15
|
-
*
|
|
16
|
-
* can't drift. The TS twin of the Rust `fact_disk_path` (`fuz_fact`).
|
|
14
|
+
* `serve_fact_route` defense-in-depth check, and the disk read
|
|
15
|
+
* (`read_fact_bytes_from_disk`) all derive the layout here, so the write path
|
|
16
|
+
* and the read path can't drift. The TS twin of the Rust `fact_disk_path` (`fuz_fact`).
|
|
17
17
|
*
|
|
18
18
|
* Defense-in-depth: a `..` segment can't match (`.` isn't in `[0-9a-f]`),
|
|
19
19
|
* neither can absolute paths, query strings, or any non-hex character.
|
package/dist/db/file_fact_url.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Canonical filesystem-fact URL shape + on-disk layout.
|
|
3
3
|
*
|
|
4
|
-
* `external_url` on the
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
4
|
+
* `external_url` on the `fact` row is free text (`string | null`), but the
|
|
5
|
+
* only shape `PgFactStore` writes, reads, or serves is the filesystem-minted
|
|
6
|
+
* one — any other reads as unavailable. Those URLs are exactly
|
|
7
7
|
* `file:<shard>/<rest>` where `<shard>` is the first 2 hex chars of the
|
|
8
8
|
* blake3 digest and `<rest>` the remaining 62 — files land at
|
|
9
9
|
* `<facts_dir>/<shard>/<rest>` after the writer atomically temp+renames
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Centralizing the regex + the `fact_disk_path` split keeps the shape in one
|
|
13
13
|
* place: `PgFactStore`'s disk CAS (`db/fact_disk_storage.ts`), the
|
|
14
|
-
* `serve_fact_route` defense-in-depth check, and the
|
|
15
|
-
*
|
|
16
|
-
* can't drift. The TS twin of the Rust `fact_disk_path` (`fuz_fact`).
|
|
14
|
+
* `serve_fact_route` defense-in-depth check, and the disk read
|
|
15
|
+
* (`read_fact_bytes_from_disk`) all derive the layout here, so the write path
|
|
16
|
+
* and the read path can't drift. The TS twin of the Rust `fact_disk_path` (`fuz_fact`).
|
|
17
17
|
*
|
|
18
18
|
* Defense-in-depth: a `..` segment can't match (`.` isn't in `[0-9a-f]`),
|
|
19
19
|
* neither can absolute paths, query strings, or any non-hex character.
|
package/dist/db/status.d.ts
CHANGED
|
@@ -97,10 +97,67 @@ export interface DbStatus {
|
|
|
97
97
|
*/
|
|
98
98
|
export declare const query_db_status: (db: Db, namespaces?: Array<MigrationNamespace>) => Promise<DbStatus>;
|
|
99
99
|
/**
|
|
100
|
-
* Format a `DbStatus` as
|
|
100
|
+
* Format a `DbStatus` as the body of the human-facing operator report.
|
|
101
|
+
*
|
|
102
|
+
* A `tables:` count with one aligned `name N rows` line per table, then a
|
|
103
|
+
* `migrations:` header (always printed, even with no namespaces) and one
|
|
104
|
+
* aligned line per namespace: its state (`up-to-date`, `PENDING <n>`, or
|
|
105
|
+
* `DIVERGED`), `applied/declared`, and the latest applied name (`(none)` when
|
|
106
|
+
* nothing is applied). A diverged namespace adds a `diverged:` line, a pending
|
|
107
|
+
* one a `pending:` line naming the tail. A failed connection renders the single
|
|
108
|
+
* line `connection: FAILED (<error>)`. Every line ends in a newline.
|
|
109
|
+
*
|
|
110
|
+
* The body only — the `database status` / `url:` header belongs to the CLI
|
|
111
|
+
* script, which holds the URL a `DbStatus` never sees. For a connected status
|
|
112
|
+
* the output is byte-identical with the Rust twin's `format_db_status`; both
|
|
113
|
+
* test suites pin the same fixture report.
|
|
101
114
|
*
|
|
102
115
|
* @param status - the status to format
|
|
103
116
|
* @returns multi-line string suitable for console output
|
|
104
117
|
*/
|
|
105
118
|
export declare const format_db_status: (status: DbStatus) => string;
|
|
119
|
+
/**
|
|
120
|
+
* Render a database URL for printing from the parse node-postgres dials —
|
|
121
|
+
* `new URL`, with pg-connection-string's precedence, where a `user`, `host`, or
|
|
122
|
+
* `port` query parameter overrides the URL's own — so the line names the server
|
|
123
|
+
* dialed and no credential can leak however the input spells it.
|
|
124
|
+
*
|
|
125
|
+
* A `postgres://` or `postgresql://` URL renders as
|
|
126
|
+
* `postgres://[user@]host:port[/dbname]`: never the password, and never the
|
|
127
|
+
* query or fragment (`sslmode` and the like are dropped by design). The scheme
|
|
128
|
+
* always prints as `postgres://`. The port always prints, `5432` when the URL
|
|
129
|
+
* names none. The user and database name print percent-encoded with
|
|
130
|
+
* `encodeURIComponent`, so no control character, escape sequence, or bidi
|
|
131
|
+
* override reaches the terminal and an `@` can't pose as the separator; each
|
|
132
|
+
* prints only when non-empty. An IP-literal host prints canonically (IPv6
|
|
133
|
+
* bracketed); a Unix-socket directory prints with each `/` as `%2F`. A PGlite
|
|
134
|
+
* `file://` or `memory://` URL prints as scheme, host, and path.
|
|
135
|
+
*
|
|
136
|
+
* The whole line is `(not a URL; hidden)` for any other scheme, when `new URL`
|
|
137
|
+
* rejects the input, when it holds a malformed percent-escape (`%ZZ`), when
|
|
138
|
+
* there is no host, when the host is neither an IP literal, a hostname of
|
|
139
|
+
* `A-Z a-z 0-9 . _ -`, nor a socket directory of those characters and `/`, when
|
|
140
|
+
* the user holds `?`, `=`, `&`, `/`, or `#`, or when the port isn't a number up
|
|
141
|
+
* to 65535. The host and user rules match the Rust twin's, where they catch
|
|
142
|
+
* tokio-postgres's split at the first `@`.
|
|
143
|
+
*
|
|
144
|
+
* Twin of the Rust `fuz_db` CLI's `display_db_url`, byte-identical on the URLs
|
|
145
|
+
* both drivers read alike. They part where the drivers do: a `host=` or `port=`
|
|
146
|
+
* query parameter overrides the URL's here (tokio-postgres appends it to a list
|
|
147
|
+
* whose first entry the pool dials); a `dbname=` query parameter, which
|
|
148
|
+
* tokio-postgres honours and node-postgres ignores, and a `#…` fragment, which
|
|
149
|
+
* tokio-postgres keeps as part of the database name; tokio-postgres also
|
|
150
|
+
* accepts `key=value` strings, host lists, and an unencoded `/` or `?` in the
|
|
151
|
+
* password (here, the placeholder); an unencoded `@` in the userinfo splits at
|
|
152
|
+
* the last `@` here, rendering the user and host node-postgres dials, where the
|
|
153
|
+
* Rust twin prints the placeholder; node-postgres decodes the database name
|
|
154
|
+
* with `decodeURI`, so a reserved-character escape such as `%2F` stays literal
|
|
155
|
+
* and prints as `%252F`; an IPv4-mapped IPv6 address serializes differently;
|
|
156
|
+
* and tokio-postgres refuses an unknown query parameter (`sslpassword=`) that
|
|
157
|
+
* node-postgres passes.
|
|
158
|
+
*
|
|
159
|
+
* @param url - the database URL
|
|
160
|
+
* @returns the URL without its password, query, or fragment, or the placeholder
|
|
161
|
+
*/
|
|
162
|
+
export declare const display_db_url: (url: string) => string;
|
|
106
163
|
//# sourceMappingURL=status.d.ts.map
|
package/dist/db/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GACnB;IACA,mEAAmE;IACnE,IAAI,EAAE,eAAe,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,kEAAkE;IAClE,IAAI,EAAE,cAAc,CAAC;IACrB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAChB,CAAC;AAEL;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3B,sCAAsC;IACtC,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GACnB;IACA,mEAAmE;IACnE,IAAI,EAAE,eAAe,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,kEAAkE;IAClE,IAAI,EAAE,cAAc,CAAC;IACrB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAChB,CAAC;AAEL;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACxB,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3B,sCAAsC;IACtC,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;CACnC;AA6DD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAC3B,IAAI,EAAE,EACN,aAAa,KAAK,CAAC,kBAAkB,CAAC,KACpC,OAAO,CAAC,QAAQ,CA2DlB,CAAC;AA0BF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,QAAQ,KAAG,MAmCnD,CAAC;AA8BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAoC5C,CAAC"}
|