@fuzdev/fuz_app 0.111.0 → 0.113.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 +15 -11
- package/dist/actions/action_rpc.d.ts +1 -1
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +4 -6
- package/dist/actions/peer_ping.d.ts +8 -0
- package/dist/actions/peer_ping.d.ts.map +1 -1
- package/dist/actions/peer_ping.js +8 -0
- package/dist/actions/peer_request.d.ts +1 -1
- package/dist/actions/peer_request.js +1 -1
- package/dist/actions/perform_action.d.ts +16 -9
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +30 -21
- package/dist/actions/register_action_ws.d.ts +1 -1
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +88 -21
- package/dist/auth/CLAUDE.md +43 -8
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +10 -1
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +36 -16
- package/dist/auth/account_schema.d.ts +20 -0
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +22 -1
- package/dist/auth/actor_search_actions.d.ts +3 -3
- package/dist/auth/actor_search_actions.d.ts.map +1 -1
- package/dist/auth/actor_search_actions.js +10 -6
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +11 -5
- package/dist/auth/app_settings_queries.d.ts.map +1 -1
- package/dist/auth/app_settings_queries.js +6 -4
- package/dist/auth/audit_log_queries.d.ts +6 -0
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +11 -5
- package/dist/auth/audit_log_route_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_route_schema.js +12 -1
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +3 -8
- package/dist/auth/cell_audit_actions.d.ts.map +1 -1
- package/dist/auth/cell_audit_actions.js +1 -1
- package/dist/auth/cell_field_actions.js +1 -1
- package/dist/auth/cell_grant_actions.js +1 -1
- package/dist/auth/cell_item_actions.js +1 -1
- package/dist/auth/invite_queries.d.ts.map +1 -1
- package/dist/auth/invite_queries.js +10 -8
- package/dist/auth/role_grant_offer_action_specs.d.ts +2 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +2 -1
- package/dist/auth/role_grant_offer_ddl.d.ts +11 -0
- package/dist/auth/role_grant_offer_ddl.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_ddl.js +20 -2
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +29 -15
- package/dist/auth/role_grant_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_queries.js +21 -7
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +9 -4
- package/dist/db/CLAUDE.md +21 -2
- package/dist/db/cell_audit_queries.js +2 -2
- package/dist/db/cell_field_queries.d.ts +1 -1
- package/dist/db/cell_field_queries.d.ts.map +1 -1
- package/dist/db/cell_field_queries.js +8 -6
- package/dist/db/cell_grant_queries.d.ts +1 -1
- package/dist/db/cell_grant_queries.d.ts.map +1 -1
- package/dist/db/cell_grant_queries.js +12 -10
- package/dist/db/cell_item_queries.d.ts +1 -1
- package/dist/db/cell_item_queries.d.ts.map +1 -1
- package/dist/db/cell_item_queries.js +9 -7
- package/dist/db/cell_queries.d.ts +3 -3
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +6 -4
- package/dist/db/fact_disk_storage.js +1 -1
- package/dist/db/fact_queries.d.ts.map +1 -1
- package/dist/db/fact_queries.js +9 -3
- package/dist/db/sql_columns.d.ts +80 -3
- package/dist/db/sql_columns.d.ts.map +1 -1
- package/dist/db/sql_columns.js +91 -4
- package/dist/http/CLAUDE.md +6 -4
- package/dist/http/auth_shape.d.ts +19 -6
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +19 -6
- package/dist/http/jsonrpc_helpers.d.ts +13 -0
- package/dist/http/jsonrpc_helpers.d.ts.map +1 -1
- package/dist/http/jsonrpc_helpers.js +13 -0
- package/dist/http/surface_query.d.ts +29 -4
- package/dist/http/surface_query.d.ts.map +1 -1
- package/dist/http/surface_query.js +30 -5
- package/dist/realtime/sse_auth_guard.d.ts +9 -3
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +9 -3
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +7 -2
- package/dist/testing/CLAUDE.md +54 -28
- package/dist/testing/admin_integration.d.ts +0 -3
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +0 -1
- package/dist/testing/adversarial_404.d.ts.map +1 -1
- package/dist/testing/adversarial_404.js +4 -1
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +5 -4
- package/dist/testing/app_server.d.ts +4 -3
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +11 -5
- package/dist/testing/attack_surface.d.ts +21 -2
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +78 -27
- package/dist/testing/audit_completeness.d.ts +0 -3
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +0 -1
- package/dist/testing/auth_apps.d.ts +34 -2
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +43 -7
- package/dist/testing/cross_backend/account_lifecycle.d.ts +5 -4
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +7 -0
- package/dist/testing/cross_backend/action_manifest.d.ts +19 -3
- package/dist/testing/cross_backend/action_manifest.d.ts.map +1 -1
- package/dist/testing/cross_backend/action_manifest.js +10 -4
- package/dist/testing/cross_backend/action_manifest_parity.d.ts +9 -3
- package/dist/testing/cross_backend/action_manifest_parity.d.ts.map +1 -1
- package/dist/testing/cross_backend/action_manifest_parity.js +6 -0
- package/dist/testing/cross_backend/actor_lookup.d.ts +3 -2
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.d.ts +4 -2
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +1 -1
- package/dist/testing/cross_backend/cell_crud.d.ts +2 -2
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +10 -0
- package/dist/testing/cross_backend/cell_gated_create.d.ts +3 -3
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_grant_role.d.ts +2 -2
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.d.ts +2 -2
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.d.ts +2 -2
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/make_cross_backend_project.d.ts +17 -2
- package/dist/testing/cross_backend/make_cross_backend_project.d.ts.map +1 -1
- package/dist/testing/cross_backend/make_cross_backend_project.js +23 -3
- package/dist/testing/cross_backend/origin.d.ts +4 -2
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.js +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.js +11 -7
- package/dist/testing/cross_backend/query_shape.d.ts +6 -5
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/ready.d.ts +2 -2
- package/dist/testing/cross_backend/ready.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_enumeration.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_enumeration.js +7 -1
- package/dist/testing/cross_backend/setup.d.ts +26 -6
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/standard.d.ts +5 -1
- package/dist/testing/cross_backend/standard.d.ts.map +1 -1
- package/dist/testing/cross_backend/standard.js +1 -5
- package/dist/testing/cross_backend/testing_backdoor.js +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +5 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +3 -2
- package/dist/testing/cross_backend/token_lifetime.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_lifetime.js +6 -0
- package/dist/testing/cross_backend/token_scope_surface.d.ts +2 -2
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +36 -7
- package/dist/testing/cross_backend/wire_shapes.d.ts +22 -0
- package/dist/testing/cross_backend/wire_shapes.d.ts.map +1 -0
- package/dist/testing/cross_backend/wire_shapes.js +41 -0
- package/dist/testing/data_exposure.d.ts +0 -3
- package/dist/testing/data_exposure.d.ts.map +1 -1
- package/dist/testing/data_exposure.js +0 -1
- package/dist/testing/db.d.ts +44 -7
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +62 -27
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +15 -2
- package/dist/testing/round_trip.d.ts +0 -3
- package/dist/testing/round_trip.d.ts.map +1 -1
- package/dist/testing/round_trip.js +0 -4
- package/dist/testing/rpc_attack_surface.js +2 -2
- package/dist/testing/rpc_round_trip.d.ts +0 -3
- package/dist/testing/rpc_round_trip.d.ts.map +1 -1
- package/dist/testing/rpc_round_trip.js +0 -1
- package/dist/testing/schema_generators.d.ts +15 -0
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +45 -11
- package/dist/testing/standard.d.ts +5 -1
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +2 -7
- package/dist/testing/surface_invariants.d.ts +7 -1
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +11 -5
- package/dist/timestamp.d.ts +58 -0
- package/dist/timestamp.d.ts.map +1 -0
- package/dist/timestamp.js +57 -0
- package/dist/ui/AdminAccounts.svelte +6 -4
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminInvites.svelte +3 -3
- package/dist/ui/AdminInvites.svelte.d.ts.map +1 -1
- package/dist/ui/AdminOverview.svelte +10 -10
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
- package/dist/ui/AdminRoleGrantHistory.svelte +7 -7
- package/dist/ui/AdminRoleGrantHistory.svelte.d.ts.map +1 -1
- package/dist/ui/AdminSettings.svelte +1 -1
- package/dist/ui/RoleGrantOfferHistory.svelte +3 -1
- package/dist/ui/RoleGrantOfferHistory.svelte.d.ts.map +1 -1
- package/dist/ui/RoleGrantOfferInbox.svelte +4 -1
- package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -1
- package/dist/ui/SurfaceExplorer.svelte +33 -17
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -1
- package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -1
- package/dist/ui/role_grant_offers_state.svelte.js +6 -2
- package/package.json +10 -10
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { hash_blake3 } from '@fuzdev/fuz_util/hash_blake3.ts';
|
|
10
10
|
import { generate_random_base64url } from '../crypto.js';
|
|
11
|
-
import { columns_sql, qualify_columns } from '../db/sql_columns.js';
|
|
11
|
+
import { columns_sql, iso8601_timestamp_expr, qualify_columns } from '../db/sql_columns.js';
|
|
12
12
|
/**
|
|
13
13
|
* Session lifetime in milliseconds (30 days).
|
|
14
14
|
*
|
|
@@ -70,6 +70,11 @@ export const AUTH_SESSION_COLUMNS = [
|
|
|
70
70
|
'created_at',
|
|
71
71
|
'expires_at'
|
|
72
72
|
];
|
|
73
|
+
/** The `auth_session` timestamp override, by row qualifier (`''` bare, `s` for the admin listing's JOIN). */
|
|
74
|
+
const auth_session_expr = iso8601_timestamp_expr(AUTH_SESSION_COLUMNS, [
|
|
75
|
+
'created_at',
|
|
76
|
+
'expires_at'
|
|
77
|
+
]);
|
|
73
78
|
/**
|
|
74
79
|
* Get a session if it exists, is not expired, and has not been revoked.
|
|
75
80
|
*
|
|
@@ -77,7 +82,7 @@ export const AUTH_SESSION_COLUMNS = [
|
|
|
77
82
|
* @param token_hash - blake3 hash of the session token
|
|
78
83
|
*/
|
|
79
84
|
export const query_session_get_valid = async (deps, token_hash) => {
|
|
80
|
-
return deps.db.query_one(`SELECT ${columns_sql(AUTH_SESSION_COLUMNS)} FROM auth_session WHERE id = $1 AND expires_at > NOW()`, [token_hash]);
|
|
85
|
+
return deps.db.query_one(`SELECT ${columns_sql(AUTH_SESSION_COLUMNS, auth_session_expr(''))} FROM auth_session WHERE id = $1 AND expires_at > NOW()`, [token_hash]);
|
|
81
86
|
};
|
|
82
87
|
/**
|
|
83
88
|
* Revoke (delete) a session by its token hash, with no account scoping.
|
|
@@ -123,7 +128,7 @@ export const query_session_revoke_all_for_account = async (deps, account_id) =>
|
|
|
123
128
|
* List sessions for an account, newest first.
|
|
124
129
|
*/
|
|
125
130
|
export const query_session_list_for_account = async (deps, account_id, limit = 50) => {
|
|
126
|
-
return deps.db.query(`SELECT ${columns_sql(AUTH_SESSION_COLUMNS)} FROM auth_session WHERE account_id = $1 ORDER BY created_at DESC LIMIT $2`, [account_id, limit]);
|
|
131
|
+
return deps.db.query(`SELECT ${columns_sql(AUTH_SESSION_COLUMNS, auth_session_expr(''))} FROM auth_session WHERE account_id = $1 ORDER BY auth_session.created_at DESC LIMIT $2`, [account_id, limit]);
|
|
127
132
|
};
|
|
128
133
|
/**
|
|
129
134
|
* Enforce a per-account session limit by evicting the oldest sessions.
|
|
@@ -187,7 +192,7 @@ export const query_session_enforce_limit = async (deps, account_id, max_sessions
|
|
|
187
192
|
* @returns active sessions joined with account usernames, newest first
|
|
188
193
|
*/
|
|
189
194
|
export const query_session_list_all_active = async (deps, limit = 200) => {
|
|
190
|
-
return deps.db.query(`SELECT ${qualify_columns(AUTH_SESSION_COLUMNS, 's')}, a.username
|
|
195
|
+
return deps.db.query(`SELECT ${qualify_columns(AUTH_SESSION_COLUMNS, 's', auth_session_expr('s'))}, a.username
|
|
191
196
|
FROM auth_session s
|
|
192
197
|
JOIN account a ON a.id = s.account_id
|
|
193
198
|
WHERE s.expires_at > NOW()
|
package/dist/db/CLAUDE.md
CHANGED
|
@@ -30,7 +30,26 @@ the code.
|
|
|
30
30
|
- `sql_columns.ts` — `columns_sql` / `qualify_columns` / `omit_columns`,
|
|
31
31
|
the derivation helpers every `*_COLUMNS` projection const's variants
|
|
32
32
|
(alias-qualified JOIN reads, the client-safe `minus token_hash` listing)
|
|
33
|
-
are built from, so the drift guard on the base const covers them.
|
|
33
|
+
are built from, so the drift guard on the base const covers them. Both
|
|
34
|
+
renderers take an optional `ColumnExpr` — a per-column expression
|
|
35
|
+
override, twin of the third argument to `fuz_db::qualify_columns` — and
|
|
36
|
+
alias an overridden column back to its own name (TS reads rows by name;
|
|
37
|
+
the Rust twin decodes positionally and needs no output name). The one
|
|
38
|
+
override in this repo is `iso8601_timestamp_column(alias, column)`, twin
|
|
39
|
+
of `fuz_db::iso8601_timestamp_column` down to the format literal
|
|
40
|
+
(`to_char(… AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')`): every
|
|
41
|
+
timestamp that reaches the wire projects through it, so both spines
|
|
42
|
+
serialize the same instant to the same 20-character second-precision UTC
|
|
43
|
+
string. Each query module builds its override once with
|
|
44
|
+
`iso8601_timestamp_expr(TABLE_COLUMNS, [...timestamp columns])` — typed
|
|
45
|
+
against the const, checked at load — and passes `expr(alias)` at each
|
|
46
|
+
read. `timestamp.ts` (`to_iso8601_seconds` / `ISO8601_SECONDS`) is that
|
|
47
|
+
shape for stamps minted in TS rather than read from a row. A cascade's
|
|
48
|
+
inner `RETURNING` inside a `WITH updated AS (…)` stays raw — the outer
|
|
49
|
+
select formats, and `to_char` over already-formatted text would fail.
|
|
50
|
+
`fact`'s store rows are the deliberate exception: `PgFactStore` feeds
|
|
51
|
+
`FactMeta.created_at`, a `Date` in the `@fuzdev/fuz_util` `FactStore`
|
|
52
|
+
contract, and nothing serializes it.
|
|
34
53
|
- `status.ts` — CLI DB status utility.
|
|
35
54
|
- `schema_ready.ts` — `/ready` deploy-gate core: `query_public_columns`
|
|
36
55
|
(keeps `schema_version`, unlike `query_schema_snapshot`), pure
|
|
@@ -108,7 +127,7 @@ child_id`, fractional-index keyed): `query_cell_item_insert` (throws
|
|
|
108
127
|
(the meta read derives `minus bytes`). The derived `grant_count` stays an
|
|
109
128
|
appended expression in the exported `cell_row_projection(alias)` rather than a
|
|
110
129
|
`CELL_COLUMNS` entry, so the const is exactly the table's column set. Column
|
|
111
|
-
order twins the Rust `fuz_cell` `*_COLUMNS` consts. Every const is pinned to
|
|
130
|
+
order twins the Rust `fuz_cell` / `fuz_fact` `*_COLUMNS` consts. Every const is pinned to
|
|
112
131
|
the live schema — and every public table forced to carry a const or a named
|
|
113
132
|
exemption — by `src/test/db/column_projections.db.test.ts`; the cell
|
|
114
133
|
`*_queries.db.test.ts` files pin the aliased JOIN reads and `grant_count`.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
|
-
import { AUDIT_LOG_COLUMNS } from '../auth/audit_log_queries.js';
|
|
15
|
+
import { AUDIT_LOG_COLUMNS, audit_log_expr } from '../auth/audit_log_queries.js';
|
|
16
16
|
import { columns_sql } from './sql_columns.js';
|
|
17
17
|
/**
|
|
18
18
|
* Metadata-jsonb keys cell-domain events use to name the cell. This
|
|
@@ -53,5 +53,5 @@ export const query_audit_log_list_by_cell = async (deps, cell_id, options) => {
|
|
|
53
53
|
const where = `WHERE ${conditions.join(' AND ')}`;
|
|
54
54
|
const limit_placeholder = `$${i++}`;
|
|
55
55
|
params.push(options.limit);
|
|
56
|
-
return deps.db.query(`SELECT ${columns_sql(AUDIT_LOG_COLUMNS)} FROM audit_log ${where} ORDER BY seq DESC LIMIT ${limit_placeholder}`, params);
|
|
56
|
+
return deps.db.query(`SELECT ${columns_sql(AUDIT_LOG_COLUMNS, audit_log_expr(''))} FROM audit_log ${where} ORDER BY seq DESC LIMIT ${limit_placeholder}`, params);
|
|
57
57
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_field_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_field_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"cell_field_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_field_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,2DAKuB,CAAC;AAKvD,wCAAwC;AACxC,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,OAAO,sBAAsB,KAC3B,OAAO,CAAC,YAAY,CAUtB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,WAAW,IAAI,EACf,MAAM,MAAM,KACV,OAAO,CAAC,YAAY,GAAG,IAAI,CAM7B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,WAAW,IAAI,EACf,MAAM,MAAM,KACV,OAAO,CAAC,YAAY,GAAG,IAAI,CAO7B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,WAAW,IAAI,EACf,UAAU;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KAC/C,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAa7B,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,WAAW,IAAI,EACf,UAAU;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAC1B,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAS5B,CAAC"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
19
|
import { assert_row } from './assert_row.js';
|
|
20
|
-
import { columns_sql, qualify_columns } from './sql_columns.js';
|
|
20
|
+
import { columns_sql, iso8601_timestamp_expr, qualify_columns } from './sql_columns.js';
|
|
21
21
|
/**
|
|
22
22
|
* The full `cell_field` column set, named explicitly so a row read fails
|
|
23
23
|
* loud on schema drift (see `CELL_COLUMNS` in `db/cell_queries.ts`). Column
|
|
@@ -30,6 +30,8 @@ export const CELL_FIELD_COLUMNS = [
|
|
|
30
30
|
'target_id',
|
|
31
31
|
'created_at'
|
|
32
32
|
];
|
|
33
|
+
/** The `cell_field` timestamp override, by row qualifier (`''` bare, `f` for the cell-joined reads). */
|
|
34
|
+
const cell_field_expr = iso8601_timestamp_expr(CELL_FIELD_COLUMNS, ['created_at']);
|
|
33
35
|
/**
|
|
34
36
|
* Insert or update a field row.
|
|
35
37
|
*
|
|
@@ -48,7 +50,7 @@ export const query_cell_field_set = async (deps, input) => {
|
|
|
48
50
|
VALUES ($1, $2, $3)
|
|
49
51
|
ON CONFLICT (source_id, name)
|
|
50
52
|
DO UPDATE SET target_id = EXCLUDED.target_id, created_at = NOW()
|
|
51
|
-
RETURNING ${columns_sql(CELL_FIELD_COLUMNS)}`, [input.source_id, input.name, input.target_id]);
|
|
53
|
+
RETURNING ${columns_sql(CELL_FIELD_COLUMNS, cell_field_expr(''))}`, [input.source_id, input.name, input.target_id]);
|
|
52
54
|
return assert_row(row, 'INSERT INTO cell_field');
|
|
53
55
|
};
|
|
54
56
|
/**
|
|
@@ -64,7 +66,7 @@ export const query_cell_field_set = async (deps, input) => {
|
|
|
64
66
|
* @returns the row or `null` when not found
|
|
65
67
|
*/
|
|
66
68
|
export const query_cell_field_get = async (deps, source_id, name) => {
|
|
67
|
-
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_FIELD_COLUMNS)} FROM cell_field WHERE source_id = $1 AND name = $2`, [source_id, name]);
|
|
69
|
+
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_FIELD_COLUMNS, cell_field_expr(''))} FROM cell_field WHERE source_id = $1 AND name = $2`, [source_id, name]);
|
|
68
70
|
return row ?? null;
|
|
69
71
|
};
|
|
70
72
|
/**
|
|
@@ -77,7 +79,7 @@ export const query_cell_field_get = async (deps, source_id, name) => {
|
|
|
77
79
|
*/
|
|
78
80
|
export const query_cell_field_delete = async (deps, source_id, name) => {
|
|
79
81
|
const row = await deps.db.query_one(`DELETE FROM cell_field WHERE source_id = $1 AND name = $2
|
|
80
|
-
RETURNING ${columns_sql(CELL_FIELD_COLUMNS)}`, [source_id, name]);
|
|
82
|
+
RETURNING ${columns_sql(CELL_FIELD_COLUMNS, cell_field_expr(''))}`, [source_id, name]);
|
|
81
83
|
return row ?? null;
|
|
82
84
|
};
|
|
83
85
|
/**
|
|
@@ -96,7 +98,7 @@ export const query_cell_field_delete = async (deps, source_id, name) => {
|
|
|
96
98
|
export const query_cell_field_list_for_source = async (deps, source_id, options) => {
|
|
97
99
|
const limit = options?.limit ?? null;
|
|
98
100
|
const name_after = options?.name_after ?? null;
|
|
99
|
-
return deps.db.query(`SELECT ${qualify_columns(CELL_FIELD_COLUMNS, 'f')} FROM cell_field f
|
|
101
|
+
return deps.db.query(`SELECT ${qualify_columns(CELL_FIELD_COLUMNS, 'f', cell_field_expr('f'))} FROM cell_field f
|
|
100
102
|
JOIN cell t ON t.id = f.target_id
|
|
101
103
|
WHERE f.source_id = $1
|
|
102
104
|
AND t.deleted_at IS NULL
|
|
@@ -121,7 +123,7 @@ export const query_cell_field_list_for_source = async (deps, source_id, options)
|
|
|
121
123
|
* @param options - `limit` caps the row count
|
|
122
124
|
* @returns matching rows, oldest field first (by the field row's `created_at`)
|
|
123
125
|
*/
|
|
124
|
-
export const query_cell_field_list_for_target = async (deps, target_id, options) => deps.db.query(`SELECT ${qualify_columns(CELL_FIELD_COLUMNS, 'f')} FROM cell_field f
|
|
126
|
+
export const query_cell_field_list_for_target = async (deps, target_id, options) => deps.db.query(`SELECT ${qualify_columns(CELL_FIELD_COLUMNS, 'f', cell_field_expr('f'))} FROM cell_field f
|
|
125
127
|
JOIN cell s ON s.id = f.source_id
|
|
126
128
|
WHERE f.target_id = $1
|
|
127
129
|
AND s.deleted_at IS NULL
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_grant_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAIzE,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"cell_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_grant_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAIzE,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,iGASuB,CAAC;AAKvD;;;;;GAKG;AACH,MAAM,MAAM,4BAA4B,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC;AAE3F,2CAA2C;AAC3C,MAAM,WAAW,yBAAyB;IACzC,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,4BAA4B,CAAC;IACxC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,OAAO,yBAAyB,KAC9B,OAAO,CAAC,YAAY,CAsBtB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,UAAU,IAAI,KACZ,OAAO,CAAC,YAAY,GAAG,IAAI,CAM7B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,UAAU,IAAI,KACZ,OAAO,CAAC,YAAY,GAAG,IAAI,CAM7B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,SAAS,IAAI,KACX,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAM5B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,+BAA+B,GAC3C,MAAM,SAAS,EACf,UAAU,aAAa,CAAC,IAAI,CAAC,KAC3B,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAQ7B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qCAAqC,GACjD,MAAM,SAAS,EACf,UAAU,aAAa,CAAC,IAAI,CAAC,EAC7B,iBAAiB,IAAI,GAAG,IAAI,EAC5B,kBAAkB,aAAa,CAAC,MAAM,CAAC,EACvC,sBAAsB,aAAa,CAAC,IAAI,GAAG,IAAI,CAAC,KAC9C,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAmB7B,CAAC"}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* @module
|
|
23
23
|
*/
|
|
24
24
|
import { assert_row } from './assert_row.js';
|
|
25
|
-
import { columns_sql, qualify_columns } from './sql_columns.js';
|
|
25
|
+
import { columns_sql, iso8601_timestamp_expr, qualify_columns } from './sql_columns.js';
|
|
26
26
|
/**
|
|
27
27
|
* The full `cell_grant` column set, named explicitly so a row read fails
|
|
28
28
|
* loud on schema drift (see `CELL_COLUMNS` in `db/cell_queries.ts`). Column
|
|
@@ -39,6 +39,8 @@ export const CELL_GRANT_COLUMNS = [
|
|
|
39
39
|
'granted_by',
|
|
40
40
|
'created_at'
|
|
41
41
|
];
|
|
42
|
+
/** The `cell_grant` timestamp override, by row qualifier (`''` bare, `g` for the cell-joined reads). */
|
|
43
|
+
const cell_grant_expr = iso8601_timestamp_expr(CELL_GRANT_COLUMNS, ['created_at']);
|
|
42
44
|
/**
|
|
43
45
|
* Insert a grant, or update the existing row's `level` + `granted_by` when
|
|
44
46
|
* one already exists for the same `(cell_id, principal)` pair.
|
|
@@ -60,14 +62,14 @@ export const query_cell_grant_create = async (deps, input) => {
|
|
|
60
62
|
VALUES ($1, $2, $3, $4)
|
|
61
63
|
ON CONFLICT (cell_id, actor_id) WHERE actor_id IS NOT NULL
|
|
62
64
|
DO UPDATE SET level = EXCLUDED.level, granted_by = EXCLUDED.granted_by
|
|
63
|
-
RETURNING ${columns_sql(CELL_GRANT_COLUMNS)}`, [cell_id, level, principal.actor_id, granted_by]);
|
|
65
|
+
RETURNING ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))}`, [cell_id, level, principal.actor_id, granted_by]);
|
|
64
66
|
return assert_row(row, 'INSERT INTO cell_grant (actor)');
|
|
65
67
|
}
|
|
66
68
|
const row = await deps.db.query_one(`INSERT INTO cell_grant (cell_id, level, role, scope_id, granted_by)
|
|
67
69
|
VALUES ($1, $2, $3, $4, $5)
|
|
68
70
|
ON CONFLICT (cell_id, role, scope_id) WHERE role IS NOT NULL
|
|
69
71
|
DO UPDATE SET level = EXCLUDED.level, granted_by = EXCLUDED.granted_by
|
|
70
|
-
RETURNING ${columns_sql(CELL_GRANT_COLUMNS)}`, [cell_id, level, principal.role, principal.scope_id, granted_by]);
|
|
72
|
+
RETURNING ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))}`, [cell_id, level, principal.role, principal.scope_id, granted_by]);
|
|
71
73
|
return assert_row(row, 'INSERT INTO cell_grant (role)');
|
|
72
74
|
};
|
|
73
75
|
/**
|
|
@@ -78,7 +80,7 @@ export const query_cell_grant_create = async (deps, input) => {
|
|
|
78
80
|
* @returns the row or `null` when not found
|
|
79
81
|
*/
|
|
80
82
|
export const query_cell_grant_get = async (deps, grant_id) => {
|
|
81
|
-
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_GRANT_COLUMNS)} FROM cell_grant WHERE id = $1`, [grant_id]);
|
|
83
|
+
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))} FROM cell_grant WHERE id = $1`, [grant_id]);
|
|
82
84
|
return row ?? null;
|
|
83
85
|
};
|
|
84
86
|
/**
|
|
@@ -94,7 +96,7 @@ export const query_cell_grant_get = async (deps, grant_id) => {
|
|
|
94
96
|
* @mutates `cell_grant` - deletes one row
|
|
95
97
|
*/
|
|
96
98
|
export const query_cell_grant_delete = async (deps, grant_id) => {
|
|
97
|
-
const row = await deps.db.query_one(`DELETE FROM cell_grant WHERE id = $1 RETURNING ${columns_sql(CELL_GRANT_COLUMNS)}`, [grant_id]);
|
|
99
|
+
const row = await deps.db.query_one(`DELETE FROM cell_grant WHERE id = $1 RETURNING ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))}`, [grant_id]);
|
|
98
100
|
return row ?? null;
|
|
99
101
|
};
|
|
100
102
|
/**
|
|
@@ -107,9 +109,9 @@ export const query_cell_grant_delete = async (deps, grant_id) => {
|
|
|
107
109
|
* @param cell_id - cell id
|
|
108
110
|
* @returns matching rows
|
|
109
111
|
*/
|
|
110
|
-
export const query_cell_grant_list_for_cell = async (deps, cell_id) => deps.db.query(`SELECT ${columns_sql(CELL_GRANT_COLUMNS)} FROM cell_grant
|
|
112
|
+
export const query_cell_grant_list_for_cell = async (deps, cell_id) => deps.db.query(`SELECT ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))} FROM cell_grant
|
|
111
113
|
WHERE cell_id = $1
|
|
112
|
-
ORDER BY created_at ASC`, [cell_id]);
|
|
114
|
+
ORDER BY cell_grant.created_at ASC`, [cell_id]);
|
|
113
115
|
/**
|
|
114
116
|
* List all grants across a set of cells, ordered by cell then creation.
|
|
115
117
|
* Used by the strict relation-read filter to test `can_view_cell` per
|
|
@@ -124,9 +126,9 @@ export const query_cell_grant_list_for_cell = async (deps, cell_id) => deps.db.q
|
|
|
124
126
|
export const query_cell_grant_list_for_cells = async (deps, cell_ids) => {
|
|
125
127
|
if (cell_ids.length === 0)
|
|
126
128
|
return [];
|
|
127
|
-
return deps.db.query(`SELECT ${columns_sql(CELL_GRANT_COLUMNS)} FROM cell_grant
|
|
129
|
+
return deps.db.query(`SELECT ${columns_sql(CELL_GRANT_COLUMNS, cell_grant_expr(''))} FROM cell_grant
|
|
128
130
|
WHERE cell_id = ANY($1::uuid[])
|
|
129
|
-
ORDER BY cell_id, created_at ASC`, [cell_ids]);
|
|
131
|
+
ORDER BY cell_grant.cell_id, cell_grant.created_at ASC`, [cell_ids]);
|
|
130
132
|
};
|
|
131
133
|
/**
|
|
132
134
|
* Load grants that admit the caller (by actor or role-scoped role_grants) across
|
|
@@ -146,7 +148,7 @@ export const query_cell_grants_for_caller_in_cells = async (deps, cell_ids, call
|
|
|
146
148
|
if (cell_ids.length === 0) {
|
|
147
149
|
return [];
|
|
148
150
|
}
|
|
149
|
-
return deps.db.query(`SELECT ${qualify_columns(CELL_GRANT_COLUMNS, 'g')} FROM cell_grant g
|
|
151
|
+
return deps.db.query(`SELECT ${qualify_columns(CELL_GRANT_COLUMNS, 'g', cell_grant_expr('g'))} FROM cell_grant g
|
|
150
152
|
WHERE g.cell_id = ANY($1::uuid[])
|
|
151
153
|
AND (
|
|
152
154
|
g.actor_id = $2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_item_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_item_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"cell_item_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_item_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,8DAKuB,CAAC;AAKtD,0CAA0C;AAC1C,MAAM,WAAW,wBAAwB;IACxC,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,OAAO,wBAAwB,KAC7B,OAAO,CAAC,WAAW,CAQrB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,WAAW,IAAI,EACf,UAAU,MAAM,KACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAM5B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,WAAW,IAAI,EACf,cAAc,MAAM,EACpB,cAAc,MAAM,KAClB,OAAO,CAAC,WAAW,GAAG,IAAI,CAS5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,WAAW,IAAI,EACf,UAAU,MAAM,KACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAO5B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,+BAA+B,GAC3C,MAAM,SAAS,EACf,WAAW,IAAI,EACf,UAAU;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,KACnD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAa5B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,UAAU,IAAI,EACd,UAAU;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAC1B,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAS3B,CAAC"}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @module
|
|
21
21
|
*/
|
|
22
22
|
import { assert_row } from './assert_row.js';
|
|
23
|
-
import { columns_sql, qualify_columns } from './sql_columns.js';
|
|
23
|
+
import { columns_sql, iso8601_timestamp_expr, qualify_columns } from './sql_columns.js';
|
|
24
24
|
/**
|
|
25
25
|
* The full `cell_item` column set, named explicitly so a row read fails
|
|
26
26
|
* loud on schema drift (see `CELL_COLUMNS` in `db/cell_queries.ts`). Column
|
|
@@ -33,6 +33,8 @@ export const CELL_ITEM_COLUMNS = [
|
|
|
33
33
|
'child_id',
|
|
34
34
|
'created_at'
|
|
35
35
|
];
|
|
36
|
+
/** The `cell_item` timestamp override, by row qualifier (`''` bare, `i` for the cell-joined reads). */
|
|
37
|
+
const cell_item_expr = iso8601_timestamp_expr(CELL_ITEM_COLUMNS, ['created_at']);
|
|
36
38
|
/**
|
|
37
39
|
* Insert one item row at the caller-supplied `position`.
|
|
38
40
|
*
|
|
@@ -47,7 +49,7 @@ export const CELL_ITEM_COLUMNS = [
|
|
|
47
49
|
export const query_cell_item_insert = async (deps, input) => {
|
|
48
50
|
const row = await deps.db.query_one(`INSERT INTO cell_item (parent_id, position, child_id)
|
|
49
51
|
VALUES ($1, $2, $3)
|
|
50
|
-
RETURNING ${columns_sql(CELL_ITEM_COLUMNS)}`, [input.parent_id, input.position, input.child_id]);
|
|
52
|
+
RETURNING ${columns_sql(CELL_ITEM_COLUMNS, cell_item_expr(''))}`, [input.parent_id, input.position, input.child_id]);
|
|
51
53
|
return assert_row(row, 'INSERT INTO cell_item');
|
|
52
54
|
};
|
|
53
55
|
/**
|
|
@@ -57,7 +59,7 @@ export const query_cell_item_insert = async (deps, input) => {
|
|
|
57
59
|
* @returns the row or `null` when not found
|
|
58
60
|
*/
|
|
59
61
|
export const query_cell_item_get = async (deps, parent_id, position) => {
|
|
60
|
-
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_ITEM_COLUMNS)} FROM cell_item WHERE parent_id = $1 AND position = $2`, [parent_id, position]);
|
|
62
|
+
const row = await deps.db.query_one(`SELECT ${columns_sql(CELL_ITEM_COLUMNS, cell_item_expr(''))} FROM cell_item WHERE parent_id = $1 AND position = $2`, [parent_id, position]);
|
|
61
63
|
return row ?? null;
|
|
62
64
|
};
|
|
63
65
|
/**
|
|
@@ -77,7 +79,7 @@ export const query_cell_item_move = async (deps, parent_id, position_old, positi
|
|
|
77
79
|
const row = await deps.db.query_one(`UPDATE cell_item
|
|
78
80
|
SET position = $3
|
|
79
81
|
WHERE parent_id = $1 AND position = $2
|
|
80
|
-
RETURNING ${columns_sql(CELL_ITEM_COLUMNS)}`, [parent_id, position_old, position_new]);
|
|
82
|
+
RETURNING ${columns_sql(CELL_ITEM_COLUMNS, cell_item_expr(''))}`, [parent_id, position_old, position_new]);
|
|
81
83
|
return row ?? null;
|
|
82
84
|
};
|
|
83
85
|
/**
|
|
@@ -90,7 +92,7 @@ export const query_cell_item_move = async (deps, parent_id, position_old, positi
|
|
|
90
92
|
*/
|
|
91
93
|
export const query_cell_item_delete = async (deps, parent_id, position) => {
|
|
92
94
|
const row = await deps.db.query_one(`DELETE FROM cell_item WHERE parent_id = $1 AND position = $2
|
|
93
|
-
RETURNING ${columns_sql(CELL_ITEM_COLUMNS)}`, [parent_id, position]);
|
|
95
|
+
RETURNING ${columns_sql(CELL_ITEM_COLUMNS, cell_item_expr(''))}`, [parent_id, position]);
|
|
94
96
|
return row ?? null;
|
|
95
97
|
};
|
|
96
98
|
/**
|
|
@@ -109,7 +111,7 @@ export const query_cell_item_delete = async (deps, parent_id, position) => {
|
|
|
109
111
|
export const query_cell_item_list_for_parent = async (deps, parent_id, options) => {
|
|
110
112
|
const limit = options?.limit ?? null;
|
|
111
113
|
const position_after = options?.position_after ?? null;
|
|
112
|
-
return deps.db.query(`SELECT ${qualify_columns(CELL_ITEM_COLUMNS, 'i')} FROM cell_item i
|
|
114
|
+
return deps.db.query(`SELECT ${qualify_columns(CELL_ITEM_COLUMNS, 'i', cell_item_expr('i'))} FROM cell_item i
|
|
113
115
|
JOIN cell c ON c.id = i.child_id
|
|
114
116
|
WHERE i.parent_id = $1
|
|
115
117
|
AND c.deleted_at IS NULL
|
|
@@ -129,7 +131,7 @@ export const query_cell_item_list_for_parent = async (deps, parent_id, options)
|
|
|
129
131
|
* inbound-linked child can't force an unbounded fetch + per-parent authz
|
|
130
132
|
* pass on the public, IP-rate-limited reverse endpoint.
|
|
131
133
|
*/
|
|
132
|
-
export const query_cell_item_list_for_child = async (deps, child_id, options) => deps.db.query(`SELECT ${qualify_columns(CELL_ITEM_COLUMNS, 'i')} FROM cell_item i
|
|
134
|
+
export const query_cell_item_list_for_child = async (deps, child_id, options) => deps.db.query(`SELECT ${qualify_columns(CELL_ITEM_COLUMNS, 'i', cell_item_expr('i'))} FROM cell_item i
|
|
133
135
|
JOIN cell p ON p.id = i.parent_id
|
|
134
136
|
WHERE i.child_id = $1
|
|
135
137
|
AND p.deleted_at IS NULL
|
|
@@ -49,9 +49,9 @@ export interface CellRow {
|
|
|
49
49
|
parent_id: Uuid | null;
|
|
50
50
|
root_id: Uuid | null;
|
|
51
51
|
moderation: string | null;
|
|
52
|
-
created_at:
|
|
53
|
-
updated_at:
|
|
54
|
-
deleted_at:
|
|
52
|
+
created_at: string;
|
|
53
|
+
updated_at: string | null;
|
|
54
|
+
deleted_at: string | null;
|
|
55
55
|
created_by: Uuid | null;
|
|
56
56
|
updated_by: Uuid | null;
|
|
57
57
|
grant_count: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAIjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"cell_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAIjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,2KAegD,CAAC;AAK1E;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,MAC2F,CAAC;AAEhJ;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,OAAO,oBAAoB,KACzB,OAAO,CAAC,OAAO,CAoBjB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAC1B,MAAM,SAAS,EACf,IAAI,IAAI,EACR,UAAU;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,KACrC,OAAO,CAAC,OAAO,GAAG,IAAI,CAUxB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,MAAM,MAAM,KACV,OAAO,CAAC,OAAO,GAAG,IAAI,CAQxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,KAAK,aAAa,CAAC,IAAI,CAAC,KACtB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAQxB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,IAAI,IAAI,EACR,OAAO,eAAe,KACpB,OAAO,CAAC,OAAO,GAAG,IAAI,CA4BxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,IAAI,IAAI,EACR,UAAU;IAAE,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,KACpC,OAAO,CAAC,OAAO,CAWjB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,SAAS,EACf,IAAI,IAAI,EACR,YAAY,MAAM,EAClB,SAAS;IAAE,qBAAqB,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,KACnE,OAAO,CAAC,OAAO,GAAG,IAAI,CAYxB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,MAAM,MAAM,EACZ,UAAU,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,QAAQ,CAAC,KACjD,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CASvB,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,GACtC,MAAM,SAAS,EACf,UAAU,IAAI,EACd,UAAU,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,QAAQ,CAAC,KACjD,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAQvB,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,eAAe,GAC3B,MAAM,SAAS,EACf,QAAQ,cAAc,KACpB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CA4DxB,CAAC;AAqGF,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC9B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,4EAA4E;IAC5E,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,OAAO,CAAC,EAAE,IAAI,CAAC;IACf;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClB;;;;OAIG;IACH,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B;;;;;;;OAOG;IACH,uBAAuB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAChD;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACzD;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,YAAY,GAAG,YAAY,CAAC;IACvC,sCAAsC;IACtC,eAAe,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACjC,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B"}
|
package/dist/db/cell_queries.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { fact_hash_extract_refs } from '@fuzdev/fuz_util/fact_hash.ts';
|
|
24
24
|
import { assert_row } from './assert_row.js';
|
|
25
|
-
import { qualify_columns } from './sql_columns.js';
|
|
25
|
+
import { iso8601_timestamp_expr, qualify_columns } from './sql_columns.js';
|
|
26
26
|
/**
|
|
27
27
|
* The full `cell` column set, named explicitly so a row read fails loud on
|
|
28
28
|
* schema drift — a `SELECT *` silently omits a dropped column and the
|
|
@@ -49,6 +49,8 @@ export const CELL_COLUMNS = [
|
|
|
49
49
|
'created_by',
|
|
50
50
|
'updated_by'
|
|
51
51
|
];
|
|
52
|
+
/** The `cell` timestamp override, by row qualifier — the one `cell_row_projection` is given. */
|
|
53
|
+
const cell_expr = iso8601_timestamp_expr(CELL_COLUMNS, ['created_at', 'updated_at', 'deleted_at']);
|
|
52
54
|
/**
|
|
53
55
|
* The full `CellRow` projection — `CELL_COLUMNS` qualified by `alias` plus
|
|
54
56
|
* the derived `grant_count` (a correlated subquery against `cell_grant`,
|
|
@@ -66,7 +68,7 @@ export const CELL_COLUMNS = [
|
|
|
66
68
|
* `CellRow` but fails at `to_cell_json` — this is the projection that
|
|
67
69
|
* actually produces one.
|
|
68
70
|
*/
|
|
69
|
-
export const cell_row_projection = (alias) => `${qualify_columns(CELL_COLUMNS, alias)}, (SELECT COUNT(*)::int FROM cell_grant WHERE cell_id = ${alias}.id) AS grant_count`;
|
|
71
|
+
export const cell_row_projection = (alias) => `${qualify_columns(CELL_COLUMNS, alias, cell_expr(alias))}, (SELECT COUNT(*)::int FROM cell_grant WHERE cell_id = ${alias}.id) AS grant_count`;
|
|
70
72
|
/**
|
|
71
73
|
* Insert a cell row, deriving `refs` from `data`.
|
|
72
74
|
*
|
|
@@ -248,7 +250,7 @@ export const query_cell_list_by_kind = async (deps, kind, options) => deps.db.qu
|
|
|
248
250
|
FROM cell
|
|
249
251
|
WHERE kind = $1
|
|
250
252
|
AND deleted_at IS NULL
|
|
251
|
-
ORDER BY created_at DESC
|
|
253
|
+
ORDER BY cell.created_at DESC
|
|
252
254
|
LIMIT $2 OFFSET $3`, [kind, options?.limit ?? null, options?.offset ?? 0]);
|
|
253
255
|
/**
|
|
254
256
|
* List active cells created by an actor, newest first. Backed by the
|
|
@@ -262,7 +264,7 @@ export const query_cell_list_by_kind = async (deps, kind, options) => deps.db.qu
|
|
|
262
264
|
export const query_cell_list_by_creator = async (deps, actor_id, options) => deps.db.query(`SELECT ${cell_row_projection('cell')}
|
|
263
265
|
FROM cell
|
|
264
266
|
WHERE created_by = $1 AND deleted_at IS NULL
|
|
265
|
-
ORDER BY created_at DESC
|
|
267
|
+
ORDER BY cell.created_at DESC
|
|
266
268
|
LIMIT $2 OFFSET $3`, [actor_id, options?.limit ?? null, options?.offset ?? 0]);
|
|
267
269
|
/**
|
|
268
270
|
* Filterable list query for the generic `cell_list` RPC.
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import { createHash } from 'node:crypto';
|
|
31
31
|
import { join } from 'node:path';
|
|
32
|
-
import { Blake3Hasher } from '@fuzdev/
|
|
32
|
+
import { Blake3Hasher } from '@fuzdev/blake3-wasm';
|
|
33
33
|
import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
34
34
|
import { blake3_ready } from '@fuzdev/fuz_util/hash_blake3.ts';
|
|
35
35
|
import { to_hex } from '@fuzdev/fuz_util/hex.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAGjE,0CAA0C;AAC1C,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kFAOwB,CAAC;
|
|
1
|
+
{"version":3,"file":"fact_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAGjE,0CAA0C;AAC1C,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kFAOwB,CAAC;AAYlD,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GAC1B,MAAM,SAAS,EACf,OAAO;IACN,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CACb,KACC,OAAO,CAAC,OAAO,CASjB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,aAAa,QAAQ,EACrB,eAAe,KAAK,CAAC,QAAQ,CAAC,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM,SAAS,EAAE,MAAM,QAAQ,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAO5F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,MAAM,QAAQ,KACZ,OAAO,CAAC,WAAW,GAAG,IAAI,CAO5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM,SAAS,EAAE,MAAM,QAAQ,KAAG,OAAO,CAAC,OAAO,CAMrF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,aAAa,QAAQ,KACnB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAMzB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,MAAM,QAAQ,KACZ,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAQ9D,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,QAAQ,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,YAAY,IAAI,GAAG,IAAI,EACvB,cAAc,MAAM,KAClB,OAAO,CAAC,qBAAqB,CA2C/B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,GAChD,MAAM,SAAS,EACf,YAAY,IAAI,KACd,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiB9E,CAAC"}
|
package/dist/db/fact_queries.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module
|
|
13
13
|
*/
|
|
14
|
-
import { columns_sql, omit_columns } from './sql_columns.js';
|
|
14
|
+
import { columns_sql, iso8601_timestamp_column, omit_columns } from './sql_columns.js';
|
|
15
15
|
/**
|
|
16
16
|
* The full `fact` column set, named explicitly so a row read fails loud on
|
|
17
17
|
* schema drift (see `ACCOUNT_COLUMNS` in `auth/account_queries.ts` for the
|
|
@@ -26,6 +26,12 @@ export const FACT_COLUMNS = [
|
|
|
26
26
|
'size',
|
|
27
27
|
'created_at'
|
|
28
28
|
];
|
|
29
|
+
// `created_at` is deliberately *not* projected through
|
|
30
|
+
// `iso8601_timestamp_column` here, unlike every other table: these rows feed
|
|
31
|
+
// `PgFactStore`, whose `FactMeta.created_at` is a `Date` in the
|
|
32
|
+
// `@fuzdev/fuz_util` `FactStore` contract, and nothing serializes them. The
|
|
33
|
+
// one fact timestamp that does reach the wire — the orphan-sweep sample in
|
|
34
|
+
// `query_orphan_facts_list` — projects the ISO-8601 wire string.
|
|
29
35
|
/** `FACT_COLUMNS` minus the payload — the `FactMetaRow` projection. */
|
|
30
36
|
const FACT_META_COLUMNS = omit_columns(FACT_COLUMNS, 'bytes');
|
|
31
37
|
/**
|
|
@@ -137,7 +143,7 @@ export const query_orphan_facts_list = async (deps, older_than, sample_limit) =>
|
|
|
137
143
|
AND c.deleted_at IS NULL
|
|
138
144
|
)
|
|
139
145
|
AND ($1::timestamptz IS NULL OR f.created_at < $1::timestamptz)`, [older_than]);
|
|
140
|
-
const sample_rows = await deps.db.query(`SELECT hash, size, created_at, external_url
|
|
146
|
+
const sample_rows = await deps.db.query(`SELECT hash, size, ${iso8601_timestamp_column('f', 'created_at')} AS created_at, external_url
|
|
141
147
|
FROM fact f
|
|
142
148
|
WHERE NOT EXISTS (
|
|
143
149
|
SELECT 1 FROM cell c
|
|
@@ -153,7 +159,7 @@ export const query_orphan_facts_list = async (deps, older_than, sample_limit) =>
|
|
|
153
159
|
sample: sample_rows.map((r) => ({
|
|
154
160
|
hash: r.hash,
|
|
155
161
|
size: Number(r.size),
|
|
156
|
-
created_at:
|
|
162
|
+
created_at: r.created_at,
|
|
157
163
|
external_url: r.external_url
|
|
158
164
|
}))
|
|
159
165
|
};
|