@fuzdev/fuz_app 0.95.0 → 0.97.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/auth/CLAUDE.md +1 -1
- package/dist/auth/account_queries.d.ts +20 -5
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +21 -4
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +6 -7
- package/dist/auth/daemon_token_middleware.d.ts +21 -4
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +61 -10
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +6 -2
- package/dist/auth/request_context.js +2 -2
- package/dist/db/CLAUDE.md +6 -3
- package/dist/db/cell_queries.js +8 -1
- package/dist/db/create_db.d.ts.map +1 -1
- package/dist/db/create_db.js +2 -14
- package/dist/db/db_pg.d.ts +30 -2
- package/dist/db/db_pg.d.ts.map +1 -1
- package/dist/db/db_pg.js +33 -2
- package/dist/db/fact_queries.d.ts.map +1 -1
- package/dist/http/CLAUDE.md +3 -2
- package/dist/http/error_schemas.d.ts +0 -6
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +0 -6
- package/dist/http/origin.d.ts +18 -1
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +17 -0
- package/dist/server/serve_fact_route.d.ts +12 -0
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +40 -0
- package/dist/testing/CLAUDE.md +23 -3
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +4 -1
- package/dist/testing/cross_backend/bootstrap_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/bootstrap_backend.js +8 -0
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +23 -0
- package/dist/testing/cross_backend/conformance_case.d.ts +40 -0
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +34 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +58 -0
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.js +5 -1
- package/dist/testing/cross_backend/setup.d.ts +17 -0
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +29 -4
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +6 -1
- package/dist/testing/middleware.js +4 -4
- package/package.json +6 -2
|
@@ -82,6 +82,15 @@ export const reconstruct_bootstrapped_handle = (serialized) => ({
|
|
|
82
82
|
base_url: serialized.config.base_url,
|
|
83
83
|
initial_cookies: serialized.keeper_cookies,
|
|
84
84
|
}),
|
|
85
|
+
// Same cookie jar but Origin-free so the daemon-token middleware doesn't
|
|
86
|
+
// discard the credential as browser-context — used by the `_testing_*`
|
|
87
|
+
// daemon-token calls (`_testing_reset` / `_testing_schema_snapshot` /
|
|
88
|
+
// `_testing_action_manifest` / `_testing_mint_session`).
|
|
89
|
+
keeper_daemon_transport: create_fetch_transport({
|
|
90
|
+
base_url: serialized.config.base_url,
|
|
91
|
+
initial_cookies: serialized.keeper_cookies,
|
|
92
|
+
origin: null,
|
|
93
|
+
}),
|
|
85
94
|
});
|
|
86
95
|
/**
|
|
87
96
|
* Structural subset of `SignupOutput` the runner cares about. Looser
|
|
@@ -163,7 +172,7 @@ const rpc_via_transport = async (transport, rpc_path, method, params, backend_na
|
|
|
163
172
|
* the snapshot shapes match by design.
|
|
164
173
|
*/
|
|
165
174
|
export const capture_schema_snapshot = async (handle, options = {}) => {
|
|
166
|
-
const raw = await rpc_via_transport(handle.
|
|
175
|
+
const raw = await rpc_via_transport(handle.keeper_daemon_transport, handle.config.rpc_path, '_testing_schema_snapshot', { exclude_tables: [...(options.exclude_tables ?? [])] }, handle.config.name, { [DAEMON_TOKEN_HEADER]: handle.daemon_token });
|
|
167
176
|
// TODO: cast, not parse — `SchemaSnapshot.parse(raw)` would validate the wire
|
|
168
177
|
// against the schema (the `capture_action_manifest` twin parses + uses a
|
|
169
178
|
// strict object); parsing here may surface a latent schema-model gap to
|
|
@@ -181,7 +190,7 @@ export const capture_schema_snapshot = async (handle, options = {}) => {
|
|
|
181
190
|
* `fuz_testing` mirror); the normalized shapes match by design.
|
|
182
191
|
*/
|
|
183
192
|
export const capture_action_manifest = async (handle) => {
|
|
184
|
-
const raw = await rpc_via_transport(handle.
|
|
193
|
+
const raw = await rpc_via_transport(handle.keeper_daemon_transport, handle.config.rpc_path, '_testing_action_manifest', {}, handle.config.name, { [DAEMON_TOKEN_HEADER]: handle.daemon_token });
|
|
185
194
|
return ActionManifest.parse(raw);
|
|
186
195
|
};
|
|
187
196
|
/**
|
|
@@ -215,7 +224,7 @@ const TestingResetResponseShape = z.object({
|
|
|
215
224
|
* can close over them.
|
|
216
225
|
*/
|
|
217
226
|
const fire_testing_reset = async (handle, options) => {
|
|
218
|
-
const raw = await rpc_via_transport(handle.
|
|
227
|
+
const raw = await rpc_via_transport(handle.keeper_daemon_transport, handle.config.rpc_path, '_testing_reset', {
|
|
219
228
|
extra_keeper_roles: options.extra_keeper_roles ?? [],
|
|
220
229
|
extra_accounts: (options.extra_accounts ?? []).map((spec) => ({
|
|
221
230
|
username: spec.username,
|
|
@@ -387,6 +396,17 @@ const create_keeper_transport = (handle, cookie_name, session_cookie) => create_
|
|
|
387
396
|
base_url: handle.config.base_url,
|
|
388
397
|
initial_cookies: [`${cookie_name}=${session_cookie}`],
|
|
389
398
|
});
|
|
399
|
+
/**
|
|
400
|
+
* Origin-free twin of `create_keeper_transport` — same fresh keeper cookie
|
|
401
|
+
* jar but `origin: null` so the daemon-token middleware doesn't discard the
|
|
402
|
+
* credential as browser-context. Used for the per-test `_testing_*`
|
|
403
|
+
* daemon-token calls (the rebuilt handle's `keeper_daemon_transport`).
|
|
404
|
+
*/
|
|
405
|
+
const create_keeper_daemon_transport = (handle, cookie_name, session_cookie) => create_fetch_transport({
|
|
406
|
+
base_url: handle.config.base_url,
|
|
407
|
+
initial_cookies: [`${cookie_name}=${session_cookie}`],
|
|
408
|
+
origin: null,
|
|
409
|
+
});
|
|
390
410
|
/**
|
|
391
411
|
* Build a `SetupTest` against a spawned + bootstrapped backend.
|
|
392
412
|
*
|
|
@@ -428,9 +448,14 @@ export const default_cross_process_setup = (handle, options) => {
|
|
|
428
448
|
// `session_cookie` for any keeper-acting calls this test makes
|
|
429
449
|
// (e.g. `fixture.create_account()`'s `invite_create` step).
|
|
430
450
|
const keeper_transport = create_keeper_transport(handle, cookie_name, keeper.session_cookie);
|
|
451
|
+
// Origin-free twin for the per-test daemon-token calls — the original
|
|
452
|
+
// `handle.keeper_daemon_transport` carries the wiped `globalSetup` keeper
|
|
453
|
+
// cookie, so rebuild it against the freshly re-seeded keeper.
|
|
454
|
+
const keeper_daemon_transport = create_keeper_daemon_transport(handle, cookie_name, keeper.session_cookie);
|
|
431
455
|
const refreshed_handle = {
|
|
432
456
|
...handle,
|
|
433
457
|
keeper_transport,
|
|
458
|
+
keeper_daemon_transport,
|
|
434
459
|
keeper_account: keeper.account,
|
|
435
460
|
keeper_actor: keeper.actor,
|
|
436
461
|
keeper_cookies: [`${cookie_name}=${keeper.session_cookie}`],
|
|
@@ -508,7 +533,7 @@ export const default_cross_process_setup = (handle, options) => {
|
|
|
508
533
|
// so `_testing_mint_session` mints the backdated row + signs the
|
|
509
534
|
// cookie server-side over the keeper's daemon-token channel.
|
|
510
535
|
mint_expired_session: async () => {
|
|
511
|
-
const raw = await rpc_via_transport(refreshed_handle.
|
|
536
|
+
const raw = await rpc_via_transport(refreshed_handle.keeper_daemon_transport, handle.config.rpc_path, '_testing_mint_session', { account_id: keeper.account.id, expires_in_seconds: EXPIRED_SESSION_OFFSET_SECONDS }, handle.config.name, { [DAEMON_TOKEN_HEADER]: handle.daemon_token });
|
|
512
537
|
const parsed = MintSessionResponseShape.safeParse(raw);
|
|
513
538
|
if (!parsed.success) {
|
|
514
539
|
throw new Error(`_testing_mint_session(${handle.config.name}) returned unexpected result: ` +
|
package/dist/testing/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA8B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA8B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,SAgEF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAQhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,UAAyC,CAAC;AAEvF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAG3D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAC9B,WAAW,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,EACvC,iBAAiB,KAAK,CAAC,MAAM,CAAC,KAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,CAwBzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,KAAK,CAAC,SAAS,CAAC,KAAG,IAMnE,CAAC"}
|
package/dist/testing/db.js
CHANGED
|
@@ -26,7 +26,7 @@ import { describe, beforeAll, beforeEach, afterAll } from 'vitest';
|
|
|
26
26
|
import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
27
27
|
import { create_pglite_db } from '../db/db_pglite.js';
|
|
28
28
|
import { assert_valid_sql_identifier } from '../db/sql_identifier.js';
|
|
29
|
-
import { create_pg_db } from '../db/db_pg.js';
|
|
29
|
+
import { create_pg_db, register_pg_type_parsers } from '../db/db_pg.js';
|
|
30
30
|
/**
|
|
31
31
|
* CI detection — `CI=true` is set automatically by GitHub Actions, GitLab CI, etc.
|
|
32
32
|
*/
|
|
@@ -121,6 +121,11 @@ export const create_pg_factory = (init_schema, test_url) => {
|
|
|
121
121
|
pool_ref = null;
|
|
122
122
|
}
|
|
123
123
|
const { Pool } = await import('pg');
|
|
124
|
+
// Mirror production's int8→number coercion (`create_db`) so the
|
|
125
|
+
// test pg pool reads `BIGSERIAL` columns (e.g. `audit_log.seq`)
|
|
126
|
+
// as numbers like PGlite does — without this the pg leg of a
|
|
127
|
+
// `.db.test.ts` sees `seq` as a string and wire-schema parses fail.
|
|
128
|
+
await register_pg_type_parsers();
|
|
124
129
|
const pool = new Pool({ connectionString: test_url });
|
|
125
130
|
pool_ref = pool;
|
|
126
131
|
const { db } = create_pg_db(pool);
|
|
@@ -13,7 +13,7 @@ import { Hono } from 'hono';
|
|
|
13
13
|
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
14
14
|
import { create_bearer_auth_middleware } from '../auth/bearer_auth.js';
|
|
15
15
|
import { query_validate_api_token } from '../auth/api_token_queries.js';
|
|
16
|
-
import { query_account_by_id, query_actor_by_id,
|
|
16
|
+
import { query_account_by_id, query_actor_by_id, query_active_actors_by_account, } from '../auth/account_queries.js';
|
|
17
17
|
import { query_role_grant_find_active_for_actor } from '../auth/role_grant_queries.js';
|
|
18
18
|
import { create_proxy_middleware } from '../http/proxy.js';
|
|
19
19
|
import { get_client_ip } from '../http/client_ip.js';
|
|
@@ -29,7 +29,7 @@ vi.mock('../auth/api_token_queries.js', () => ({
|
|
|
29
29
|
vi.mock('../auth/account_queries.js', () => ({
|
|
30
30
|
query_account_by_id: vi.fn(),
|
|
31
31
|
query_actor_by_id: vi.fn(),
|
|
32
|
-
|
|
32
|
+
query_active_actors_by_account: vi.fn(),
|
|
33
33
|
}));
|
|
34
34
|
vi.mock('../auth/role_grant_queries.js', () => ({
|
|
35
35
|
query_role_grant_find_active_for_actor: vi.fn(),
|
|
@@ -52,7 +52,7 @@ export const create_bearer_auth_mocks = (tc) => {
|
|
|
52
52
|
const mock_validate = vi.mocked(query_validate_api_token);
|
|
53
53
|
const mock_find_by_id = vi.mocked(query_account_by_id);
|
|
54
54
|
const mock_find_actor_by_id = vi.mocked(query_actor_by_id);
|
|
55
|
-
const mock_find_actors_by_account = vi.mocked(
|
|
55
|
+
const mock_find_actors_by_account = vi.mocked(query_active_actors_by_account);
|
|
56
56
|
const mock_find_active_for_actor = vi.mocked(query_role_grant_find_active_for_actor);
|
|
57
57
|
mock_validate
|
|
58
58
|
.mockReset()
|
|
@@ -211,7 +211,7 @@ export const create_test_middleware_stack_app = (options) => {
|
|
|
211
211
|
const mock_validate = vi.mocked(query_validate_api_token);
|
|
212
212
|
const mock_find_by_id = vi.mocked(query_account_by_id);
|
|
213
213
|
const mock_find_actor_by_id = vi.mocked(query_actor_by_id);
|
|
214
|
-
const mock_find_actors_by_account = vi.mocked(
|
|
214
|
+
const mock_find_actors_by_account = vi.mocked(query_active_actors_by_account);
|
|
215
215
|
const mock_find_active_for_actor = vi.mocked(query_role_grant_find_active_for_actor);
|
|
216
216
|
mock_validate.mockReset().mockImplementation(() => Promise.resolve(undefined));
|
|
217
217
|
mock_find_by_id.mockReset().mockImplementation(() => Promise.resolve(undefined));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "fullstack app library",
|
|
5
5
|
"glyph": "🗝",
|
|
6
6
|
"logo": "logo.svg",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"deploy": "gro deploy"
|
|
24
24
|
},
|
|
25
25
|
"type": "module",
|
|
26
|
+
"imports": {
|
|
27
|
+
"#lib/*": "./src/lib/*",
|
|
28
|
+
"#routes/*": "./src/routes/*"
|
|
29
|
+
},
|
|
26
30
|
"engines": {
|
|
27
31
|
"node": ">=24.14"
|
|
28
32
|
},
|
|
@@ -79,7 +83,7 @@
|
|
|
79
83
|
"@hono/node-server": "^1.19.14",
|
|
80
84
|
"@hono/node-ws": "^1.3.1",
|
|
81
85
|
"@node-rs/argon2": "^2.0.2",
|
|
82
|
-
"@ryanatkn/eslint-config": "^0.12.
|
|
86
|
+
"@ryanatkn/eslint-config": "^0.12.2",
|
|
83
87
|
"@sveltejs/acorn-typescript": "^1.0.9",
|
|
84
88
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
85
89
|
"@sveltejs/kit": "^2.63.0",
|