@somewhere-tech/cli 0.37.21 → 0.37.22
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.
|
@@ -50,15 +50,15 @@ Functions: a bare \`export default async function (req, sw)\` returning a
|
|
|
50
50
|
\`params.id\` there, \`sw.params.id\` bare. \`somewhere typecheck\` types bare
|
|
51
51
|
handlers as \`(req: Request, sw: SomewhereRuntimeContext)\`.
|
|
52
52
|
|
|
53
|
-
Data: declare tables in \`db/schema.ts\`; pages use
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
\`
|
|
57
|
-
\`
|
|
58
|
-
|
|
59
|
-
function for
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
Data: declare tables in \`db/schema.ts\`; pages use \`somewhere:data\`
|
|
54
|
+
(\`data.notes.list()\`, \`.create()\`, \`.update(id, …)\`) without API files.
|
|
55
|
+
Use \`owner()\` for personal rows, \`group()\` for invited teams, \`appRole()\`
|
|
56
|
+
for app-wide roles, and \`anyOf()\` for owner or a permitted role.
|
|
57
|
+
\`shared()\` gives signed-in reads and creator-only writes. \`client\` sets browser
|
|
58
|
+
columns; \`publicRead: { where }\` admits visitors. Keep these rules; add one
|
|
59
|
+
function for an exceptional write, not \`serverOnly()\` everywhere. Validate
|
|
60
|
+
first. Here \`handle\` is a public intake address its owner claimed, never a
|
|
61
|
+
private profile:
|
|
62
62
|
|
|
63
63
|
\`\`\`ts
|
|
64
64
|
const { handle, title, from_email } = body as { handle?: unknown; title?: unknown; from_email?: unknown };
|
|
@@ -458,6 +458,7 @@ export interface NotesController {
|
|
|
458
458
|
cancelEdit(): void;
|
|
459
459
|
saving: boolean;
|
|
460
460
|
canSave: boolean;
|
|
461
|
+
retryingCreate: boolean;
|
|
461
462
|
save(): Promise<void>;
|
|
462
463
|
removingId: NoteId | null;
|
|
463
464
|
remove(note: Note): Promise<void>;
|
|
@@ -497,10 +498,41 @@ export async function listNotes(): Promise<{ notes: Note[]; truncated: boolean }
|
|
|
497
498
|
return { notes: page.data, truncated: page.has_more };
|
|
498
499
|
}
|
|
499
500
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
501
|
+
/** Keep one logical create in memory; retry never calls create() again. */
|
|
502
|
+
export class NoteCreateError extends Error {
|
|
503
|
+
constructor(message: string, readonly outcome: 'unknown' | 'committed', readonly retry: (() => Promise<Note>) | null) {
|
|
504
|
+
super(message);
|
|
505
|
+
this.name = 'NoteCreateError';
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async function finishCreate(send: () => Promise<unknown>): Promise<Note> {
|
|
510
|
+
let result: unknown;
|
|
511
|
+
try {
|
|
512
|
+
result = await send();
|
|
513
|
+
} catch (reason: unknown) {
|
|
514
|
+
if (reason instanceof DataError && (reason.outcome === 'unknown'
|
|
515
|
+
|| reason.outcome === 'committed' || reason.write_committed === true)) {
|
|
516
|
+
const request = reason.request;
|
|
517
|
+
const retry = reason.outcome === 'unknown' && reason.write_committed !== true
|
|
518
|
+
&& reason.code !== 'IDEMPOTENCY_RETRY_EXPIRED' && request
|
|
519
|
+
? () => finishCreate(() => request.retry()) : null;
|
|
520
|
+
throw new NoteCreateError(retry
|
|
521
|
+
? 'The save could not be confirmed. Retry the original save; edits below will be kept.'
|
|
522
|
+
: 'The note may already be saved. Check your notes before starting another save.', reason.outcome === 'unknown' && reason.write_committed !== true ? 'unknown' : 'committed', retry);
|
|
523
|
+
}
|
|
524
|
+
throw reason;
|
|
525
|
+
}
|
|
526
|
+
const row = result && typeof result === 'object' && 'data' in result ? result.data : null;
|
|
527
|
+
if (!row || typeof row !== 'object' || !('id' in row) || typeof row.id !== 'number'
|
|
528
|
+
|| !('title' in row) || typeof row.title !== 'string' || !('body' in row) || typeof row.body !== 'string') {
|
|
529
|
+
throw new NoteCreateError('The save returned no readable note. Check your notes before starting another save.', 'committed', null);
|
|
530
|
+
}
|
|
531
|
+
return { id: row.id, title: row.title, body: row.body };
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function createNote(draft: NoteDraft): Promise<Note> {
|
|
535
|
+
return finishCreate(() => data.notes.create(normalizeDraft(draft)));
|
|
504
536
|
}
|
|
505
537
|
|
|
506
538
|
export async function updateNote(note: Note, draft: NoteDraft): Promise<NoteSaveResult> {
|
|
@@ -555,6 +587,7 @@ import { useAuth } from '@somewhere-tech/sdk/react';
|
|
|
555
587
|
import type { Note, NoteDraft, NoteDraftErrors, NoteId, NotesController, NotesStatus } from '../../types/notes';
|
|
556
588
|
import {
|
|
557
589
|
createNote,
|
|
590
|
+
NoteCreateError,
|
|
558
591
|
isSessionEnded,
|
|
559
592
|
listNotes,
|
|
560
593
|
NOTE_LIMITS,
|
|
@@ -580,6 +613,8 @@ export function useNotes(): NotesController {
|
|
|
580
613
|
const [draft, setDraft] = useState<NoteDraft>(EMPTY_DRAFT);
|
|
581
614
|
const [editingId, setEditingId] = useState<NoteId | null>(null);
|
|
582
615
|
const [saving, setSaving] = useState(false);
|
|
616
|
+
const busy = useRef(false);
|
|
617
|
+
const [pendingCreate, setPendingCreate] = useState<{ error: NoteCreateError; draft: NoteDraft } | null>(null);
|
|
583
618
|
const [removingId, setRemovingId] = useState<NoteId | null>(null);
|
|
584
619
|
const [notice, setNotice] = useState<NotesController['notice']>(null);
|
|
585
620
|
|
|
@@ -616,7 +651,8 @@ export function useNotes(): NotesController {
|
|
|
616
651
|
// An empty title disables Save; it is not flagged while the user types.
|
|
617
652
|
const draftErrors: NoteDraftErrors = draft.title.trim() ? errors : { body: errors.body };
|
|
618
653
|
const editing = editingId === null ? null : notes.find((note) => note.id === editingId) ?? null;
|
|
619
|
-
const
|
|
654
|
+
const pendingAdd = editing ? null : pendingCreate;
|
|
655
|
+
const canSave = !saving && (pendingAdd ? pendingAdd.error.retry !== null : Object.keys(errors).length === 0);
|
|
620
656
|
|
|
621
657
|
function fail(reason: unknown) {
|
|
622
658
|
setNotice({ tone: 'error', text: notesErrorMessage(reason) });
|
|
@@ -624,16 +660,19 @@ export function useNotes(): NotesController {
|
|
|
624
660
|
}
|
|
625
661
|
|
|
626
662
|
async function save() {
|
|
627
|
-
if (!canSave) return;
|
|
663
|
+
if (!canSave || busy.current) return;
|
|
664
|
+
busy.current = true;
|
|
628
665
|
setSaving(true);
|
|
629
666
|
setNotice(null);
|
|
667
|
+
const submitted = pendingAdd?.draft ?? { ...draft };
|
|
668
|
+
const creating = !editing;
|
|
630
669
|
try {
|
|
631
|
-
if (editing) {
|
|
670
|
+
if (!creating && editing) {
|
|
632
671
|
const result = await updateNote(editing, draft);
|
|
633
672
|
if (!mounted.current) return;
|
|
634
673
|
if (result.kind === 'saved') {
|
|
635
674
|
setNotes((list) => list.map((note) => (note.id === editing.id ? result.note : note)));
|
|
636
|
-
setNotice({ tone: 'info', text: 'Saved.' });
|
|
675
|
+
setNotice({ tone: 'info', text: pendingCreate ? 'Saved. ' + pendingCreate.error.message : 'Saved.' });
|
|
637
676
|
} else if (result.kind === 'unchanged') {
|
|
638
677
|
setNotice({ tone: 'info', text: 'No changes to save.' });
|
|
639
678
|
} else {
|
|
@@ -641,16 +680,23 @@ export function useNotes(): NotesController {
|
|
|
641
680
|
setNotice({ tone: 'error', text: 'That note was already removed.' });
|
|
642
681
|
}
|
|
643
682
|
} else {
|
|
644
|
-
const created =
|
|
683
|
+
const created = pendingAdd?.error.retry
|
|
684
|
+
? await pendingAdd.error.retry() : await createNote(submitted);
|
|
645
685
|
if (!mounted.current) return;
|
|
646
686
|
setNotes((list) => [...list, created]);
|
|
647
|
-
|
|
687
|
+
setPendingCreate(null);
|
|
688
|
+
setNotice({ tone: 'info', text: pendingCreate ? 'Original note added.' : 'Added.' });
|
|
648
689
|
}
|
|
649
|
-
|
|
650
|
-
|
|
690
|
+
// A retry saves the original values, not edits made while it was uncertain.
|
|
691
|
+
setDraft((current) => current.title === submitted.title && current.body === submitted.body ? EMPTY_DRAFT : current);
|
|
692
|
+
setEditingId((current) => current === editingId ? null : current);
|
|
651
693
|
} catch (reason: unknown) {
|
|
652
|
-
if (mounted.current)
|
|
694
|
+
if (mounted.current) {
|
|
695
|
+
if (creating && reason instanceof NoteCreateError) setPendingCreate({ error: reason, draft: submitted });
|
|
696
|
+
fail(reason);
|
|
697
|
+
}
|
|
653
698
|
} finally {
|
|
699
|
+
busy.current = false;
|
|
654
700
|
if (mounted.current) setSaving(false);
|
|
655
701
|
}
|
|
656
702
|
}
|
|
@@ -693,9 +739,11 @@ export function useNotes(): NotesController {
|
|
|
693
739
|
cancelEdit() {
|
|
694
740
|
setEditingId(null);
|
|
695
741
|
setDraft(EMPTY_DRAFT);
|
|
742
|
+
if (pendingCreate) setNotice({ tone: 'error', text: pendingCreate.error.message });
|
|
696
743
|
},
|
|
697
744
|
saving,
|
|
698
745
|
canSave,
|
|
746
|
+
retryingCreate: pendingAdd?.error.retry != null,
|
|
699
747
|
save,
|
|
700
748
|
removingId,
|
|
701
749
|
remove,
|
|
@@ -1763,7 +1811,7 @@ export function NotesBoard({ notes }: { notes: NotesController }) {
|
|
|
1763
1811
|
</div>
|
|
1764
1812
|
<div className="actions">
|
|
1765
1813
|
<button type="submit" className="button" disabled={!notes.canSave} aria-busy={notes.saving}>
|
|
1766
|
-
{notes.saving ? 'Saving…' : editing ? 'Save changes' : 'Add note'}
|
|
1814
|
+
{notes.saving ? 'Saving…' : notes.retryingCreate ? 'Retry original save' : editing ? 'Save changes' : 'Add note'}
|
|
1767
1815
|
</button>
|
|
1768
1816
|
{editing ? <button type="button" className="button button--quiet" onClick={notes.cancelEdit} disabled={notes.saving}>Cancel</button> : null}
|
|
1769
1817
|
</div>
|
|
@@ -1951,7 +1999,7 @@ export function NotesBoard({ notes }: { notes: NotesController }) {
|
|
|
1951
1999
|
{draftErrors.body ? <span role="alert"> {draftErrors.body}</span> : null}
|
|
1952
2000
|
</p>
|
|
1953
2001
|
<button type="submit" disabled={!notes.canSave} aria-busy={notes.saving}>
|
|
1954
|
-
{notes.saving ? 'Saving…' : editing ? 'Save changes' : 'Add note'}
|
|
2002
|
+
{notes.saving ? 'Saving…' : notes.retryingCreate ? 'Retry original save' : editing ? 'Save changes' : 'Add note'}
|
|
1955
2003
|
</button>{' '}
|
|
1956
2004
|
{editing ? <button type="button" onClick={notes.cancelEdit}>Cancel</button> : null}
|
|
1957
2005
|
<p role="status">{notes.notice?.text ?? ''}</p>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-feature-template.js","sourceRoot":"","sources":["../../src/lib/init-feature-template.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"init-feature-template.js","sourceRoot":"","sources":["../../src/lib/init-feature-template.ts"],"names":[],"mappings":"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"}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@somewhere-tech/cli",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.22",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@somewhere-tech/cli",
|
|
9
|
-
"version": "0.37.
|
|
9
|
+
"version": "0.37.22",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"@modelcontextprotocol/sdk",
|
|
12
12
|
"chokidar",
|
package/package.json
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"esbuild": "0.24.0",
|
|
3
3
|
"source_files": {
|
|
4
|
-
"worker/containers/compile/declared-data-contract.cjs": "
|
|
4
|
+
"worker/containers/compile/declared-data-contract.cjs": "3c243824d169c69a16fc1408a98deabeb8d36dce28835b9f7d8215428b216d01",
|
|
5
5
|
"worker/containers/compile/groups-types.cjs": "f0f38ca6f160561f997b20af44763bd07232deb2668a536cd52c1974fcfed2c8",
|
|
6
|
-
"worker/containers/compile/runtime-types.cjs": "
|
|
7
|
-
"worker/containers/compile/schema-types.cjs": "
|
|
6
|
+
"worker/containers/compile/runtime-types.cjs": "aeb6261ecf31d1cd965159442b16957062005fb54221f07fee821c2199ff70ae",
|
|
7
|
+
"worker/containers/compile/schema-types.cjs": "768e88adfc09233b097386b03ee2bf896e4970572c4e9d118b13fa89c0ff9644",
|
|
8
8
|
"worker/containers/compile/typed-data.cjs": "1c8bec853fbee4ffd34c651076a4e1f4d8b18c0c2be5e99e31df7c9283207627",
|
|
9
9
|
"worker/containers/compile/typed-files.cjs": "a0b1818afbc7673f84583c76436a3b3ca1d1fdf63d8d8db138b36646103f0708",
|
|
10
10
|
"worker/src/services/jobs/limits.ts": "f806f045dcb92f7da1e830aab65b74185ebd3071aeade368db776f3a0546de38",
|
|
11
|
-
"worker/src/utils/authority/
|
|
11
|
+
"worker/src/utils/authority/intake-bake.ts": "e68088af7b9e16cdfc8ac21852aa24b19b0ea0301fcc25bbc8a2d2bdd41603c9",
|
|
12
|
+
"worker/src/utils/authority/scope-enforcement.ts": "93120a82f4f819dc27e688bbe02d8fe763454a07c7aedc8049ad28be8a9576e7",
|
|
12
13
|
"worker/src/utils/db-schema-deploy/bigint-text.ts": "ef3f581daeecb234d2c1e288bc09495a6facd7b0354b300134918f6c0cf10cc2",
|
|
13
|
-
"worker/src/utils/db-schema-deploy/client-contract-source.ts": "
|
|
14
|
-
"worker/src/utils/db-schema-deploy/client-permissions.ts": "
|
|
14
|
+
"worker/src/utils/db-schema-deploy/client-contract-source.ts": "3bb56b3c1ebafec0aaa764346fb41d36315658f8e168d2ccc480e180c46789ad",
|
|
15
|
+
"worker/src/utils/db-schema-deploy/client-permissions.ts": "df93a103f5ff3ec89bd9a274a00651b4c77eafeb9b770e89ed82d56675d6c0f6",
|
|
15
16
|
"worker/src/utils/db-schema-deploy/extract-schema-app-roles.ts": "7f0e6ce3e213d56b678a60de133d10ed6f51f3a42ba73071d821d42a48c676a2",
|
|
16
|
-
"worker/src/utils/db-schema-deploy/extract-schema-bindings.ts": "
|
|
17
|
+
"worker/src/utils/db-schema-deploy/extract-schema-bindings.ts": "2028fc9adc639dd2a0a70874b3e2bc98414391c003fcb000102fea2cce01b8ba",
|
|
17
18
|
"worker/src/utils/db-schema-deploy/extract-schema-files.ts": "dddbb2d914a112e2820598d64f9da781aecec55e121f10de3501c3a7b4238f36",
|
|
18
19
|
"worker/src/utils/db-schema-deploy/extract-schema-groups.ts": "f80b93121e1ece04f43fa728517b5baa72fed1d9c833c23cf87ca558f8ca0263",
|
|
20
|
+
"worker/src/utils/db-schema-deploy/extract-schema-intake.ts": "61490eb93ce73e4ee846adf8756b93a211d4a158f11ba7f448fffd35c4c4e70a",
|
|
19
21
|
"worker/src/utils/db-schema-deploy/extract-schema-links.ts": "91cd99fc90133e51cbbd92656d592714a8fd71e0ac1c869cf161ad4a07225b57",
|
|
20
22
|
"worker/src/utils/db-schema-deploy/extract-schema-options.ts": "0998748a953fa9df742a7bdcbbce01f4fc56f9735ddbe3adf9e01facd82f87ad",
|
|
21
23
|
"worker/src/utils/db-schema-deploy/extract-schema-parents.ts": "eaec77c4db2c9a1903bd07fb265fc4f3fa8941f23724ab568ccdbf9569dc7a78",
|
|
22
24
|
"worker/src/utils/db-schema-deploy/extract-schema-relations.ts": "3984683d3227e964845836079476687a7295e6907b525ef21b9eebc488825bf8",
|
|
23
25
|
"worker/src/utils/db-schema-deploy/extract-schema-roles.ts": "1b2d7c7279679c726053c5d1586221476587273fc24ce93bde72a4a8ef8e7582",
|
|
24
|
-
"worker/src/utils/db-schema-deploy/extract-schema-ts.ts": "
|
|
26
|
+
"worker/src/utils/db-schema-deploy/extract-schema-ts.ts": "8b2fcb8683a506a41128335ad3fa7000701b3344f816eeaa28d10bab95464834",
|
|
25
27
|
"worker/src/utils/db-schema-deploy/schema-constants.ts": "07e648748409207fa4b97367b8942463c047a0bb0e27a36f16f696f90f2b550d",
|
|
26
28
|
"worker/src/utils/db-schema-deploy/schema-ownership.ts": "e6c811a87bc657707be3518dfe547c6d97718ac073108b126eb7f791c9c08202",
|
|
27
29
|
"worker/src/utils/managed-groups/errors.ts": "4830b1ad7357a79760b0bcc68884e562cfbc07d12a37cc73651a6fcb256d682f",
|
|
28
30
|
"worker/src/utils/managed-groups/policy.ts": "2259a883645c8bfd607ead7c37387f3ffd42ac9dfb86722c72b224adb498511e"
|
|
29
31
|
},
|
|
30
|
-
"sha256": "
|
|
32
|
+
"sha256": "c45b2036e7211aa1b187d803c4c261c62ea46f98c367f6d168f3c0fb53d74290"
|
|
31
33
|
}
|
|
@@ -45,7 +45,7 @@ var require_declared_data_contract = __commonJS({
|
|
|
45
45
|
function fail(detail) {
|
|
46
46
|
throw new Error(`Invalid declared data contract: ${detail}`);
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function record2(value, name) {
|
|
49
49
|
if (!value || typeof value !== "object" || Array.isArray(value)) fail(name);
|
|
50
50
|
}
|
|
51
51
|
function fields(value, columns, name, empty = false) {
|
|
@@ -55,11 +55,11 @@ var require_declared_data_contract = __commonJS({
|
|
|
55
55
|
return result.sort();
|
|
56
56
|
}
|
|
57
57
|
function policy(value, label, edges = 0) {
|
|
58
|
-
|
|
58
|
+
record2(value, label);
|
|
59
59
|
const keys = Object.keys(value).sort().join(",");
|
|
60
60
|
if (value.k === "o" && keys === "c,k" && identifier.test(value.c)) return { k: "o", c: value.c };
|
|
61
61
|
if (value.k === "m" && keys === "k,m") {
|
|
62
|
-
|
|
62
|
+
record2(value.m, label + ".member");
|
|
63
63
|
const { g, m, u, mg, o } = value.m;
|
|
64
64
|
const memberKeys = Object.keys(value.m).sort().join(",");
|
|
65
65
|
if (!["g,m,mg,u", "g,m,mg,o,u"].includes(memberKeys) || !identifier.test(m) || !identifier.test(u) || !Array.isArray(g) || !g.length || !Array.isArray(mg) || g.length !== mg.length || [...g, ...mg].some((field) => typeof field !== "string" || !identifier.test(field)) || o !== void 0 && (!Array.isArray(o) || JSON.stringify(o) !== JSON.stringify(["read", "create", "update", "delete"].filter((operation) => o.includes(operation))) || !o.includes("read") && (o.includes("update") || o.includes("delete")))) fail(label);
|
|
@@ -86,7 +86,7 @@ var require_declared_data_contract = __commonJS({
|
|
|
86
86
|
fail(label);
|
|
87
87
|
}
|
|
88
88
|
function policyRoles(value, label) {
|
|
89
|
-
|
|
89
|
+
record2(value, label + ".roles");
|
|
90
90
|
if (Object.keys(value).sort().join(",") !== "create,delete,read,update") fail(label);
|
|
91
91
|
const roles = {};
|
|
92
92
|
for (const op of ["read", "create", "update", "delete"]) {
|
|
@@ -108,25 +108,25 @@ var require_declared_data_contract = __commonJS({
|
|
|
108
108
|
}
|
|
109
109
|
function canonicalize2(schema, intents, scopes, insertReceiptCapability) {
|
|
110
110
|
validateInsertReceiptCapability(insertReceiptCapability);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
record2(schema, "schema");
|
|
112
|
+
record2(intents, "intents");
|
|
113
|
+
record2(scopes, "scopes");
|
|
114
114
|
const tables = [];
|
|
115
115
|
const membershipTables = new Set(Object.values(schema).filter((table) => table && table.member).map((table) => table.member.m));
|
|
116
116
|
for (const table of Object.values(schema)) if (table?.policy) policyMembershipTables(table.policy, membershipTables);
|
|
117
117
|
for (const name of Object.keys(schema).sort()) {
|
|
118
118
|
const table = schema[name];
|
|
119
|
-
|
|
119
|
+
record2(table, `table ${name}`);
|
|
120
120
|
if (table.client === void 0) {
|
|
121
121
|
if (table.clientPrimaryKey !== void 0) fail(`${name} has a primary key without client permissions`);
|
|
122
122
|
continue;
|
|
123
123
|
}
|
|
124
124
|
if (!identifier.test(name) || name.startsWith("_") || name.startsWith("sqlite_")) fail(`table ${name}`);
|
|
125
|
-
|
|
125
|
+
record2(table.client, `${name}.client`);
|
|
126
126
|
if (!Array.isArray(table.columns) || !table.columns.length) fail(`${name}.columns`);
|
|
127
127
|
const seen = /* @__PURE__ */ new Set();
|
|
128
128
|
const columns = table.columns.map((column) => {
|
|
129
|
-
|
|
129
|
+
record2(column, `${name}.column`);
|
|
130
130
|
if (typeof column.n !== "string" || !identifier.test(column.n) || seen.has(column.n) || !types.has(column.t)) fail(`${name}.column`);
|
|
131
131
|
if (column.nul !== void 0 && column.nul !== 1 || column.d !== void 0 && column.d !== 1) fail(`${name}.${column.n} flags`);
|
|
132
132
|
seen.add(column.n);
|
|
@@ -135,14 +135,14 @@ var require_declared_data_contract = __commonJS({
|
|
|
135
135
|
const pk = table.clientPrimaryKey;
|
|
136
136
|
if (!seen.has(pk) || !["integer", "text"].includes(columns.find((column) => column.n === pk).t)) fail(`${name} primary key`);
|
|
137
137
|
const input = table.client;
|
|
138
|
-
if (Object.keys(input).some((key) => !["read", "publicRead", "create", "update", "delete", "identity", "links"].includes(key))) fail(`${name} permissions`);
|
|
138
|
+
if (Object.keys(input).some((key) => !["read", "publicRead", "create", "update", "delete", "identity", "links", "intake"].includes(key))) fail(`${name} permissions`);
|
|
139
139
|
const read = typeof input.read === "boolean" ? input.read : fields(input.read, seen, `${name}.read`);
|
|
140
140
|
if (Array.isArray(read) && !read.includes(pk)) fail(`${name}.read must include the primary key`);
|
|
141
141
|
let publicRead = input.publicRead;
|
|
142
142
|
if (typeof publicRead !== "boolean") {
|
|
143
|
-
|
|
143
|
+
record2(publicRead, `${name} public read`);
|
|
144
144
|
if (Object.keys(publicRead).some((key) => key !== "where")) fail(`${name} public read`);
|
|
145
|
-
|
|
145
|
+
record2(publicRead.where, `${name} public read predicate`);
|
|
146
146
|
const entries = Object.entries(publicRead.where);
|
|
147
147
|
if (!entries.length || entries.length > 8) fail(`${name} public read predicate`);
|
|
148
148
|
const where = {};
|
|
@@ -176,7 +176,7 @@ var require_declared_data_contract = __commonJS({
|
|
|
176
176
|
if ([...create || [], ...update || []].some((field) => field === pk || field === owner || field === author)) fail(`${name} identity writes`);
|
|
177
177
|
let member = null;
|
|
178
178
|
if (intent === "member") {
|
|
179
|
-
|
|
179
|
+
record2(table.member, `${name}.member`);
|
|
180
180
|
const { g, m, u, mg, o } = table.member;
|
|
181
181
|
if (typeof m !== "string" || typeof u !== "string" || !identifier.test(m) || !identifier.test(u) || !Array.isArray(mg) || mg.some((field) => typeof field !== "string" || !identifier.test(field))) fail(`${name}.member`);
|
|
182
182
|
fields(g, seen, `${name}.member.g`);
|
|
@@ -199,8 +199,9 @@ var require_declared_data_contract = __commonJS({
|
|
|
199
199
|
if (normalizedPolicy?.k === "p" && create !== null && !create.includes(normalizedPolicy.v)) fail(`${name}.policy parent create`);
|
|
200
200
|
let links = null;
|
|
201
201
|
if (input.links !== void 0) {
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
record2(input.links, `${name}.links`);
|
|
203
|
+
const linkKeys = Object.keys(input.links).sort().join();
|
|
204
|
+
if (linkKeys !== "children,edit,maxDays,read" && !(linkKeys === "anonymousCreate,children,edit,maxDays,read" && input.links.anonymousCreate === true)) fail(`${name}.links`);
|
|
204
205
|
if (!(intent === "scoped" && !visitors) && normalizedPolicy?.k !== "a") fail(`${name}.links owner`);
|
|
205
206
|
const readable = read === true ? columns.filter((column) => column.n !== author).map((column) => column.n) : read || [];
|
|
206
207
|
const linkRead = fields(input.links.read, new Set(readable), `${name}.links.read`);
|
|
@@ -210,12 +211,31 @@ var require_declared_data_contract = __commonJS({
|
|
|
210
211
|
if (!Array.isArray(children) || children.some((child) => typeof child !== "string" || !identifier.test(child)) || new Set(children).size !== children.length) fail(`${name}.links.children`);
|
|
211
212
|
const maxDays = input.links.maxDays;
|
|
212
213
|
if (maxDays !== null && !(Number.isSafeInteger(maxDays) && maxDays >= 1 && maxDays <= 365)) fail(`${name}.links.maxDays`);
|
|
213
|
-
|
|
214
|
+
const anonymousCreate = input.links.anonymousCreate === true;
|
|
215
|
+
if (anonymousCreate && (intent !== "scoped" || visitors || normalizedPolicy || !create || create.length === 0 || columns.find((column) => column.n === pk).t !== "integer" || columns.some((column) => column.t === "blob"))) fail(`${name}.links.anonymousCreate`);
|
|
216
|
+
links = { read: linkRead, edit: linkEdit, children: [...children].sort(), maxDays, ...anonymousCreate ? { anonymousCreate: true } : {} };
|
|
217
|
+
}
|
|
218
|
+
let intake;
|
|
219
|
+
if (input.intake !== void 0) {
|
|
220
|
+
record2(input.intake, `${name}.intake`);
|
|
221
|
+
if (!["fields,target", "fields,target,where"].includes(Object.keys(input.intake).sort().join(","))) fail(`${name}.intake`);
|
|
222
|
+
record2(input.intake.target, `${name}.intake.target`);
|
|
223
|
+
if (Object.keys(input.intake.target).sort().join(",") !== "field,table" || ![input.intake.target.table, input.intake.target.field].every((value) => typeof value === "string" && identifier.test(value))) fail(`${name}.intake.target`);
|
|
224
|
+
if (membershipTables.has(name) || intent !== "scoped" || visitors || normalizedPolicy || columns.find((column) => column.n === pk).t !== "integer" || publicRead === true) fail(`${name}.intake owner`);
|
|
225
|
+
const accepted = fields(input.intake.fields, seen, `${name}.intake.fields`);
|
|
226
|
+
if (accepted.some((field) => field === pk || field === owner || field === author || columns.find((column) => column.n === field).t === "blob" || typeof publicRead === "object" && Object.hasOwn(publicRead.where, field)) || columns.some((column) => column.n !== pk && column.n !== owner && column.nul !== 1 && column.d !== 1 && !accepted.includes(column.n))) fail(`${name}.intake.fields`);
|
|
227
|
+
intake = { target: { table: input.intake.target.table, field: input.intake.target.field }, fields: accepted };
|
|
228
|
+
if (input.intake.where !== void 0) {
|
|
229
|
+
record2(input.intake.where, `${name}.intake.where`);
|
|
230
|
+
const keys = Object.keys(input.intake.where).sort();
|
|
231
|
+
if (!keys.length || keys.length > 8) fail(`${name}.intake.where`);
|
|
232
|
+
intake.where = Object.fromEntries(keys.map((field) => [field, input.intake.where[field]]));
|
|
233
|
+
}
|
|
214
234
|
}
|
|
215
235
|
tables.push({
|
|
216
236
|
name,
|
|
217
237
|
columns,
|
|
218
|
-
client: { identity: input.identity, read, publicRead, create, update, delete: input.delete, ...links ? { links } : {} },
|
|
238
|
+
client: { identity: input.identity, read, publicRead, create, update, delete: input.delete, ...links ? { links } : {}, ...intake ? { intake } : {} },
|
|
219
239
|
primaryKey: pk,
|
|
220
240
|
intent,
|
|
221
241
|
owner,
|
|
@@ -226,6 +246,19 @@ var require_declared_data_contract = __commonJS({
|
|
|
226
246
|
});
|
|
227
247
|
}
|
|
228
248
|
const tableByName = new Map(tables.map((table) => [table.name, table]));
|
|
249
|
+
for (const table of tables) {
|
|
250
|
+
const intake = table.client.intake;
|
|
251
|
+
if (!intake) continue;
|
|
252
|
+
const target = tableByName.get(intake.target.table);
|
|
253
|
+
const column = target?.columns.find((column2) => column2.n === intake.target.field);
|
|
254
|
+
const rawColumn = schema[intake.target.table]?.columns?.find((column2) => column2.n === intake.target.field);
|
|
255
|
+
if (!target || target.intent !== "scoped" || target.visitors || !target.client.publicRead || !Array.isArray(target.client.read) || !target.client.read.includes(intake.target.field) || !column || column.nul === 1 || !["text", "integer", "bigint"].includes(column.t) || rawColumn?.u !== 1) fail(`${table.name}.intake target`);
|
|
256
|
+
for (const [field, value] of Object.entries(intake.where || {})) {
|
|
257
|
+
const c = target.columns.find((column2) => column2.n === field);
|
|
258
|
+
if (!c) fail(`${table.name}.intake.where field`);
|
|
259
|
+
if (value === null ? c.nul !== 1 : c.t === "boolean" ? typeof value !== "boolean" : c.t === "integer" ? !Number.isSafeInteger(value) : c.t === "number" ? typeof value !== "number" || !Number.isFinite(value) : c.t === "bigint" ? !canonicalBigintText(value) : ["text", "timestamp"].includes(c.t) ? typeof value !== "string" || value.length > 256 : true) fail(`${table.name}.intake.where type`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
229
262
|
for (const table of tables) {
|
|
230
263
|
const declared = schema[table.name].relations;
|
|
231
264
|
if (declared === void 0) continue;
|
|
@@ -233,7 +266,7 @@ var require_declared_data_contract = __commonJS({
|
|
|
233
266
|
const relations = [];
|
|
234
267
|
const names = /* @__PURE__ */ new Set();
|
|
235
268
|
for (const relation of declared) {
|
|
236
|
-
|
|
269
|
+
record2(relation, `${table.name}.relation`);
|
|
237
270
|
if (Object.keys(relation).some((key) => !["name", "kind", "table", "fk", "parentKey"].includes(key))) fail(`${table.name}.relation`);
|
|
238
271
|
const { name, kind, table: relatedName, fk, parentKey } = relation;
|
|
239
272
|
if (![name, relatedName, fk, parentKey].every((value) => typeof value === "string" && identifier.test(value)) || names.has(name)) {
|
|
@@ -295,6 +328,27 @@ function insertError(status, payload) {
|
|
|
295
328
|
if (receipt) error.idempotency = receipt;
|
|
296
329
|
return error;
|
|
297
330
|
}
|
|
331
|
+
// One logical request's outcome across its explicit retries (one value per request handle). A later
|
|
332
|
+
// refusal, or this client's local retry horizon, describes only that attempt: it never erases an
|
|
333
|
+
// earlier committed result, and after an unknown attempt it never proves the write absent.
|
|
334
|
+
function requestOutcome() {
|
|
335
|
+
let known = null;
|
|
336
|
+
return {
|
|
337
|
+
done(result) { known = 'committed'; return result; },
|
|
338
|
+
failed(error) {
|
|
339
|
+
if (error.outcome === 'committed' || error.write_committed === true) { known = 'committed'; return error; }
|
|
340
|
+
if (known === 'committed') {
|
|
341
|
+
error.outcome = 'committed'; error.write_committed = true;
|
|
342
|
+
error.message += ' An earlier attempt of this request was already applied; do not create it again.';
|
|
343
|
+
} else if (error.outcome === 'unknown') known = 'unknown';
|
|
344
|
+
else if (known === 'unknown') {
|
|
345
|
+
error.outcome = 'unknown';
|
|
346
|
+
error.message += ' An earlier attempt of this request may still have been applied.';
|
|
347
|
+
}
|
|
348
|
+
return error;
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
298
352
|
async function createWithReceipt(table, values, extra, eligible) {
|
|
299
353
|
// create takes only values: the retry key is a private random nonce this client allocates,
|
|
300
354
|
// never a caller choice. Anything more refuses before the network.
|
|
@@ -307,7 +361,8 @@ async function createWithReceipt(table, values, extra, eligible) {
|
|
|
307
361
|
const body = JSON.stringify({values, contract, table, operation:'create', idempotency_key:key});
|
|
308
362
|
let handle;
|
|
309
363
|
const attach = target => { Object.defineProperty(target, 'request', {value:handle, enumerable:false, writable:false, configurable:false}); return target; };
|
|
310
|
-
const
|
|
364
|
+
const outcome = requestOutcome();
|
|
365
|
+
const attempt = async () => {
|
|
311
366
|
const now = Date.now();
|
|
312
367
|
if (!Number.isFinite(createdAt) || !Number.isFinite(now) || now < createdAt || now >= createdAt + 691200000) {
|
|
313
368
|
throw attach(insertError(410, {error:'IDEMPOTENCY_RETRY_EXPIRED', message:'This request can no longer be retried safely. Nothing was sent.'}));
|
|
@@ -325,9 +380,90 @@ async function createWithReceipt(table, values, extra, eligible) {
|
|
|
325
380
|
payload.idempotency = insertReceipt(payload.idempotency);
|
|
326
381
|
return attach(payload);
|
|
327
382
|
};
|
|
383
|
+
const send = () => attempt().then(outcome.done, error => { throw outcome.failed(error); });
|
|
384
|
+
handle = Object.freeze({key, createdAt, retry:send});
|
|
385
|
+
return send();
|
|
386
|
+
}
|
|
387
|
+
`;
|
|
388
|
+
var ANONYMOUS_CLIENT_RUNTIME = String.raw`
|
|
389
|
+
function creatorCapability(grant, secret, table) {
|
|
390
|
+
const capability = {grant};
|
|
391
|
+
Object.defineProperty(capability, 'secret', {value:secret, enumerable:false, writable:false, configurable:false});
|
|
392
|
+
// The creator link: the platform landing page, with everything in the fragment (never sent to a server).
|
|
393
|
+
const route = location.pathname + location.search + location.hash;
|
|
394
|
+
Object.defineProperty(capability, 'url', {value:location.origin + '/__sw/creator#' + grant + '.' + secret + '.' + table + '.' + b64url(route), enumerable:false, writable:false, configurable:false});
|
|
395
|
+
Object.defineProperty(capability, 'toJSON', {value:() => ({grant}), enumerable:false, writable:false, configurable:false});
|
|
396
|
+
return Object.freeze(capability);
|
|
397
|
+
}
|
|
398
|
+
async function createAnonymous(table, values, extra) {
|
|
399
|
+
if (extra.length !== 0) throw new DataError(400, {error:'DATA_INPUT_INVALID', message:'createAnonymous takes only the values to insert. Nothing was sent.'});
|
|
400
|
+
const hex = size => Array.from(crypto.getRandomValues(new Uint8Array(size)), byte => byte.toString(16).padStart(2,'0')).join('');
|
|
401
|
+
const key = hex(16), secret = hex(32), createdAt = Date.now();
|
|
402
|
+
const body = JSON.stringify({values, contract, table, operation:'create_anonymous', operation_key:key, creator_secret:secret});
|
|
403
|
+
let handle;
|
|
404
|
+
const attach = target => { Object.defineProperty(target, 'request', {value:handle, enumerable:false, writable:false, configurable:false}); return target; };
|
|
405
|
+
const outcome = requestOutcome();
|
|
406
|
+
const attempt = async () => {
|
|
407
|
+
const now = Date.now();
|
|
408
|
+
if (!Number.isFinite(createdAt) || !Number.isFinite(now) || now < createdAt || now >= createdAt + 691200000) {
|
|
409
|
+
throw attach(insertError(410, {error:'IDEMPOTENCY_RETRY_EXPIRED', message:'This request can no longer be retried safely. Nothing was sent.'}));
|
|
410
|
+
}
|
|
411
|
+
let response, payload;
|
|
412
|
+
try { response = await fetch('/__sw/data', {method:'POST', credentials:'same-origin', cache:'no-store', headers:{'Content-Type':'application/json'}, body}); }
|
|
413
|
+
catch (_) { throw attach(insertError(503, {error:'DB_WRITE_OUTCOME_UNKNOWN', message:'The write outcome could not be confirmed. Retry this request with its original key.', outcome:'unknown'})); }
|
|
414
|
+
try { payload = await response.json(); }
|
|
415
|
+
catch (_) { throw attach(insertError(response.status, {error:'INVALID_DATA_RESPONSE', message:'The write response could not be read. Retry this request with its original key.', outcome:'unknown'})); }
|
|
416
|
+
if (!response.ok) throw attach(insertError(response.status, payload));
|
|
417
|
+
const receipt = payload && typeof payload === 'object' && !Array.isArray(payload) ? insertReceipt(payload.idempotency) : null;
|
|
418
|
+
if (!receipt || typeof payload.grant !== 'string' || !/^crt_[0-9a-f]{32}$/.test(payload.grant)) {
|
|
419
|
+
throw insertError(502, {error:'IDEMPOTENCY_RECEIPT_INVALID', message:'The row was created, but retry protection could not be confirmed. Do not retry it.', outcome:'committed', write_committed:true});
|
|
420
|
+
}
|
|
421
|
+
return attach({data:payload.data === undefined ? null : payload.data, grant:payload.grant, idempotency:receipt, creator:creatorCapability(payload.grant, secret, table)});
|
|
422
|
+
};
|
|
423
|
+
const send = () => attempt().then(outcome.done, error => { throw outcome.failed(error); });
|
|
424
|
+
handle = Object.freeze({key, createdAt, retry:send});
|
|
425
|
+
return send();
|
|
426
|
+
}
|
|
427
|
+
`;
|
|
428
|
+
var INTAKE_CLIENT_RUNTIME = String.raw`
|
|
429
|
+
async function intake(table, reference, values, extra) {
|
|
430
|
+
if (extra.length !== 0) throw new DataError(400, {error:'DATA_INPUT_INVALID', message:'intake takes only the reference and the values to submit. Nothing was sent.'});
|
|
431
|
+
const key = Array.from(crypto.getRandomValues(new Uint8Array(16)), byte => byte.toString(16).padStart(2,'0')).join('');
|
|
432
|
+
const createdAt = Date.now();
|
|
433
|
+
const body = JSON.stringify({reference, values, contract, table, operation:'intake', operation_key:key});
|
|
434
|
+
let handle;
|
|
435
|
+
const attach = target => { Object.defineProperty(target, 'request', {value:handle, enumerable:false, writable:false, configurable:false}); return target; };
|
|
436
|
+
const outcome = requestOutcome();
|
|
437
|
+
const attempt = async () => {
|
|
438
|
+
const now = Date.now();
|
|
439
|
+
if (!Number.isFinite(createdAt) || !Number.isFinite(now) || now < createdAt || now >= createdAt + 691200000) {
|
|
440
|
+
throw attach(insertError(410, {error:'IDEMPOTENCY_RETRY_EXPIRED', message:'This request can no longer be retried safely. Nothing was sent.'}));
|
|
441
|
+
}
|
|
442
|
+
let response, payload;
|
|
443
|
+
try { response = await fetch('/__sw/data', {method:'POST', credentials:'same-origin', cache:'no-store', headers:{'Content-Type':'application/json'}, body}); }
|
|
444
|
+
catch (_) { throw attach(insertError(503, {error:'DB_WRITE_OUTCOME_UNKNOWN', message:'The write outcome could not be confirmed. Retry this request with its original key.', outcome:'unknown'})); }
|
|
445
|
+
try { payload = await response.json(); }
|
|
446
|
+
catch (_) { throw attach(insertError(response.status, {error:'INVALID_DATA_RESPONSE', message:'The write response could not be read. Retry this request with its original key.', outcome:'unknown'})); }
|
|
447
|
+
if (!response.ok) throw attach(insertError(response.status, payload));
|
|
448
|
+
const receipt = payload && typeof payload === 'object' && !Array.isArray(payload) && payload.accepted === true ? insertReceipt(payload.idempotency) : null;
|
|
449
|
+
if (!receipt) {
|
|
450
|
+
throw attach(insertError(502, {error:'IDEMPOTENCY_RECEIPT_INVALID', message:'The submission was accepted, but retry protection could not be confirmed. Do not retry it.', outcome:'committed', write_committed:true}));
|
|
451
|
+
}
|
|
452
|
+
return attach({accepted:true, idempotency:receipt});
|
|
453
|
+
};
|
|
454
|
+
const send = () => attempt().then(outcome.done, error => { throw outcome.failed(error); });
|
|
328
455
|
handle = Object.freeze({key, createdAt, retry:send});
|
|
329
456
|
return send();
|
|
330
457
|
}
|
|
458
|
+
`;
|
|
459
|
+
var CREATOR_CLIENT_RUNTIME = 'const creatorError=(status,payload)=>{const e=new DataError(status,payload);if(payload&&["committed","unknown","read_failed","not_committed"].includes(payload.outcome))e.outcome=payload.outcome;if(payload&&payload.write_committed===true)e.write_committed=true;e.retry=false;e.retryable=false;return e};const creatorDoor=async(path,init,write)=>{const lost=(status,code)=>creatorError(status,{error:code,message:write?"The creator operation could not be confirmed. Do not repeat it automatically.":"The creator operation result could not be read.",outcome:write?"unknown":"read_failed"});let response;try{response=await fetch(path,{credentials:"same-origin",cache:"no-store",...init})}catch(_){throw lost(503,"CREATOR_OUTCOME_UNKNOWN")}let payload;try{payload=await response.json()}catch(_){throw lost(response.status,"INVALID_DATA_RESPONSE")}if(!response.ok){if(!payload||typeof payload!=="object"||typeof payload.error!=="string")throw lost(response.status,"INVALID_DATA_RESPONSE");throw creatorError(response.status,payload)}if(!payload||typeof payload!=="object"||payload.ok!==true||!("data" in payload)||payload.data===undefined)throw lost(502,"INVALID_DATA_RESPONSE");return payload.data};const creatorPost=(body,write)=>creatorDoor("/__sw/creator",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...body,contract})},write);const claimOutcomes=new Map();const creatorsOpened=()=>{try{const list=JSON.parse(sessionStorage.getItem("__sw_creators_opened")||"[]");return Array.isArray(list)?list:[]}catch(_){return[]}};const creators=Object.freeze({opened:creatorsOpened,sessions:async()=>({data:await creatorDoor("/__sw/creator/sessions",{method:"GET"})}),forget:async creatorId=>{await creatorDoor("/__sw/creator/forget",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(creatorId===undefined?{}:{creator_id:creatorId})},true)}});const creatorView=spec=>creatorId=>{if(typeof creatorId!=="string"||!/^crt_[0-9a-f]{32}$/.test(creatorId))throw new DataError(400,{error:"DATA_INPUT_INVALID",message:"creator() needs a creator id"});const view={};for(const[table,canUpdate,children]of spec){const call=(action,fields,write)=>creatorPost({action,creator_id:creatorId,table,...fields},write);const root={get:id=>call("get",{id}).then(r=>({data:r.data})),links:id=>call("link_list",{id}),revokeLink:(id,linkId)=>call("link_revoke",{id,link_id:linkId},true),createLink:async(id,options={})=>{const result=await call("link_create",{id,access:options.access,...(options.expiresInDays===undefined?{}:{expires_in_days:options.expiresInDays})},true);const route=typeof options.returnTo==="string"?options.returnTo:location.pathname+location.search+location.hash;return{link_id:result.link_id,url:location.origin+"/__sw/link#"+result.secret+"."+b64url(route),expires_at:result.expires_at}},claim:async(id,options={})=>{const key=creatorId+"|"+table+"|"+String(id);let result;try{result=await call("claim",{id,keep_shares:options.keepShares===true},true)}catch(e){const known=claimOutcomes.get(key);if(e.outcome==="committed"||e.write_committed===true)claimOutcomes.set(key,"committed");else if(e.outcome==="unknown")claimOutcomes.set(key,"unknown");else if(known){e.outcome=known==="committed"?"committed":"unknown";if(known==="committed")e.write_committed=true;e.message+=" An earlier attempt of this claim may already have applied; check claimStatus() or your account."}throw e}claimOutcomes.set(key,"committed");try{sessionStorage.setItem("__sw_creators_opened",JSON.stringify(creatorsOpened().filter(e=>e&&e.creator_id!==creatorId)))}catch(_){}return result},claimStatus:id=>call("claim_status",{id})};if(canUpdate)root.update=(id,values)=>call("update",{id,values},true);const relations={};for(const[relation,child,canCreate,canUpdateChild]of children){relations[relation]=Object.freeze({list:(parentId,options={})=>call("relation_list",{relation,parent_id:parentId,...(options.after===undefined?{}:{after:options.after}),...(options.limit===undefined?{}:{limit:options.limit})})});const childOps={};if(canCreate)childOps.create=values=>call("child_create",{child,values},true);if(canUpdateChild)childOps.update=(id,values)=>call("child_update",{child,id,values},true);if(canCreate||canUpdateChild)view[child]=Object.freeze(childOps)}if(children.length)root.relations=Object.freeze(relations);view[table]=Object.freeze(root)}return Object.freeze(view)};\n';
|
|
460
|
+
var ANONYMOUS_CLIENT_DECLARATIONS = `
|
|
461
|
+
/** The private creator capability of a row created with createAnonymous. Keep it, and its url, private: anyone opening the url can read, edit, share and claim the row until it is claimed. */
|
|
462
|
+
export interface CreatorCapability { readonly grant: string; readonly secret: string; readonly url: string; }
|
|
463
|
+
export type AnonymousCreateResult<T> = T & { readonly grant: string; readonly idempotency: InsertReceipt; readonly creator: CreatorCapability; readonly request: InsertRequest<AnonymousCreateResult<T>> };
|
|
464
|
+
`;
|
|
465
|
+
var INTAKE_CLIENT_DECLARATIONS = `
|
|
466
|
+
export interface IntakeResult { readonly accepted: true; readonly idempotency: InsertReceipt; readonly request: InsertRequest<IntakeResult> }
|
|
331
467
|
`;
|
|
332
468
|
var INSERT_CLIENT_DECLARATIONS = `
|
|
333
469
|
export interface InsertReceipt { readonly replayed: boolean; readonly created_at: number; readonly result_until: number; readonly refuse_until: number; }
|
|
@@ -341,6 +477,10 @@ async function createWithReceipt(table, values, extra, eligible) {
|
|
|
341
477
|
const runtimeTables = [];
|
|
342
478
|
const receiptTables = [];
|
|
343
479
|
const receiptCapable = insertReceiptCapability === "insert-v1";
|
|
480
|
+
const anonymousTables = [];
|
|
481
|
+
const intakeTables = [];
|
|
482
|
+
const creatorDeclarations = [];
|
|
483
|
+
const creatorSpec = [];
|
|
344
484
|
const linkedDeclarations = [];
|
|
345
485
|
const linkedSpec = [];
|
|
346
486
|
for (const table of tables) {
|
|
@@ -377,6 +517,47 @@ async function createWithReceipt(table, values, extra, eligible) {
|
|
|
377
517
|
if (receiptCapable && eligible) receiptTables.push(name);
|
|
378
518
|
operations.push(`create(values: ${shape(columns, client.create, "create", required)}): Promise<${receiptCapable && eligible ? `InsertResult<${mutation}>` : mutation}>`);
|
|
379
519
|
methods.push("create");
|
|
520
|
+
if (receiptCapable && eligible && client.links && client.links.anonymousCreate === true) {
|
|
521
|
+
operations.push(`createAnonymous(values: ${shape(columns, client.create, "create", required)}): Promise<AnonymousCreateResult<{ data: ${row} | null }>>`);
|
|
522
|
+
methods.push("createAnonymous");
|
|
523
|
+
anonymousTables.push(name);
|
|
524
|
+
const ownerUpdate = (client.update || []).filter((field) => field !== table.owner && field !== primaryKey);
|
|
525
|
+
const creatorRow = shape(columns, readable, "read");
|
|
526
|
+
const rootOps = [
|
|
527
|
+
`get(id: ${id}): Promise<{ data: ${creatorRow} | null }>`,
|
|
528
|
+
`links(id: ${id}): Promise<{ data: Array<{ link_id: string; access: 'read' | 'edit'; created_at: number; expires_at: number | null }> }>`,
|
|
529
|
+
`createLink(id: ${id}, options: { access: ${client.links.edit.length ? "'read' | 'edit'" : "'read'"}; expiresInDays?: number; returnTo?: string }): Promise<{ link_id: string; url: string; expires_at: number | null }>`,
|
|
530
|
+
`revokeLink(id: ${id}, linkId: string): Promise<{ revoked: boolean }>`,
|
|
531
|
+
`claim(id: ${id}, options?: { keepShares?: boolean }): Promise<{ claimed: true; table: string; id: ${id}; shares: 'kept' | 'revoked' | 'unknown'; reconciled?: true }>`,
|
|
532
|
+
`claimStatus(id: ${id}): Promise<{ status: 'claimed_by_you' | 'not_claimed' | 'unknown' }>`
|
|
533
|
+
];
|
|
534
|
+
if (ownerUpdate.length) rootOps.push(`update(id: ${id}, values: ${shape(columns, ownerUpdate, "update")}): Promise<{ data: ${creatorRow} | null; count: number; changes: number }>`);
|
|
535
|
+
const childRelations = [], childSpecs = [];
|
|
536
|
+
for (const relationName of client.links.children) {
|
|
537
|
+
const relation = table.relations.find((item) => item.name === relationName);
|
|
538
|
+
const child = tables.find((candidate) => candidate.name === relation.table);
|
|
539
|
+
const childReadable = child.client.read === true ? child.columns.filter((column) => column.n !== child.author).map((column) => column.n) : child.client.read;
|
|
540
|
+
const childRow = shape(child.columns, childReadable, "read");
|
|
541
|
+
const childId = columnType(child.columns.find((column) => column.n === child.primaryKey));
|
|
542
|
+
childRelations.push(`${JSON.stringify(relationName)}: { list(parentId: ${id}, options?: { limit?: number; after?: ${childId} }): Promise<{ data: ${childRow}[]; next: ${childId} | null; has_more: boolean }> }`);
|
|
543
|
+
const childUpdate = child.client.update ? child.client.update.filter((field) => field !== relation.fk) : [];
|
|
544
|
+
const childOps = [];
|
|
545
|
+
if (child.client.create !== null) childOps.push(`create(values: ${shape(child.columns, child.client.create, "create", /* @__PURE__ */ new Set([relation.fk]))}): Promise<{ data: ${childRow} | null; count: number; changes: number }>`);
|
|
546
|
+
if (childUpdate.length) childOps.push(`update(id: ${childId}, values: ${shape(child.columns, childUpdate, "update")}): Promise<{ data: ${childRow} | null; count: number; changes: number }>`);
|
|
547
|
+
if (childOps.length) creatorDeclarations.push(`${JSON.stringify(child.name)}: { ${childOps.join("; ")} }`);
|
|
548
|
+
childSpecs.push([relationName, child.name, child.client.create !== null, childUpdate.length > 0]);
|
|
549
|
+
}
|
|
550
|
+
if (childRelations.length) rootOps.push(`relations: { ${childRelations.join("; ")} }`);
|
|
551
|
+
creatorDeclarations.push(`${JSON.stringify(name)}: { ${rootOps.join("; ")} }`);
|
|
552
|
+
creatorSpec.push([name, ownerUpdate.length > 0, childSpecs]);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (receiptCapable && client.intake) {
|
|
556
|
+
const target = tables.find((candidate) => candidate.name === client.intake.target.table);
|
|
557
|
+
const reference = columnType({ ...target.columns.find((column) => column.n === client.intake.target.field), nul: void 0 });
|
|
558
|
+
operations.push(`intake(reference: ${reference}, values: ${shape(columns, client.intake.fields, "create")}): Promise<IntakeResult>`);
|
|
559
|
+
methods.push("intake");
|
|
560
|
+
intakeTables.push(name);
|
|
380
561
|
}
|
|
381
562
|
if (client.update !== null) {
|
|
382
563
|
operations.push(`update(id: ${id}, values: ${shape(columns, client.update, "update")}): Promise<${mutation}>`);
|
|
@@ -433,20 +614,24 @@ async function createWithReceipt(table, values, extra, eligible) {
|
|
|
433
614
|
declarations.push(`${JSON.stringify(name)}: { ${operations.join("; ")} }`);
|
|
434
615
|
runtimeTables.push([name, methods, relationNames]);
|
|
435
616
|
}
|
|
617
|
+
if (creatorSpec.length) {
|
|
618
|
+
declarations.push(`creators: { opened(): Array<{ creator_id: string; table: string; row_id: string }>; sessions(): Promise<{ data: Array<{ creator_id: string; table: string; row_id: string; expires_at: number }> }>; forget(creatorId?: string): Promise<void> }`);
|
|
619
|
+
declarations.push(`creator(creatorId: string): { ${creatorDeclarations.join("; ")} }`);
|
|
620
|
+
}
|
|
436
621
|
if (linkedSpec.length) {
|
|
437
622
|
declarations.push(`links: { opened(): Array<{ link_id: string; table: string; row_id: string; access: 'read' | 'edit' }>; sessions(): Promise<{ data: Array<{ link_id: string; table: string; row_id: string; access: 'read' | 'edit'; expires_at: number }> }>; forget(linkId?: string): Promise<void> }`);
|
|
438
623
|
declarations.push(`linked(linkId: string): { ${linkedDeclarations.join("; ")} }`);
|
|
439
624
|
}
|
|
440
625
|
const declaration = `declare module ${JSON.stringify("somewhere:data")} {
|
|
441
626
|
export type Json = string | number | boolean | null | Json[] | { [key: string]: Json };
|
|
442
|
-
${receiptCapable ? localTypes ? INSERT_CLIENT_DECLARATIONS.replace("readonly idempotency:", "readonly idempotency?:").replace("readonly request:", "readonly request?:") : INSERT_CLIENT_DECLARATIONS : ""} export class DataError extends Error { readonly status: number; readonly code: string | null;${receiptCapable ? " readonly request?: InsertRequest<unknown>; readonly outcome?: string; readonly write_committed?: boolean; readonly retry?: false; readonly retryable?: false; readonly idempotency?: InsertReceipt;" : ""} constructor(status: number, payload: unknown); }
|
|
627
|
+
${receiptCapable ? localTypes ? INSERT_CLIENT_DECLARATIONS.replace("readonly idempotency:", "readonly idempotency?:").replace("readonly request:", "readonly request?:") : INSERT_CLIENT_DECLARATIONS : ""}${anonymousTables.length ? ANONYMOUS_CLIENT_DECLARATIONS : ""}${intakeTables.length ? INTAKE_CLIENT_DECLARATIONS : ""} export class DataError extends Error { readonly status: number; readonly code: string | null;${receiptCapable ? " readonly request?: InsertRequest<unknown>; readonly outcome?: string; readonly write_committed?: boolean; readonly retry?: false; readonly retryable?: false; readonly idempotency?: InsertReceipt;" : ""} constructor(status: number, payload: unknown); }
|
|
443
628
|
export const data: { ${declarations.join(";\n ")} };
|
|
444
629
|
}
|
|
445
630
|
`;
|
|
446
631
|
const runtime = `const contract=${JSON.stringify(contract_digest)};
|
|
447
632
|
class DataError extends Error{constructor(status,payload){super(payload&&typeof payload.message==="string"?payload.message:payload&&typeof payload.error==="string"?payload.error:"Data operation failed");this.name="DataError";this.status=status;this.code=payload&&typeof payload.error==="string"?payload.error:null}}
|
|
448
633
|
const invoke=async(table,operation,input)=>{const response=await fetch("/__sw/data",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({...input,contract,table,operation})});const payload=await response.json().catch(()=>{throw new DataError(response.status,{error:"INVALID_DATA_RESPONSE",message:"Data operation returned an invalid response"})});if(!response.ok)throw new DataError(response.status,payload);return payload};
|
|
449
|
-
${receiptCapable ? INSERT_CLIENT_RUNTIME + "const receiptTables=" + JSON.stringify(receiptTables) + ";\n" : ""}${linkedSpec.length ? LINK_CLIENT_RUNTIME : ""}const data=Object.freeze(Object.fromEntries(${JSON.stringify(runtimeTables)}.map(([table,operations,relations])=>{const entries=operations.map(operation=>[operation,operation==="list"||operation==="aggregate"?(options={})=>invoke(table,operation,options):operation==="create"?${receiptCapable ? "(values,...extra)=>createWithReceipt(table,values,extra,receiptTables.includes(table))" : "values=>invoke(table,operation,{values})"}:operation==="update"?(id,values)=>invoke(table,operation,{id,values}):operation==="createLink"?(id,options)=>createLink(table,id,options):operation==="links"?id=>invoke(table,"link_list",{id}):operation==="revokeLink"?(id,link_id)=>invoke(table,"link_revoke",{id,link_id}):id=>invoke(table,operation,{id})]);if(relations.length)entries.push(["relations",Object.freeze(Object.fromEntries(relations.map(relation=>[relation,Object.freeze({list:(parent_id,options={})=>invoke(table,"relation_list",{...options,relation,parent_id})})])))]);return[table,Object.freeze(Object.fromEntries(entries))];}).concat(${linkedSpec.length ? `[["links",links],["linked",linkedView(${JSON.stringify(linkedSpec)})]]` : "[]"})));
|
|
634
|
+
${receiptCapable ? INSERT_CLIENT_RUNTIME + "const receiptTables=" + JSON.stringify(receiptTables) + ";\n" : ""}${anonymousTables.length ? ANONYMOUS_CLIENT_RUNTIME + CREATOR_CLIENT_RUNTIME : ""}${intakeTables.length ? INTAKE_CLIENT_RUNTIME : ""}${linkedSpec.length ? LINK_CLIENT_RUNTIME : ""}const data=Object.freeze(Object.fromEntries(${JSON.stringify(runtimeTables)}.map(([table,operations,relations])=>{const entries=operations.map(operation=>[operation,operation==="list"||operation==="aggregate"?(options={})=>invoke(table,operation,options):operation==="create"?${receiptCapable ? "(values,...extra)=>createWithReceipt(table,values,extra,receiptTables.includes(table))" : "values=>invoke(table,operation,{values})"}:${anonymousTables.length ? 'operation==="createAnonymous"?(values,...extra)=>createAnonymous(table,values,extra):' : ""}${intakeTables.length ? 'operation==="intake"?(reference,values,...extra)=>intake(table,reference,values,extra):' : ""}operation==="update"?(id,values)=>invoke(table,operation,{id,values}):operation==="createLink"?(id,options)=>createLink(table,id,options):operation==="links"?id=>invoke(table,"link_list",{id}):operation==="revokeLink"?(id,link_id)=>invoke(table,"link_revoke",{id,link_id}):id=>invoke(table,operation,{id})]);if(relations.length)entries.push(["relations",Object.freeze(Object.fromEntries(relations.map(relation=>[relation,Object.freeze({list:(parent_id,options={})=>invoke(table,"relation_list",{...options,relation,parent_id})})])))]);return[table,Object.freeze(Object.fromEntries(entries))];}).concat(${linkedSpec.length ? `[["links",links],["linked",linkedView(${JSON.stringify(linkedSpec)})]]` : "[]"})${creatorSpec.length ? `.concat([["creators",creators],["creator",creatorView(${JSON.stringify(creatorSpec)})]])` : ""}));
|
|
450
635
|
export{data,DataError};
|
|
451
636
|
`;
|
|
452
637
|
return { contract_digest, declaration, runtime, manifest: { version: 1, contract_digest, tables, declaration, ...insertReceiptCapability === void 0 ? {} : { insert_receipt: insertReceiptCapability } } };
|
|
@@ -3446,7 +3631,7 @@ interface SomewhereEndpointConfig<Auth extends SomewhereEndpointAuth, Schema ext
|
|
|
3446
3631
|
if (owner && !columns.some((column) => column.n === owner)) columns.push({ n: owner, t: "text", optional: false, identity: true, type: "string" });
|
|
3447
3632
|
const declared = columns.filter((column) => !column.identity);
|
|
3448
3633
|
const relations = (table.relations || []).filter((relation) => Object.prototype.hasOwnProperty.call(schema, relation.table)).map((relation) => key(relation.name) + ": SomewhereDeclaredTables[" + key(relation.table) + "]['row']" + (relation.kind === "belongsTo" ? " | null" : "[]"));
|
|
3449
|
-
return " " + key(name) + ": {\n row: " + shape(columns.map((column) => field(column, false))) + ";\n insert: " + shape(declared.map((column) => field(column, column.optional))) + ";\n serverInsert: " + shape(columns.map((column) => field(column, column.optional
|
|
3634
|
+
return " " + key(name) + ": {\n row: " + shape(columns.map((column) => field(column, false))) + ";\n insert: " + shape(declared.map((column) => field(column, column.optional))) + ";\n serverInsert: " + shape(columns.map((column) => field(column, column.optional))) + ";\n set: " + shape(declared.map((column) => field(column, true))) + ";\n serverSet: " + shape(columns.map((column) => field(column, true))) + ";\n numeric: " + union(declared.filter((column) => column.t === "integer" || column.t === "number")) + ";\n scalar: " + union(declared.filter((column) => column.t !== "json" && column.t !== "blob")) + ";\n relations: " + (relations.length ? shape(relations) : "{}") + ";\n };\n";
|
|
3450
3635
|
});
|
|
3451
3636
|
return "interface SomewhereDeclaredTables {\n" + entries.join("") + "}\n";
|
|
3452
3637
|
}
|
|
@@ -3647,9 +3832,10 @@ var require_schema_types = __commonJS({
|
|
|
3647
3832
|
identity?: 'authenticated' | 'visitor'; read?: boolean | readonly Field[]; publicRead?: boolean | { where: Partial<Record<Field, string | number | boolean | null>> };
|
|
3648
3833
|
create?: readonly Field[] | false | null; update?: readonly Field[] | false | null; delete?: boolean;
|
|
3649
3834
|
links?: ClientLinkPermissions<Field>;
|
|
3835
|
+
intake?: { target: { table: string; field: string }; fields: readonly Field[]; where?: Record<string, string | number | boolean | null> };
|
|
3650
3836
|
}
|
|
3651
3837
|
interface ClientLinkPermissions<Field extends string> {
|
|
3652
|
-
read: true | readonly Field[]; edit?: readonly Field[] | false; children?: readonly string[]; maxDays?: number;
|
|
3838
|
+
read: true | readonly Field[]; edit?: readonly Field[] | false; children?: readonly string[]; maxDays?: number; anonymousCreate?: boolean;
|
|
3653
3839
|
}
|
|
3654
3840
|
interface FileCollection { readonly __somewhereFileCollection: unique symbol }
|
|
3655
3841
|
type FileOperation = 'read' | 'upload' | 'replace' | 'delete';
|
|
@@ -3721,9 +3907,6 @@ __export(declared_data_vendor_entry_exports, {
|
|
|
3721
3907
|
});
|
|
3722
3908
|
module.exports = __toCommonJS(declared_data_vendor_entry_exports);
|
|
3723
3909
|
|
|
3724
|
-
// worker/src/utils/db-schema-deploy/schema-ownership.ts
|
|
3725
|
-
var SHARED_AUTHOR_COLUMN = "_sw_author_id";
|
|
3726
|
-
|
|
3727
3910
|
// worker/src/utils/db-schema-deploy/bigint-text.ts
|
|
3728
3911
|
function isCanonicalBigintText(value) {
|
|
3729
3912
|
if (!/^(0|-?[1-9][0-9]*)$/.test(value)) return false;
|
|
@@ -3741,7 +3924,7 @@ function parseClientPermissions(value, columns, scope) {
|
|
|
3741
3924
|
}
|
|
3742
3925
|
const input = value;
|
|
3743
3926
|
for (const key of Object.keys(input)) {
|
|
3744
|
-
if (!["identity", "read", "publicRead", "create", "update", "delete", "links"].includes(key)) {
|
|
3927
|
+
if (!["identity", "read", "publicRead", "create", "update", "delete", "links", "intake"].includes(key)) {
|
|
3745
3928
|
return fail(`Unknown client permission "${key}".`);
|
|
3746
3929
|
}
|
|
3747
3930
|
}
|
|
@@ -3763,25 +3946,9 @@ function parseClientPermissions(value, columns, scope) {
|
|
|
3763
3946
|
if (!rawPublicRead || typeof rawPublicRead !== "object" || Array.isArray(rawPublicRead) || Object.keys(rawPublicRead).some((key) => key !== "where")) {
|
|
3764
3947
|
return fail("client.publicRead must be true, false, or { where: { field: literal } }.");
|
|
3765
3948
|
}
|
|
3766
|
-
const where = rawPublicRead.where;
|
|
3767
|
-
if (
|
|
3768
|
-
|
|
3769
|
-
if (entries.length === 0 || entries.length > 8) return fail("client.publicRead.where must declare 1 to 8 equality fields.");
|
|
3770
|
-
const normalized = {};
|
|
3771
|
-
for (const [rawName, literal] of entries) {
|
|
3772
|
-
const name = rawName.toLowerCase();
|
|
3773
|
-
const column = columns.find((candidate) => candidate.name === name);
|
|
3774
|
-
if (Object.prototype.hasOwnProperty.call(normalized, name)) return fail(`client.publicRead.where declares field "${rawName}" twice.`);
|
|
3775
|
-
if (!column || ["json", "blob"].includes(column.helper)) return fail(`client.publicRead.where names undeclared or non-scalar field "${rawName}".`);
|
|
3776
|
-
if (!(literal === null || typeof literal === "boolean" || typeof literal === "string" || typeof literal === "number" && Number.isFinite(literal))) return fail(`client.publicRead.where field "${rawName}" must equal a literal scalar.`);
|
|
3777
|
-
if (typeof literal === "string" && literal.length > 256) return fail(`client.publicRead.where field "${rawName}" exceeds 256 characters.`);
|
|
3778
|
-
if (literal === null && !column.nullable) return fail(`client.publicRead.where field "${rawName}" cannot equal null because it is required.`);
|
|
3779
|
-
if (literal !== null && (column.helper === "boolean" && typeof literal !== "boolean" || ["integer", "number"].includes(column.helper) && typeof literal !== "number" || column.helper === "integer" && !Number.isSafeInteger(literal) || column.helper === "bigint" && (typeof literal !== "string" || !isCanonicalBigintText(literal)) || ["text", "timestamp"].includes(column.helper) && typeof literal !== "string")) {
|
|
3780
|
-
return fail(`client.publicRead.where field "${rawName}" must match its declared type.`);
|
|
3781
|
-
}
|
|
3782
|
-
normalized[name] = literal;
|
|
3783
|
-
}
|
|
3784
|
-
publicRead = { where: Object.fromEntries(Object.entries(normalized).sort(([a], [b]) => a.localeCompare(b))) };
|
|
3949
|
+
const where = parseEqualityWhere(rawPublicRead.where, columns, "client.publicRead.where");
|
|
3950
|
+
if (typeof where === "string") return fail(where);
|
|
3951
|
+
publicRead = { where };
|
|
3785
3952
|
}
|
|
3786
3953
|
if (read !== true && read !== false && !Array.isArray(read)) return fail("client.read must list readable fields, or be true or false.");
|
|
3787
3954
|
if (publicRead && (!Array.isArray(read) || read.length === 0)) {
|
|
@@ -3829,17 +3996,8 @@ function parseClientPermissions(value, columns, scope) {
|
|
|
3829
3996
|
writes[operation] = allowed.sort();
|
|
3830
3997
|
}
|
|
3831
3998
|
if (writes.create !== null) {
|
|
3832
|
-
if (typeof publicRead === "object") {
|
|
3833
|
-
|
|
3834
|
-
for (const [name, publishedValue] of Object.entries(publicRead.where)) {
|
|
3835
|
-
const column = fields.get(name);
|
|
3836
|
-
if (column.autoNow) continue;
|
|
3837
|
-
const defaultValue = column.hasDefault ? column.default : column.nullable ? null : void 0;
|
|
3838
|
-
if (defaultValue !== void 0 && defaultValue !== publishedValue) guaranteedPrivate = true;
|
|
3839
|
-
}
|
|
3840
|
-
if (!guaranteedPrivate) {
|
|
3841
|
-
return fail("client.create has no fixed publication-field default that guarantees a private row. Give at least one predicate field a private default, or use a server operation.");
|
|
3842
|
-
}
|
|
3999
|
+
if (typeof publicRead === "object" && !privateByDefault(publicRead.where, fields)) {
|
|
4000
|
+
return fail("client.create has no fixed publication-field default that guarantees a private row. Give at least one predicate field a private default, or use a server operation.");
|
|
3843
4001
|
}
|
|
3844
4002
|
for (const column of columns) {
|
|
3845
4003
|
if (column.helper !== "id" && !column.nullable && !column.hasDefault && !column.autoNow && !writes.create.includes(column.name)) {
|
|
@@ -3849,11 +4007,97 @@ function parseClientPermissions(value, columns, scope) {
|
|
|
3849
4007
|
}
|
|
3850
4008
|
let links;
|
|
3851
4009
|
if (input.links !== void 0) {
|
|
3852
|
-
const parsed = parseLinkPermissions(input.links, read, writes.update, columns, scope);
|
|
4010
|
+
const parsed = parseLinkPermissions(input.links, read, writes.update, writes.create, columns, scope);
|
|
3853
4011
|
if (typeof parsed === "string") return fail(parsed);
|
|
3854
4012
|
links = parsed;
|
|
3855
4013
|
}
|
|
3856
|
-
|
|
4014
|
+
let intake;
|
|
4015
|
+
if (input.intake !== void 0) {
|
|
4016
|
+
const parsed = parseIntakePermissions(input.intake, columns, scope, publicRead);
|
|
4017
|
+
if (typeof parsed === "string") return fail(parsed);
|
|
4018
|
+
intake = parsed;
|
|
4019
|
+
}
|
|
4020
|
+
return { ok: true, permissions: { identity, read, publicRead, ...writes, delete: remove, ...links ? { links } : {}, ...intake ? { intake } : {} } };
|
|
4021
|
+
}
|
|
4022
|
+
function parseEqualityWhere(where, columns, label) {
|
|
4023
|
+
if (!where || typeof where !== "object" || Array.isArray(where)) return `${label} must be a non-empty object.`;
|
|
4024
|
+
const entries = Object.entries(where);
|
|
4025
|
+
if (entries.length === 0 || entries.length > 8) return `${label} must declare 1 to 8 equality fields.`;
|
|
4026
|
+
const normalized = {};
|
|
4027
|
+
for (const [rawName, literal] of entries) {
|
|
4028
|
+
const name = rawName.toLowerCase();
|
|
4029
|
+
const column = columns?.find((candidate) => candidate.name === name);
|
|
4030
|
+
if (Object.prototype.hasOwnProperty.call(normalized, name)) return `${label} declares field "${rawName}" twice.`;
|
|
4031
|
+
if (columns && (!column || ["json", "blob"].includes(column.helper))) return `${label} names undeclared or non-scalar field "${rawName}".`;
|
|
4032
|
+
if (!(literal === null || typeof literal === "boolean" || typeof literal === "string" || typeof literal === "number" && Number.isFinite(literal))) return `${label} field "${rawName}" must equal a literal scalar.`;
|
|
4033
|
+
if (typeof literal === "string" && literal.length > 256) return `${label} field "${rawName}" exceeds 256 characters.`;
|
|
4034
|
+
if (column && literal === null && !column.nullable) return `${label} field "${rawName}" cannot equal null because it is required.`;
|
|
4035
|
+
if (column && literal !== null && (column.helper === "boolean" && typeof literal !== "boolean" || ["integer", "number"].includes(column.helper) && typeof literal !== "number" || column.helper === "integer" && !Number.isSafeInteger(literal) || column.helper === "bigint" && (typeof literal !== "string" || !isCanonicalBigintText(literal)) || ["text", "timestamp"].includes(column.helper) && typeof literal !== "string")) {
|
|
4036
|
+
return `${label} field "${rawName}" must match its declared type.`;
|
|
4037
|
+
}
|
|
4038
|
+
normalized[name] = literal;
|
|
4039
|
+
}
|
|
4040
|
+
return Object.fromEntries(Object.entries(normalized).sort(([a], [b]) => a.localeCompare(b)));
|
|
4041
|
+
}
|
|
4042
|
+
function privateByDefault(where, fields) {
|
|
4043
|
+
for (const [name, publishedValue] of Object.entries(where)) {
|
|
4044
|
+
const column = fields.get(name);
|
|
4045
|
+
if (column.autoNow) continue;
|
|
4046
|
+
const defaultValue = column.hasDefault ? column.default : column.nullable ? null : void 0;
|
|
4047
|
+
if (defaultValue !== void 0 && defaultValue !== publishedValue) return true;
|
|
4048
|
+
}
|
|
4049
|
+
return false;
|
|
4050
|
+
}
|
|
4051
|
+
function parseIntakePermissions(value, columns, scope, publicRead) {
|
|
4052
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "client.intake must be an object: { target: { table, field }, fields, where? }.";
|
|
4053
|
+
const input = value;
|
|
4054
|
+
for (const key of Object.keys(input)) {
|
|
4055
|
+
if (!["target", "fields", "where"].includes(key)) return `Unknown client.intake option "${key}". Allowed: target, fields, where.`;
|
|
4056
|
+
}
|
|
4057
|
+
if (scope.kind !== "owner" || scope.visitors === true) return "client.intake needs owner() without visitors: each accepted row belongs to the target row's owner.";
|
|
4058
|
+
const id = columns.find((column) => column.helper === "id");
|
|
4059
|
+
if (!id || id.uuid === true) return "client.intake needs an integer id(), not id({ uuid: true }).";
|
|
4060
|
+
if (publicRead === true) return "client.intake cannot accept rows into a table whose rows are all public (client.publicRead: true).";
|
|
4061
|
+
const target = input.target;
|
|
4062
|
+
if (!target || typeof target !== "object" || Array.isArray(target) || Object.keys(target).sort().join() !== "field,table") {
|
|
4063
|
+
return "client.intake.target must be { table, field }: the public table and its unique reference field.";
|
|
4064
|
+
}
|
|
4065
|
+
const { table, field } = target;
|
|
4066
|
+
if (typeof table !== "string" || !/^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(table) || typeof field !== "string" || !/^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(field)) {
|
|
4067
|
+
return "client.intake.target must name a table and one of its fields.";
|
|
4068
|
+
}
|
|
4069
|
+
if (!Array.isArray(input.fields) || input.fields.length === 0) return "client.intake.fields must list at least one field a submission supplies.";
|
|
4070
|
+
const byName2 = new Map(columns.map((column) => [column.name, column]));
|
|
4071
|
+
const fields = [];
|
|
4072
|
+
for (const entry of input.fields) {
|
|
4073
|
+
if (typeof entry !== "string") return "client.intake.fields must be column names.";
|
|
4074
|
+
const name = entry.toLowerCase();
|
|
4075
|
+
const column = byName2.get(name);
|
|
4076
|
+
if (!column) return `client.intake.fields names undeclared or platform-managed field "${entry}".`;
|
|
4077
|
+
if (column.helper === "id" || name === scope.column) return `client.intake.fields cannot set the platform-assigned identity field "${entry}".`;
|
|
4078
|
+
if (column.helper === "blob") return `client.intake.fields cannot accept binary field "${entry}". Use project files for uploads.`;
|
|
4079
|
+
if (column.autoNow) return `client.intake.fields cannot set "${entry}", which the platform fills in.`;
|
|
4080
|
+
if (typeof publicRead === "object" && Object.prototype.hasOwnProperty.call(publicRead.where, name)) {
|
|
4081
|
+
return `client.intake.fields cannot set publication field "${entry}".`;
|
|
4082
|
+
}
|
|
4083
|
+
if (fields.includes(name)) return `client.intake.fields declares field "${entry}" twice.`;
|
|
4084
|
+
fields.push(name);
|
|
4085
|
+
}
|
|
4086
|
+
for (const column of columns) {
|
|
4087
|
+
if (column.helper !== "id" && !column.nullable && !column.hasDefault && !column.autoNow && !fields.includes(column.name)) {
|
|
4088
|
+
return `client.intake.fields must include required field "${column.name}", or that field needs a declared default.`;
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
if (typeof publicRead === "object" && !privateByDefault(publicRead.where, byName2)) {
|
|
4092
|
+
return "client.intake has no fixed publication-field default that guarantees a private row. Give at least one predicate field a private default.";
|
|
4093
|
+
}
|
|
4094
|
+
let where;
|
|
4095
|
+
if (input.where !== void 0) {
|
|
4096
|
+
const parsed = parseEqualityWhere(input.where, null, "client.intake.where");
|
|
4097
|
+
if (typeof parsed === "string") return parsed;
|
|
4098
|
+
where = parsed;
|
|
4099
|
+
}
|
|
4100
|
+
return { target: { table: table.toLowerCase(), field: field.toLowerCase() }, fields: fields.sort(), ...where ? { where } : {} };
|
|
3857
4101
|
}
|
|
3858
4102
|
function authoredClientFromCanonical(client) {
|
|
3859
4103
|
if (!client || typeof client !== "object" || Array.isArray(client)) return client;
|
|
@@ -3861,16 +4105,17 @@ function authoredClientFromCanonical(client) {
|
|
|
3861
4105
|
if (!links || typeof links !== "object" || Array.isArray(links)) return client;
|
|
3862
4106
|
const l = links;
|
|
3863
4107
|
const keys = Object.keys(l).sort().join(",");
|
|
3864
|
-
if (keys !== "children,edit,maxDays,read" || !Array.isArray(l.read) || !Array.isArray(l.edit) || !Array.isArray(l.children) || !(l.maxDays === null || typeof l.maxDays === "number")) return client;
|
|
4108
|
+
if (keys !== "children,edit,maxDays,read" && !(keys === "anonymousCreate,children,edit,maxDays,read" && l.anonymousCreate === true) || !Array.isArray(l.read) || !Array.isArray(l.edit) || !Array.isArray(l.children) || !(l.maxDays === null || typeof l.maxDays === "number")) return client;
|
|
3865
4109
|
const authored = { read: l.read, edit: l.edit.length === 0 ? false : l.edit, children: l.children };
|
|
3866
4110
|
if (l.maxDays !== null) authored.maxDays = l.maxDays;
|
|
4111
|
+
if (l.anonymousCreate === true) authored.anonymousCreate = true;
|
|
3867
4112
|
return { ...client, links: authored };
|
|
3868
4113
|
}
|
|
3869
|
-
function parseLinkPermissions(value, read, update, columns, scope) {
|
|
3870
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return "client.links must be an object: { read, edit?, children?, maxDays? }.";
|
|
4114
|
+
function parseLinkPermissions(value, read, update, create, columns, scope) {
|
|
4115
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "client.links must be an object: { read, edit?, children?, maxDays?, anonymousCreate? }.";
|
|
3871
4116
|
const input = value;
|
|
3872
4117
|
for (const key2 of Object.keys(input)) {
|
|
3873
|
-
if (!["read", "edit", "children", "maxDays"].includes(key2)) return `Unknown client.links option "${key2}". Allowed: read, edit, children, maxDays.`;
|
|
4118
|
+
if (!["read", "edit", "children", "maxDays", "anonymousCreate"].includes(key2)) return `Unknown client.links option "${key2}". Allowed: read, edit, children, maxDays, anonymousCreate.`;
|
|
3874
4119
|
}
|
|
3875
4120
|
const owned = scope.kind === "owner" && scope.visitors !== true || scope.kind === "policy" && typeof scope.column === "string";
|
|
3876
4121
|
if (!owned) return "client.links needs rows with one signed-in owner: owner() (without visitors) or anyOf(owner(), ...).";
|
|
@@ -3917,9 +4162,64 @@ function parseLinkPermissions(value, read, update, columns, scope) {
|
|
|
3917
4162
|
}
|
|
3918
4163
|
maxDays = input.maxDays;
|
|
3919
4164
|
}
|
|
3920
|
-
return
|
|
4165
|
+
if (input.anonymousCreate !== void 0 && typeof input.anonymousCreate !== "boolean") return "client.links.anonymousCreate must be true or false.";
|
|
4166
|
+
if (input.anonymousCreate === true) {
|
|
4167
|
+
if (scope.kind !== "owner" || scope.visitors === true) return "client.links.anonymousCreate needs owner() without visitors.";
|
|
4168
|
+
if (!create || create.length === 0) return "client.links.anonymousCreate needs client.create: it creates rows with the fields the app data client creates.";
|
|
4169
|
+
if (columns.find((column) => column.helper === "id")?.uuid === true) return "client.links.anonymousCreate needs an integer id(), not id({ uuid: true }).";
|
|
4170
|
+
if (columns.some((column) => column.helper === "blob")) return "client.links.anonymousCreate is not available on a table with a blob() column.";
|
|
4171
|
+
}
|
|
4172
|
+
return { read: linkRead, edit, children, maxDays, ...input.anonymousCreate === true ? { anonymousCreate: true } : {} };
|
|
4173
|
+
}
|
|
4174
|
+
|
|
4175
|
+
// worker/src/utils/authority/intake-bake.ts
|
|
4176
|
+
function record(value) {
|
|
4177
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4178
|
+
}
|
|
4179
|
+
function bakeIntakePermissions(schema, declarations, intents, scopes) {
|
|
4180
|
+
const membershipTables = /* @__PURE__ */ new Set();
|
|
4181
|
+
const members = (policy) => {
|
|
4182
|
+
if (policy.k === "m") membershipTables.add(policy.m.m);
|
|
4183
|
+
else if (policy.k === "a") policy.p.forEach(members);
|
|
4184
|
+
else if (policy.k === "p") members(policy.p);
|
|
4185
|
+
};
|
|
4186
|
+
for (const table of Object.values(schema)) {
|
|
4187
|
+
if (table.member) membershipTables.add(table.member.m);
|
|
4188
|
+
if (table.policy) members(table.policy);
|
|
4189
|
+
}
|
|
4190
|
+
for (const [name, table] of Object.entries(schema)) {
|
|
4191
|
+
const intake = table.client?.intake;
|
|
4192
|
+
if (!intake) continue;
|
|
4193
|
+
let valid = false;
|
|
4194
|
+
const target = schema[intake.target.table];
|
|
4195
|
+
try {
|
|
4196
|
+
const declared = record(JSON.parse(declarations[intake.target.table]));
|
|
4197
|
+
const scope = record(declared?.scope);
|
|
4198
|
+
const destination = record(JSON.parse(declarations[name]));
|
|
4199
|
+
const destinationScope = record(destination?.scope);
|
|
4200
|
+
const rawColumns = declared?.columns;
|
|
4201
|
+
const matches = Array.isArray(rawColumns) ? rawColumns.map(record).filter((c) => c?.name === intake.target.field) : [];
|
|
4202
|
+
const column = matches.length === 1 ? matches[0] : null;
|
|
4203
|
+
const bakedColumn = target?.columns.find((c) => c.n === intake.target.field);
|
|
4204
|
+
const owner = scope?.column;
|
|
4205
|
+
if (!membershipTables.has(name) && destination?.name === name && destinationScope?.kind === "owner" && destinationScope.column === scopes[name] && declared?.name === intake.target.table && scope?.kind === "owner" && scope.visitors !== true && typeof owner === "string" && scopes[intake.target.table] === owner && intents[intake.target.table] === "scoped" && intents[name] === "scoped" && scopes[name] && !table.visitors && !table.member && !table.policy && target && !target.visitors && !target.member && !target.policy && target.client?.publicRead && Array.isArray(target.client.read) && target.client.read.includes(intake.target.field) && column && column.nullable === false && ["id", "text", "integer", "bigint"].includes(String(column.helper)) && (column.helper === "id" || column.unique === true) && bakedColumn && !bakedColumn.nul && bakedColumn.t === (column.helper === "id" ? column.uuid === true ? "text" : "integer" : column.helper)) {
|
|
4206
|
+
const predicateColumns = rawColumns;
|
|
4207
|
+
const columns = predicateColumns.map((c) => ({ name: String(c.name), helper: String(c.helper), nullable: c.nullable === true }));
|
|
4208
|
+
valid = !intake.where || typeof parseEqualityWhere(intake.where, columns, "client.intake.where") !== "string";
|
|
4209
|
+
if (valid) target.columns = target.columns.map((c) => c.n === intake.target.field ? { ...c, u: 1 } : c);
|
|
4210
|
+
}
|
|
4211
|
+
} catch {
|
|
4212
|
+
}
|
|
4213
|
+
if (!valid && table.client) {
|
|
4214
|
+
const { intake: _intake, ...client } = table.client;
|
|
4215
|
+
table.client = client;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
3921
4218
|
}
|
|
3922
4219
|
|
|
4220
|
+
// worker/src/utils/db-schema-deploy/schema-ownership.ts
|
|
4221
|
+
var SHARED_AUTHOR_COLUMN = "_sw_author_id";
|
|
4222
|
+
|
|
3923
4223
|
// worker/src/services/jobs/limits.ts
|
|
3924
4224
|
var STALE_JOB_WINDOW_MS = 45 * 60 * 1e3;
|
|
3925
4225
|
|
|
@@ -4117,8 +4417,8 @@ function validateBindings(input, tableInfo, errors) {
|
|
|
4117
4417
|
}
|
|
4118
4418
|
if (c.helper !== helper || c.nullable) errors.push(`${at(p, field)}payment binding "${p.name}": "${p.table}"."${name}" must be ${what}.`);
|
|
4119
4419
|
if (info.identity.includes(name)) errors.push(`${at(p, field)}payment binding "${p.name}": "${p.table}"."${name}" is the table's access column; a payment never moves a row.`);
|
|
4120
|
-
const writable = [...info.table.client?.create ?? [], ...info.table.client?.update ?? []];
|
|
4121
|
-
if (writable.includes(name)) errors.push(`${at(p, field)}payment binding "${p.name}": "${p.table}"."${name}" is browser-writable through client.create or client.
|
|
4420
|
+
const writable = [...info.table.client?.create ?? [], ...info.table.client?.update ?? [], ...info.table.client?.intake?.fields ?? []];
|
|
4421
|
+
if (writable.includes(name)) errors.push(`${at(p, field)}payment binding "${p.name}": "${p.table}"."${name}" is browser-writable through client.create, client.update or client.intake. Remove it there; the server sets prices and the payment sets the status.`);
|
|
4122
4422
|
}
|
|
4123
4423
|
if ((/* @__PURE__ */ new Set([p.amount, p.currency, p.status.column])).size !== 3) errors.push(`${at(p, "")}payment binding "${p.name}" must name three different columns for amount, currency and status.`);
|
|
4124
4424
|
const status = column(p.status.column);
|
|
@@ -4185,6 +4485,7 @@ function bakedTableSchemaFromDeclared(declaredJson) {
|
|
|
4185
4485
|
permissionColumns.push({
|
|
4186
4486
|
name: entry.n,
|
|
4187
4487
|
helper: col.helper,
|
|
4488
|
+
...col.uuid === true ? { uuid: true } : {},
|
|
4188
4489
|
nullable: col.nullable === true,
|
|
4189
4490
|
hasDefault: col.hasDefault === true,
|
|
4190
4491
|
autoNow: col.autoNow === true,
|
|
@@ -4734,6 +5035,56 @@ function validateRowLinks(tables, tableByName, errors) {
|
|
|
4734
5035
|
}
|
|
4735
5036
|
}
|
|
4736
5037
|
|
|
5038
|
+
// worker/src/utils/db-schema-deploy/extract-schema-intake.ts
|
|
5039
|
+
var REFERENCE_HELPERS = ["id", "text", "integer", "bigint"];
|
|
5040
|
+
function validateIntake(tables, tableByName, errors) {
|
|
5041
|
+
for (const t of tables) {
|
|
5042
|
+
const intake = t.client?.intake;
|
|
5043
|
+
if (!intake) continue;
|
|
5044
|
+
const at = `Table "${t.name}" client.intake`;
|
|
5045
|
+
const target = tableByName.get(intake.target.table);
|
|
5046
|
+
if (!target) {
|
|
5047
|
+
errors.push(`${at} targets "${intake.target.table}", which is not a table declared in db/schema.ts.`);
|
|
5048
|
+
continue;
|
|
5049
|
+
}
|
|
5050
|
+
if (target.scope.kind !== "owner" || target.scope.visitors === true) {
|
|
5051
|
+
errors.push(`${at} targets "${target.name}", which must be scoped owner() without visitors: its owner receives the submissions.`);
|
|
5052
|
+
continue;
|
|
5053
|
+
}
|
|
5054
|
+
const client = target.client;
|
|
5055
|
+
if (!client || !client.publicRead || !Array.isArray(client.read)) {
|
|
5056
|
+
errors.push(`${at} targets "${target.name}", which declares no client.publicRead. Only a published table can receive public submissions.`);
|
|
5057
|
+
continue;
|
|
5058
|
+
}
|
|
5059
|
+
const field = intake.target.field;
|
|
5060
|
+
const column = target.columns.find((c) => c.name === field);
|
|
5061
|
+
if (!column) {
|
|
5062
|
+
errors.push(`${at} names reference "${field}", which is not a declared column of "${target.name}".`);
|
|
5063
|
+
continue;
|
|
5064
|
+
}
|
|
5065
|
+
if (!client.read.includes(field)) {
|
|
5066
|
+
errors.push(`${at} names reference "${field}", which "${target.name}" does not list in client.read. The reference must be a public field.`);
|
|
5067
|
+
continue;
|
|
5068
|
+
}
|
|
5069
|
+
if (!REFERENCE_HELPERS.includes(column.helper)) {
|
|
5070
|
+
errors.push(`${at} names reference "${field}", a ${column.helper} column. A reference is an id, text, integer or bigint column.`);
|
|
5071
|
+
continue;
|
|
5072
|
+
}
|
|
5073
|
+
if (column.helper !== "id" && !column.unique) {
|
|
5074
|
+
errors.push(`${at} names reference "${field}", which is not unique on "${target.name}". Declare it { unique: true }; a reference must name one row.`);
|
|
5075
|
+
continue;
|
|
5076
|
+
}
|
|
5077
|
+
if (column.nullable) {
|
|
5078
|
+
errors.push(`${at} names reference "${field}", which is nullable on "${target.name}". A reference must be required.`);
|
|
5079
|
+
continue;
|
|
5080
|
+
}
|
|
5081
|
+
if (intake.where) {
|
|
5082
|
+
const typed = parseEqualityWhere(intake.where, target.columns, "client.intake.where");
|
|
5083
|
+
if (typeof typed === "string") errors.push(`${at} (target "${target.name}"): ${typed}`);
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
}
|
|
5087
|
+
|
|
4737
5088
|
// worker/src/utils/db-schema-deploy/extract-schema-files.ts
|
|
4738
5089
|
var FILE_OPERATIONS = ["read", "upload", "replace", "delete"];
|
|
4739
5090
|
var MAX_FILE_COLLECTIONS = 20;
|
|
@@ -5742,7 +6093,7 @@ function readClientPermissions(r) {
|
|
|
5742
6093
|
}
|
|
5743
6094
|
out[key.name] = fields;
|
|
5744
6095
|
} else {
|
|
5745
|
-
out[key.name] =
|
|
6096
|
+
out[key.name] = ["links", "intake", "target", "where"].includes(key.name) && r.peek().kind === "punct" && r.peek().value === "{" ? readClientPermissions(r) : r.readLiteral(`for client.${key.name}`);
|
|
5746
6097
|
}
|
|
5747
6098
|
if (!r.tryPunct(",")) {
|
|
5748
6099
|
r.expectPunct("}", "closing client permissions");
|
|
@@ -6535,7 +6886,7 @@ function extractSchemaTs(source) {
|
|
|
6535
6886
|
continue;
|
|
6536
6887
|
}
|
|
6537
6888
|
const membershipCols = knownColumns(membershipTable);
|
|
6538
|
-
if (membershipTable.client && (membershipTable.client.create !== null || membershipTable.client.update !== null || membershipTable.client.delete)) {
|
|
6889
|
+
if (membershipTable.client && (membershipTable.client.create !== null || membershipTable.client.update !== null || membershipTable.client.delete || membershipTable.client.intake !== void 0)) {
|
|
6539
6890
|
errors.push(`Table "${sc.membership}" grants membership access to "${t.name}" and cannot allow client writes. Change membership through a server function.`);
|
|
6540
6891
|
}
|
|
6541
6892
|
if (!membershipCols.has(sc.memberUser)) {
|
|
@@ -6554,11 +6905,12 @@ function extractSchemaTs(source) {
|
|
|
6554
6905
|
}
|
|
6555
6906
|
validateDeclaredRelations(tables, tableByName, knownColumns, (table) => removedTables.includes(table) ? "removedTable()" : exportedTables.includes(table) ? "exported()" : null, errors);
|
|
6556
6907
|
validateRowLinks(tables, tableByName, errors);
|
|
6908
|
+
validateIntake(tables, tableByName, errors);
|
|
6557
6909
|
if (fileCollections) {
|
|
6558
6910
|
errors.push(...fileErrors);
|
|
6559
6911
|
validateFileCollections(fileCollections, (name) => {
|
|
6560
6912
|
const t = tableByName.get(name);
|
|
6561
|
-
return t ? { columns: knownColumns(t), clientWrites: Boolean(t.client && (t.client.create !== null || t.client.update !== null || t.client.delete)), parentTarget: fileParentTarget(t) } : null;
|
|
6913
|
+
return t ? { columns: knownColumns(t), clientWrites: Boolean(t.client && (t.client.create !== null || t.client.update !== null || t.client.delete || t.client.intake !== void 0)), parentTarget: fileParentTarget(t) } : null;
|
|
6562
6914
|
}, errors);
|
|
6563
6915
|
}
|
|
6564
6916
|
if (groupRoles || appRoles) errors.push(...validateDeclaredRoles(groupRoles, appRoles));
|
|
@@ -6655,6 +7007,7 @@ function schemaAuthorityFromSource(files) {
|
|
|
6655
7007
|
const ownerColumn = declaredOwnerColumn(table.scope);
|
|
6656
7008
|
if (declaredScopeIntent(table.scope) === "scoped" && ownerColumn) declareEntry(scopes, table.name, ownerColumn);
|
|
6657
7009
|
}
|
|
7010
|
+
bakeIntakePermissions(schema, Object.fromEntries(parsed.declaration.tables.map((table) => [table.name, JSON.stringify(canonicalTableShape(table))])), intents, scopes);
|
|
6658
7011
|
return { schema, intents, scopes };
|
|
6659
7012
|
}
|
|
6660
7013
|
function declaredFilesFromSource(files) {
|