@riffdb/better-auth 0.0.0-stage → 0.2.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/DESIGN.md +197 -0
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +27 -0
- package/README.md +191 -2
- package/dist/adapter.d.ts +28 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +1262 -0
- package/dist/adapter.js.map +1 -0
- package/dist/generated/client.d.ts +1925 -0
- package/dist/generated/client.d.ts.map +1 -0
- package/dist/generated/client.js +2044 -0
- package/dist/generated/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/profile-contract.d.ts +60 -0
- package/dist/profile-contract.d.ts.map +1 -0
- package/dist/profile-contract.js +535 -0
- package/dist/profile-contract.js.map +1 -0
- package/dist/profile-plan.d.ts +69 -0
- package/dist/profile-plan.d.ts.map +1 -0
- package/dist/profile-plan.js +180 -0
- package/dist/profile-plan.js.map +1 -0
- package/dist/profile.d.ts +47 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +131 -0
- package/dist/profile.js.map +1 -0
- package/dist/testing.d.ts +11 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +12 -0
- package/dist/testing.js.map +1 -0
- package/generated/go/client.go +1996 -0
- package/generated/mcp/tools.json +12352 -0
- package/generated/python/client.py +3877 -0
- package/generated/riffdb.application.exact.json +1 -0
- package/generated/riffdb.contract.bundle +0 -0
- package/generated/rust/client.rs +6028 -0
- package/package.json +62 -4
- package/profiles/organization-security/materialization.json +48 -0
- package/profiles/organization-security/riffdb/contract.riff +766 -0
- package/profiles/organization-security/riffdb/queries/find_account_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_invitation_by_email.riffq +17 -0
- package/profiles/organization-security/riffdb/queries/find_invitation_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_invitation_by_organization_id.riffq +17 -0
- package/profiles/organization-security/riffdb/queries/find_member_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_member_by_user_id.riffq +17 -0
- package/profiles/organization-security/riffdb/queries/find_organization_by_id.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_organization_by_slug.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_session_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_session_by_token.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_team_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_team_member_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_team_member_by_team_id.riffq +17 -0
- package/profiles/organization-security/riffdb/queries/find_two_factor_by_id.riffq +18 -0
- package/profiles/organization-security/riffdb/queries/find_two_factor_by_secret.riffq +17 -0
- package/profiles/organization-security/riffdb/queries/find_user_by_email.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_user_by_id.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_verification_by_id.riffq +16 -0
- package/profiles/organization-security/riffdb/queries/find_verification_by_identifier.riffq +17 -0
- package/profiles/organization-security/riffdb.application.json +167 -0
- package/profiles/organization-security/riffdb.toml +7 -0
- package/profiles/organization-security.profile.json +954 -0
- package/riffdb/contract.riff +489 -0
- package/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
- package/riffdb/queries/admin_users_contains_asc.riffq +24 -0
- package/riffdb/queries/admin_users_contains_desc.riffq +24 -0
- package/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
- package/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
- package/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
- package/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
- package/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
- package/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
- package/riffdb/queries/find_account_by_id.riffq +24 -0
- package/riffdb/queries/find_account_by_provider.riffq +26 -0
- package/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
- package/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
- package/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
- package/riffdb/queries/find_expired_verification_ids.riffq +17 -0
- package/riffdb/queries/find_latest_verification.riffq +20 -0
- package/riffdb/queries/find_session_by_id.riffq +20 -0
- package/riffdb/queries/find_session_by_token.riffq +20 -0
- package/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
- package/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
- package/riffdb/queries/find_user_by_email.riffq +16 -0
- package/riffdb/queries/find_user_by_id.riffq +15 -0
- package/riffdb/queries/find_verification_by_id.riffq +19 -0
- package/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
- package/riffdb.application.json +107 -0
- package/riffdb.application.lock.json +1 -0
- package/scripts/real-riffdb-runner.mjs +333 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Materializes a reviewed profile plan into RiffDB contract and query sources.
|
|
3
|
+
*
|
|
4
|
+
* The plan records what Better Auth resolved. This module turns that record
|
|
5
|
+
* into the compiled artifacts DESIGN requires before a plan can become a
|
|
6
|
+
* runtime profile: one contract, one named query per accepted call shape, and
|
|
7
|
+
* one application source binding them.
|
|
8
|
+
*
|
|
9
|
+
* It is deliberately not a schema pusher. The output is source a human reviews
|
|
10
|
+
* and compiles; the generator's contribution is that every safety property
|
|
11
|
+
* RiffDB can prove is declared, and every property it cannot prove is named in
|
|
12
|
+
* {@link RiffDBBetterAuthMaterialization.report} rather than silently dropped.
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_STRING_BOUND = 2_048;
|
|
15
|
+
const DEFAULT_BYTES_BOUND = 8_192;
|
|
16
|
+
const DEFAULT_LIST_BOUND = 32;
|
|
17
|
+
const DEFAULT_CASCADE_MAXIMUM = 32;
|
|
18
|
+
/**
|
|
19
|
+
* The tenant partition column.
|
|
20
|
+
*
|
|
21
|
+
* It is deliberately not `organization_id`: the Better Auth organization
|
|
22
|
+
* plugin contributes a model named `organization`, whose synthesized key
|
|
23
|
+
* column would then collide with the partition column.
|
|
24
|
+
*/
|
|
25
|
+
const PARTITION_FIELD = "tenant_id";
|
|
26
|
+
/** Cascade covers at most 32 relationships (SPEC DEL-004). */
|
|
27
|
+
const MAX_CASCADE_RELATIONSHIPS = 32;
|
|
28
|
+
/**
|
|
29
|
+
* SPEC DEL-004 bounds the whole cascaded graph:
|
|
30
|
+
* `root_count_maximum * (1 + sum(relationship maxima)) <= 256`.
|
|
31
|
+
*/
|
|
32
|
+
const MAX_CASCADE_GRAPH = 256;
|
|
33
|
+
/**
|
|
34
|
+
* The per-relationship cascade maximum an entity with `children` can afford.
|
|
35
|
+
*
|
|
36
|
+
* Deleting one root must stay inside {@link MAX_CASCADE_GRAPH}, so a wide
|
|
37
|
+
* aggregate lowers its per-relationship maximum rather than failing to
|
|
38
|
+
* compile.
|
|
39
|
+
*/
|
|
40
|
+
function cascadeMaximumFor(children, bounds) {
|
|
41
|
+
if (children === 0)
|
|
42
|
+
return bounds.cascadeMaximum;
|
|
43
|
+
return Math.max(1, Math.min(bounds.cascadeMaximum, Math.floor((MAX_CASCADE_GRAPH - 1) / children)));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* How many roots one bulk delete may name.
|
|
47
|
+
*
|
|
48
|
+
* A cascading delete pays for its whole discovered graph, so an aggregate with
|
|
49
|
+
* five children admits a single root per command — the same bound the
|
|
50
|
+
* hand-written core contract reaches for `DeleteUser`.
|
|
51
|
+
*/
|
|
52
|
+
function deleteRootBound(children, bounds) {
|
|
53
|
+
if (children === 0)
|
|
54
|
+
return bounds.cascadeMaximum;
|
|
55
|
+
const perRelationship = cascadeMaximumFor(children, bounds);
|
|
56
|
+
return Math.max(1, Math.floor(MAX_CASCADE_GRAPH / (1 + children * perRelationship)));
|
|
57
|
+
}
|
|
58
|
+
export class RiffDBBetterAuthMaterializationError extends Error {
|
|
59
|
+
code;
|
|
60
|
+
detail;
|
|
61
|
+
constructor(code, detail) {
|
|
62
|
+
super(`cannot materialize RiffDB Better Auth profile: ${code} (${detail})`);
|
|
63
|
+
this.code = code;
|
|
64
|
+
this.detail = detail;
|
|
65
|
+
this.name = "RiffDBBetterAuthMaterializationError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function reject(code, detail) {
|
|
69
|
+
throw new RiffDBBetterAuthMaterializationError(code, detail);
|
|
70
|
+
}
|
|
71
|
+
/** `twoFactor` -> `two_factor`; `organizationId` -> `organization_id`. */
|
|
72
|
+
function snake(name) {
|
|
73
|
+
return name
|
|
74
|
+
.replace(/([a-z0-9])([A-Z])/gu, "$1_$2")
|
|
75
|
+
.replace(/([A-Z]+)([A-Z][a-z])/gu, "$1_$2")
|
|
76
|
+
.toLowerCase();
|
|
77
|
+
}
|
|
78
|
+
/** `twoFactor` -> `TwoFactor`; `team_member` -> `TeamMember`. */
|
|
79
|
+
function pascal(name) {
|
|
80
|
+
return snake(name)
|
|
81
|
+
.split("_")
|
|
82
|
+
.filter((part) => part.length > 0)
|
|
83
|
+
.map((part) => part[0].toUpperCase() + part.slice(1))
|
|
84
|
+
.join("");
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The preferred synthesized primary-key column for one model, e.g. `user_id`.
|
|
88
|
+
*
|
|
89
|
+
* Better Auth schemas contain fields that snake-case onto this name — the
|
|
90
|
+
* `account` model carries its provider's own `accountId` — so the preference
|
|
91
|
+
* is resolved against the rest of the entity by {@link resolveKeyColumns}.
|
|
92
|
+
*/
|
|
93
|
+
function preferredKeyColumn(model) {
|
|
94
|
+
return `${snake(model)}_id`;
|
|
95
|
+
}
|
|
96
|
+
function resolveBounds(options) {
|
|
97
|
+
const bounded = (value, fallback, maximum) => {
|
|
98
|
+
if (value === undefined)
|
|
99
|
+
return fallback;
|
|
100
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) {
|
|
101
|
+
reject("invalid_materialization_option", `${value} is out of range`);
|
|
102
|
+
}
|
|
103
|
+
return value;
|
|
104
|
+
};
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
stringBound: bounded(options?.stringBound, DEFAULT_STRING_BOUND, 1_048_576),
|
|
107
|
+
bytesBound: bounded(options?.bytesBound, DEFAULT_BYTES_BOUND, 1_048_576),
|
|
108
|
+
listBound: bounded(options?.listBound, DEFAULT_LIST_BOUND, 1_024),
|
|
109
|
+
cascadeMaximum: bounded(options?.cascadeMaximum, DEFAULT_CASCADE_MAXIMUM, 256),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The RiffDB type for one planned field.
|
|
114
|
+
*
|
|
115
|
+
* A field that references another model carries that model's identifier, so it
|
|
116
|
+
* is a `uuid` regardless of the JavaScript type Better Auth reports.
|
|
117
|
+
*/
|
|
118
|
+
function fieldType(field, bounds) {
|
|
119
|
+
const base = (() => {
|
|
120
|
+
if (field.reference !== undefined)
|
|
121
|
+
return "uuid";
|
|
122
|
+
switch (field.type) {
|
|
123
|
+
case "boolean":
|
|
124
|
+
return "bool";
|
|
125
|
+
case "date":
|
|
126
|
+
return "timestamp";
|
|
127
|
+
case "number":
|
|
128
|
+
return "i64";
|
|
129
|
+
case "string":
|
|
130
|
+
return `string<${bounds.stringBound}>`;
|
|
131
|
+
case "json":
|
|
132
|
+
return `bytes<${bounds.bytesBound}>`;
|
|
133
|
+
case "string[]":
|
|
134
|
+
return `list<string<${bounds.stringBound}>, 0..${bounds.listBound}>`;
|
|
135
|
+
case "number[]":
|
|
136
|
+
return `list<i64, 0..${bounds.listBound}>`;
|
|
137
|
+
default:
|
|
138
|
+
return reject("unsupported_field_type", `${field.name}: ${String(field.type)}`);
|
|
139
|
+
}
|
|
140
|
+
})();
|
|
141
|
+
return field.required ? base : `optional<${base}>`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Chooses a primary-key column per model that collides with nothing.
|
|
145
|
+
*
|
|
146
|
+
* The column must differ from the partition column, from `revision`, from
|
|
147
|
+
* every stored field of its own entity, and from the parent key column its
|
|
148
|
+
* children embed. Roots resolve before children so a child can see the column
|
|
149
|
+
* its parent settled on.
|
|
150
|
+
*/
|
|
151
|
+
function resolveKeyColumns(plan, parentOf, childrenOf) {
|
|
152
|
+
const modelsByName = new Map(plan.models.map((model) => [model.name, model]));
|
|
153
|
+
const resolved = new Map();
|
|
154
|
+
const storedNames = (model) => {
|
|
155
|
+
const parent = parentOf.get(model.name);
|
|
156
|
+
return new Set(model.fields
|
|
157
|
+
.filter((field) => parent === undefined || field.reference?.model !== parent)
|
|
158
|
+
.map((field) => snake(field.name)));
|
|
159
|
+
};
|
|
160
|
+
const order = [
|
|
161
|
+
...plan.models.filter((model) => !parentOf.has(model.name)),
|
|
162
|
+
...plan.models.filter((model) => parentOf.has(model.name)),
|
|
163
|
+
];
|
|
164
|
+
for (const model of order) {
|
|
165
|
+
const taken = storedNames(model);
|
|
166
|
+
taken.add(PARTITION_FIELD);
|
|
167
|
+
taken.add("revision");
|
|
168
|
+
const parent = parentOf.get(model.name);
|
|
169
|
+
if (parent !== undefined)
|
|
170
|
+
taken.add(resolved.get(parent));
|
|
171
|
+
// The column also lands in every child's key, so it must clear their fields.
|
|
172
|
+
for (const child of childrenOf.get(model.name) ?? []) {
|
|
173
|
+
for (const name of storedNames(modelsByName.get(child)))
|
|
174
|
+
taken.add(name);
|
|
175
|
+
}
|
|
176
|
+
const preferred = preferredKeyColumn(model.name);
|
|
177
|
+
const candidate = taken.has(preferred) ? `${snake(model.name)}_row_id` : preferred;
|
|
178
|
+
if (taken.has(candidate)) {
|
|
179
|
+
reject("reserved_symbol_collision", `${model.name} cannot name a key column`);
|
|
180
|
+
}
|
|
181
|
+
resolved.set(model.name, candidate);
|
|
182
|
+
}
|
|
183
|
+
return resolved;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Assigns every model to exactly one aggregate.
|
|
187
|
+
*
|
|
188
|
+
* A model with no references is a root. A model whose references include at
|
|
189
|
+
* least one root becomes that root's child, choosing the first such reference
|
|
190
|
+
* in sorted field order so the assignment is deterministic. Everything else is
|
|
191
|
+
* its own root, because RiffDB aggregates are one level deep: a child cannot
|
|
192
|
+
* itself own children.
|
|
193
|
+
*/
|
|
194
|
+
function assignAggregates(plan) {
|
|
195
|
+
const referencesOf = new Map();
|
|
196
|
+
for (const model of plan.models) {
|
|
197
|
+
referencesOf.set(model.name, model.fields.filter((field) => field.reference !== undefined));
|
|
198
|
+
}
|
|
199
|
+
const rootEligible = new Set(plan.models
|
|
200
|
+
.filter((model) => (referencesOf.get(model.name) ?? []).length === 0)
|
|
201
|
+
.map((model) => model.name));
|
|
202
|
+
const parentOf = new Map();
|
|
203
|
+
for (const model of plan.models) {
|
|
204
|
+
const owning = (referencesOf.get(model.name) ?? []).find((field) => rootEligible.has(field.reference.model));
|
|
205
|
+
if (owning !== undefined)
|
|
206
|
+
parentOf.set(model.name, owning.reference.model);
|
|
207
|
+
}
|
|
208
|
+
const childrenOf = new Map();
|
|
209
|
+
for (const [child, parent] of parentOf) {
|
|
210
|
+
const bucket = childrenOf.get(parent) ?? [];
|
|
211
|
+
bucket.push(child);
|
|
212
|
+
childrenOf.set(parent, bucket);
|
|
213
|
+
}
|
|
214
|
+
for (const bucket of childrenOf.values())
|
|
215
|
+
bucket.sort();
|
|
216
|
+
const roots = plan.models.map((model) => model.name).filter((name) => !parentOf.has(name));
|
|
217
|
+
const frozenChildren = new Map([...childrenOf].map(([key, value]) => [key, Object.freeze(value)]));
|
|
218
|
+
return Object.freeze({
|
|
219
|
+
parentOf,
|
|
220
|
+
roots: Object.freeze(roots),
|
|
221
|
+
childrenOf: frozenChildren,
|
|
222
|
+
keyColumnOf: resolveKeyColumns(plan, parentOf, frozenChildren),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/** The full key column list for one model, parent prefix included. */
|
|
226
|
+
function keyColumns(model, assignment) {
|
|
227
|
+
const parent = assignment.parentOf.get(model);
|
|
228
|
+
return parent === undefined
|
|
229
|
+
? [PARTITION_FIELD, assignment.keyColumnOf.get(model)]
|
|
230
|
+
: [PARTITION_FIELD, assignment.keyColumnOf.get(parent), assignment.keyColumnOf.get(model)];
|
|
231
|
+
}
|
|
232
|
+
/** The reference field that owns this model's aggregate, if it has one. */
|
|
233
|
+
function owningField(model, assignment) {
|
|
234
|
+
const parent = assignment.parentOf.get(model.name);
|
|
235
|
+
if (parent === undefined)
|
|
236
|
+
return undefined;
|
|
237
|
+
return model.fields.find((field) => field.reference?.model === parent);
|
|
238
|
+
}
|
|
239
|
+
function emitEntity(model, assignment, bounds) {
|
|
240
|
+
const lines = [];
|
|
241
|
+
const unenforced = [];
|
|
242
|
+
const columns = keyColumns(model.name, assignment);
|
|
243
|
+
const owning = owningField(model, assignment);
|
|
244
|
+
lines.push(` entity ${pascal(model.name)} {`);
|
|
245
|
+
lines.push(` key (${columns.map((column) => `${column}: uuid`).join(", ")})`);
|
|
246
|
+
// The owning reference is carried by the key, so it is never also a field.
|
|
247
|
+
const stored = model.fields.filter((field) => field !== owning);
|
|
248
|
+
for (const field of stored) {
|
|
249
|
+
const secret = field.secret ? "secret " : "";
|
|
250
|
+
lines.push(` field ${secret}${snake(field.name)}: ${fieldType(field, bounds)}`);
|
|
251
|
+
}
|
|
252
|
+
lines.push(" field revision: u64");
|
|
253
|
+
const tail = columns.slice(1);
|
|
254
|
+
for (const field of stored) {
|
|
255
|
+
if (field.unique) {
|
|
256
|
+
lines.push(` unique ${snake(model.name)}_${snake(field.name)} (${PARTITION_FIELD}, ${snake(field.name)})`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
for (const field of stored) {
|
|
260
|
+
const needsIndex = field.indexed || field.unique || field.reference !== undefined;
|
|
261
|
+
if (!needsIndex)
|
|
262
|
+
continue;
|
|
263
|
+
lines.push(` index by_${snake(field.name)} (${PARTITION_FIELD}, ${snake(field.name)}, ${tail.join(", ")})`);
|
|
264
|
+
}
|
|
265
|
+
// A child is discovered from its parent through this index, which is also the
|
|
266
|
+
// reverse index a cascade or restrict proof names.
|
|
267
|
+
if (owning !== undefined) {
|
|
268
|
+
const parentModel = assignment.parentOf.get(model.name);
|
|
269
|
+
const parentColumn = assignment.keyColumnOf.get(parentModel);
|
|
270
|
+
lines.push(` index by_parent (${columns.join(", ")})`);
|
|
271
|
+
lines.push(` reference ${snake(model.name)}_parent (${PARTITION_FIELD}, ${parentColumn})` +
|
|
272
|
+
` -> ${pascal(parentModel)}(${PARTITION_FIELD}, ${parentColumn})`);
|
|
273
|
+
}
|
|
274
|
+
for (const field of stored) {
|
|
275
|
+
if (field.reference === undefined)
|
|
276
|
+
continue;
|
|
277
|
+
unenforced.push(Object.freeze({
|
|
278
|
+
model: model.name,
|
|
279
|
+
field: field.name,
|
|
280
|
+
targetModel: field.reference.model,
|
|
281
|
+
reason: "cross_aggregate_edge",
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
const children = assignment.childrenOf.get(model.name) ?? [];
|
|
285
|
+
if (children.length > MAX_CASCADE_RELATIONSHIPS) {
|
|
286
|
+
reject("cascade_bound_exceeded", `${model.name} owns ${children.length} children`);
|
|
287
|
+
}
|
|
288
|
+
if (children.length === 0) {
|
|
289
|
+
lines.push(" delete_policy no_inbound");
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
lines.push(" delete_policy cascade {");
|
|
293
|
+
for (const child of children) {
|
|
294
|
+
lines.push(` relationship ${pascal(child)}.${snake(child)}_parent using ${pascal(child)}.by_parent maximum ${cascadeMaximumFor(children.length, bounds)}`);
|
|
295
|
+
}
|
|
296
|
+
lines.push(" }");
|
|
297
|
+
}
|
|
298
|
+
lines.push(" }");
|
|
299
|
+
return Object.freeze({ source: lines.join("\n"), unenforced: Object.freeze(unenforced) });
|
|
300
|
+
}
|
|
301
|
+
function emitAggregate(root, assignment) {
|
|
302
|
+
const children = assignment.childrenOf.get(root) ?? [];
|
|
303
|
+
const lines = [` aggregate ${pascal(root)}Data {`, ` root ${pascal(root)}`];
|
|
304
|
+
for (const child of children)
|
|
305
|
+
lines.push(` child ${pascal(child)}`);
|
|
306
|
+
lines.push(` partition_by ${PARTITION_FIELD}`);
|
|
307
|
+
lines.push(` conflict_key (${PARTITION_FIELD}, ${assignment.keyColumnOf.get(root)})`);
|
|
308
|
+
lines.push(" }");
|
|
309
|
+
return lines.join("\n");
|
|
310
|
+
}
|
|
311
|
+
/** Command input declarations for every stored field of one model. */
|
|
312
|
+
function commandInputs(model, assignment, bounds) {
|
|
313
|
+
const owning = owningField(model, assignment);
|
|
314
|
+
return model.fields
|
|
315
|
+
.filter((field) => field !== owning)
|
|
316
|
+
.map((field) => ` input ${snake(field.name)}: ${fieldType(field, bounds)}`);
|
|
317
|
+
}
|
|
318
|
+
function emitCommands(model, assignment, bounds) {
|
|
319
|
+
const entity = pascal(model.name);
|
|
320
|
+
const columns = keyColumns(model.name, assignment);
|
|
321
|
+
const binding = snake(model.name);
|
|
322
|
+
const owning = owningField(model, assignment);
|
|
323
|
+
const stored = model.fields.filter((field) => field !== owning);
|
|
324
|
+
const keyInputs = columns.map((column) => ` input ${column}: uuid`);
|
|
325
|
+
const lines = [];
|
|
326
|
+
lines.push(` command Create${entity} {`);
|
|
327
|
+
lines.push(" input request_id: uuid");
|
|
328
|
+
lines.push(...keyInputs);
|
|
329
|
+
lines.push(...commandInputs(model, assignment, bounds));
|
|
330
|
+
lines.push(" idempotency_key request_id");
|
|
331
|
+
// A create that declares a reference must first prove the target exists,
|
|
332
|
+
// reusing the same key expressions the reference was declared with.
|
|
333
|
+
if (owning !== undefined) {
|
|
334
|
+
const parentModel = assignment.parentOf.get(model.name);
|
|
335
|
+
const parentColumn = assignment.keyColumnOf.get(parentModel);
|
|
336
|
+
lines.push(` read ${pascal(parentModel)}(${PARTITION_FIELD}, ${parentColumn}) as ${snake(parentModel)}` +
|
|
337
|
+
` else ${entity}ParentMissing {}`);
|
|
338
|
+
}
|
|
339
|
+
lines.push(` create ${entity}(${columns.join(", ")}) as ${binding} else ${entity}AlreadyExists {}`);
|
|
340
|
+
for (const field of stored) {
|
|
341
|
+
lines.push(` set ${binding}.${snake(field.name)} = ${snake(field.name)}`);
|
|
342
|
+
}
|
|
343
|
+
lines.push(` set ${binding}.revision = 1`);
|
|
344
|
+
lines.push(` return ${entity}Created {}`);
|
|
345
|
+
lines.push(" }");
|
|
346
|
+
lines.push("");
|
|
347
|
+
lines.push(` command Update${entity} {`);
|
|
348
|
+
lines.push(" input request_id: uuid");
|
|
349
|
+
lines.push(...keyInputs);
|
|
350
|
+
lines.push(" input expected_revision: u64");
|
|
351
|
+
lines.push(...commandInputs(model, assignment, bounds));
|
|
352
|
+
lines.push(" idempotency_key request_id");
|
|
353
|
+
lines.push(` mutate ${entity}(${columns.join(", ")}) as ${binding} else ${entity}UpdateMissing {}`);
|
|
354
|
+
lines.push(` require current_revision: ${binding}.revision == expected_revision else ${entity}UpdateStale {}`);
|
|
355
|
+
const checkedBy = assignment.parentOf.has(model.name) ? " checked_by current_revision" : "";
|
|
356
|
+
for (const field of stored) {
|
|
357
|
+
lines.push(` set ${binding}.${snake(field.name)} = ${snake(field.name)}${checkedBy}`);
|
|
358
|
+
}
|
|
359
|
+
lines.push(` set ${binding}.revision = ${binding}.revision + 1`);
|
|
360
|
+
lines.push(` return ${entity}Updated {}`);
|
|
361
|
+
lines.push(" }");
|
|
362
|
+
lines.push("");
|
|
363
|
+
const cascades = (assignment.childrenOf.get(model.name) ?? []).length > 0;
|
|
364
|
+
const column = assignment.keyColumnOf.get(model.name);
|
|
365
|
+
lines.push(` bulk command Delete${entity} {`);
|
|
366
|
+
lines.push(" input request_id: uuid");
|
|
367
|
+
lines.push(...columns.slice(0, -1).map((column) => ` input ${column}: uuid`));
|
|
368
|
+
lines.push(` input ${column}s: list<uuid, 1..${deleteRootBound((assignment.childrenOf.get(model.name) ?? []).length, bounds)}>`);
|
|
369
|
+
lines.push(" idempotency_key request_id");
|
|
370
|
+
lines.push(` for ${column} in ${column}s {`);
|
|
371
|
+
lines.push(` delete ${entity}(${columns.join(", ")}) as ${binding} else ${entity}Missing {}`);
|
|
372
|
+
if (cascades)
|
|
373
|
+
lines.push(` cascade ${entity}CascadeLimitExceeded {}`);
|
|
374
|
+
lines.push(" }");
|
|
375
|
+
lines.push(` return ${entity}Deleted {}`);
|
|
376
|
+
lines.push(" }");
|
|
377
|
+
return lines.join("\n");
|
|
378
|
+
}
|
|
379
|
+
/** The projection every generated read returns for one model. */
|
|
380
|
+
function projection(model, assignment, binding) {
|
|
381
|
+
const owning = owningField(model, assignment);
|
|
382
|
+
const columns = keyColumns(model.name, assignment).slice(1);
|
|
383
|
+
const fields = model.fields
|
|
384
|
+
.filter((field) => field !== owning)
|
|
385
|
+
.map((field) => field.secret
|
|
386
|
+
? `${snake(field.name)} reveals ${binding}.${snake(field.name)}`
|
|
387
|
+
: snake(field.name));
|
|
388
|
+
return [...columns, ...fields, "revision"].join(" ");
|
|
389
|
+
}
|
|
390
|
+
function emitQueries(model, assignment) {
|
|
391
|
+
const entity = pascal(model.name);
|
|
392
|
+
const columns = keyColumns(model.name, assignment);
|
|
393
|
+
const binding = `${snake(model.name)}s`;
|
|
394
|
+
const queries = [];
|
|
395
|
+
const build = (name, parameters, predicate, order, take) => Object.freeze({
|
|
396
|
+
name,
|
|
397
|
+
path: `riffdb/queries/${snake(name)}.riffq`,
|
|
398
|
+
code: [
|
|
399
|
+
`query ${name}(`,
|
|
400
|
+
...parameters.map((parameter) => ` ${parameter},`),
|
|
401
|
+
") {",
|
|
402
|
+
` many ${binding} from ${entity}`,
|
|
403
|
+
` where ${predicate.join("\n && ")}`,
|
|
404
|
+
` order by ${order}`,
|
|
405
|
+
` ${take}`,
|
|
406
|
+
"",
|
|
407
|
+
" return Found {",
|
|
408
|
+
` ${binding}: ${binding} { ${projection(model, assignment, binding)} }`,
|
|
409
|
+
" }",
|
|
410
|
+
"",
|
|
411
|
+
" outcomes Found",
|
|
412
|
+
"}",
|
|
413
|
+
"",
|
|
414
|
+
].join("\n"),
|
|
415
|
+
});
|
|
416
|
+
// Exact identity: every key column bound, one row.
|
|
417
|
+
queries.push(build(`Find${entity}ById`, columns.map((column) => `$${column}: ${entity}.${column}`), columns.map((column) => `${column} == $${column}`), `${assignment.keyColumnOf.get(model.name)} asc`, "take 1"));
|
|
418
|
+
const owning = owningField(model, assignment);
|
|
419
|
+
for (const field of model.fields) {
|
|
420
|
+
if (field === owning)
|
|
421
|
+
continue;
|
|
422
|
+
if (!field.unique && !field.indexed && field.reference === undefined)
|
|
423
|
+
continue;
|
|
424
|
+
const column = snake(field.name);
|
|
425
|
+
queries.push(build(`Find${entity}By${pascal(field.name)}`, [
|
|
426
|
+
`$${PARTITION_FIELD}: ${entity}.${PARTITION_FIELD}`,
|
|
427
|
+
`$${column}: ${entity}.${column}`,
|
|
428
|
+
...(field.unique ? [] : ["$after: Cursor?"]),
|
|
429
|
+
], [`${PARTITION_FIELD} == $${PARTITION_FIELD}`, `${column} == $${column}`],
|
|
430
|
+
// The serving index is (tenant, field, ...key tail), so the bounded
|
|
431
|
+
// order must name that whole tail for the planner to prove it.
|
|
432
|
+
columns
|
|
433
|
+
.slice(1)
|
|
434
|
+
.map((keyColumn) => `${keyColumn} asc`)
|
|
435
|
+
.join(", "), field.unique ? "take 1" : "take 50 after $after"));
|
|
436
|
+
}
|
|
437
|
+
return Object.freeze(queries);
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Materializes one reviewed plan into compilable RiffDB sources.
|
|
441
|
+
*
|
|
442
|
+
* The returned sources are input to `riffdb application check` and human
|
|
443
|
+
* review, not a deployment. Callers must read
|
|
444
|
+
* {@link RiffDBBetterAuthMaterialization.report} before trusting the result:
|
|
445
|
+
* it names every reference the contract does not enforce.
|
|
446
|
+
*/
|
|
447
|
+
export function materializeRiffDBBetterAuthProfile(plan, options) {
|
|
448
|
+
const bounds = resolveBounds(options);
|
|
449
|
+
for (const model of plan.models) {
|
|
450
|
+
if (preferredKeyColumn(model.name) === PARTITION_FIELD) {
|
|
451
|
+
reject("reserved_symbol_collision", `${model.name} collides with ${PARTITION_FIELD}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const assignment = assignAggregates(plan);
|
|
455
|
+
const entities = [];
|
|
456
|
+
const unenforced = [];
|
|
457
|
+
for (const model of plan.models) {
|
|
458
|
+
const emitted = emitEntity(model, assignment, bounds);
|
|
459
|
+
entities.push(emitted.source);
|
|
460
|
+
unenforced.push(...emitted.unenforced);
|
|
461
|
+
}
|
|
462
|
+
const aggregates = assignment.roots.map((root) => emitAggregate(root, assignment));
|
|
463
|
+
const commands = plan.models.map((model) => emitCommands(model, assignment, bounds));
|
|
464
|
+
const commandNames = plan.models.flatMap((model) => [
|
|
465
|
+
`Create${pascal(model.name)}`,
|
|
466
|
+
`Update${pascal(model.name)}`,
|
|
467
|
+
`Delete${pascal(model.name)}`,
|
|
468
|
+
]);
|
|
469
|
+
const queries = plan.models.flatMap((model) => emitQueries(model, assignment));
|
|
470
|
+
const contract = [
|
|
471
|
+
`contract ${plan.contract.lineage} version 1 {`,
|
|
472
|
+
entities.join("\n\n"),
|
|
473
|
+
"",
|
|
474
|
+
aggregates.join("\n\n"),
|
|
475
|
+
"",
|
|
476
|
+
commands.join("\n\n"),
|
|
477
|
+
"}",
|
|
478
|
+
"",
|
|
479
|
+
].join("\n");
|
|
480
|
+
const applicationSource = `${JSON.stringify({
|
|
481
|
+
schema: "riffdb.application-source/v6",
|
|
482
|
+
application: snake(plan.name).replaceAll("_", "-"),
|
|
483
|
+
contract: {
|
|
484
|
+
source: "riffdb/contract.riff",
|
|
485
|
+
lineage: plan.contract.lineage,
|
|
486
|
+
version: 1,
|
|
487
|
+
},
|
|
488
|
+
generation: {
|
|
489
|
+
go: "generated/go/client.go",
|
|
490
|
+
mcp: "generated/mcp/tools.json",
|
|
491
|
+
python: "generated/python/client.py",
|
|
492
|
+
rust: "generated/rust/client.rs",
|
|
493
|
+
typescript: "src/generated/client.ts",
|
|
494
|
+
},
|
|
495
|
+
migrations: [],
|
|
496
|
+
query_modules: [
|
|
497
|
+
{
|
|
498
|
+
name: snake(plan.name),
|
|
499
|
+
version: 1,
|
|
500
|
+
queries: queries.map((query) => ({ name: query.name, source: query.path })),
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
reactive_modules: [],
|
|
504
|
+
// The role grants exactly the operations this contract declares, so the
|
|
505
|
+
// materialized profile is callable without widening it by hand.
|
|
506
|
+
roles: [
|
|
507
|
+
{
|
|
508
|
+
name: plan.contract.applicationRole,
|
|
509
|
+
environment: "development",
|
|
510
|
+
tenant_scope: "global",
|
|
511
|
+
queries: queries.map((query) => query.name),
|
|
512
|
+
commands: commandNames,
|
|
513
|
+
event_streams: [],
|
|
514
|
+
watch_queries: [],
|
|
515
|
+
agent_subscriptions: [],
|
|
516
|
+
row_policies: [],
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
seed_inputs: [],
|
|
520
|
+
}, null, 2)}\n`;
|
|
521
|
+
return Object.freeze({
|
|
522
|
+
contract,
|
|
523
|
+
queries,
|
|
524
|
+
applicationSource,
|
|
525
|
+
report: Object.freeze({
|
|
526
|
+
aggregates: Object.freeze(assignment.roots.map((root) => Object.freeze({
|
|
527
|
+
name: `${pascal(root)}Data`,
|
|
528
|
+
root,
|
|
529
|
+
children: assignment.childrenOf.get(root) ?? Object.freeze([]),
|
|
530
|
+
}))),
|
|
531
|
+
unenforcedReferences: Object.freeze(unenforced),
|
|
532
|
+
}),
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
//# sourceMappingURL=profile-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-contract.js","sourceRoot":"","sources":["../src/profile-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from "better-auth";
|
|
2
|
+
import { type AdapterFactory } from "better-auth/adapters";
|
|
3
|
+
import type { BetterAuthDBSchema, DBFieldType } from "better-auth/db";
|
|
4
|
+
import { BETTER_AUTH_PINNED_VERSION } from "./profile.js";
|
|
5
|
+
export declare const RIFFDB_BETTER_AUTH_PROFILE_PLAN_SCHEMA: "riffdb.better-auth-profile-plan/v1";
|
|
6
|
+
declare const MAX_MODELS = 32;
|
|
7
|
+
declare const MAX_FIELDS_PER_MODEL = 64;
|
|
8
|
+
export interface RiffDBBetterAuthProfileGeneratorConfig {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly contractLineage: string;
|
|
11
|
+
readonly applicationRole?: string;
|
|
12
|
+
readonly output?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RiffDBBetterAuthProfileFieldPlan {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly storageName: string;
|
|
17
|
+
readonly type: DBFieldType;
|
|
18
|
+
readonly required: boolean;
|
|
19
|
+
readonly unique: boolean;
|
|
20
|
+
readonly indexed: boolean;
|
|
21
|
+
readonly secret: boolean;
|
|
22
|
+
readonly input: boolean;
|
|
23
|
+
readonly returned: boolean;
|
|
24
|
+
readonly hasDefault: boolean;
|
|
25
|
+
readonly hasOnUpdate: boolean;
|
|
26
|
+
readonly reference?: Readonly<{
|
|
27
|
+
model: string;
|
|
28
|
+
field: string;
|
|
29
|
+
onDelete?: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export interface RiffDBBetterAuthProfileModelPlan {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly storageName: string;
|
|
35
|
+
readonly fields: readonly RiffDBBetterAuthProfileFieldPlan[];
|
|
36
|
+
}
|
|
37
|
+
export interface RiffDBBetterAuthProfilePlan {
|
|
38
|
+
readonly schema: typeof RIFFDB_BETTER_AUTH_PROFILE_PLAN_SCHEMA;
|
|
39
|
+
readonly betterAuthVersion: typeof BETTER_AUTH_PINNED_VERSION;
|
|
40
|
+
readonly idGeneration: "uuid";
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly contract: Readonly<{
|
|
43
|
+
lineage: string;
|
|
44
|
+
applicationRole: string;
|
|
45
|
+
}>;
|
|
46
|
+
readonly plugins: readonly string[];
|
|
47
|
+
readonly models: readonly RiffDBBetterAuthProfileModelPlan[];
|
|
48
|
+
readonly bounds: Readonly<{
|
|
49
|
+
maximumModels: typeof MAX_MODELS;
|
|
50
|
+
maximumFieldsPerModel: typeof MAX_FIELDS_PER_MODEL;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
export type RiffDBBetterAuthProfileGenerationErrorCode = "invalid_generator_configuration" | "unsupported_id_generation" | "profile_model_bound_exceeded" | "profile_field_bound_exceeded" | "invalid_model_name" | "invalid_field_name" | "unsupported_field_type" | "invalid_reference" | "generation_only_runtime_call";
|
|
54
|
+
export declare class RiffDBBetterAuthProfileGenerationError extends Error {
|
|
55
|
+
readonly code: RiffDBBetterAuthProfileGenerationErrorCode;
|
|
56
|
+
constructor(code: RiffDBBetterAuthProfileGenerationErrorCode);
|
|
57
|
+
}
|
|
58
|
+
export declare function defineRiffDBBetterAuthProfilePlan(options: BetterAuthOptions, tables: BetterAuthDBSchema, config: RiffDBBetterAuthProfileGeneratorConfig): RiffDBBetterAuthProfilePlan;
|
|
59
|
+
export declare function renderRiffDBBetterAuthProfilePlan(plan: RiffDBBetterAuthProfilePlan): string;
|
|
60
|
+
/**
|
|
61
|
+
* Generation-only Better Auth adapter used by `better-auth generate`.
|
|
62
|
+
*
|
|
63
|
+
* It resolves the complete configured Better Auth schema without requiring a
|
|
64
|
+
* live RiffDB driver. Runtime methods always fail; the resulting reviewed plan
|
|
65
|
+
* is input to the compiled-profile materializer, never a generic CRUD schema.
|
|
66
|
+
*/
|
|
67
|
+
export declare function riffdbProfileAdapter(config: RiffDBBetterAuthProfileGeneratorConfig): AdapterFactory<BetterAuthOptions>;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=profile-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-plan.d.ts","sourceRoot":"","sources":["../src/profile-plan.ts"],"names":[],"mappings":"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"}
|