js-bao 0.5.0 → 0.5.2
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/README.md +124 -30
- package/dist/browser.cjs +759 -273
- package/dist/browser.d.cts +62 -0
- package/dist/browser.d.ts +62 -0
- package/dist/browser.js +760 -271
- package/dist/client.cjs +53 -6
- package/dist/client.d.cts +149 -0
- package/dist/client.d.ts +149 -0
- package/dist/client.js +49 -4
- package/dist/cloudflare-do.cjs +643 -231
- package/dist/cloudflare-do.d.cts +237 -1
- package/dist/cloudflare-do.d.ts +237 -1
- package/dist/cloudflare-do.js +639 -229
- package/dist/cloudflare.cjs +330 -26
- package/dist/cloudflare.d.cts +360 -1
- package/dist/cloudflare.d.ts +360 -1
- package/dist/cloudflare.js +326 -24
- package/dist/codegen-v2.cjs +139 -21
- package/dist/codegen.cjs +7 -1
- package/dist/index.cjs +724 -232
- package/dist/index.d.cts +98 -1
- package/dist/index.d.ts +98 -1
- package/dist/index.js +721 -229
- package/dist/node.cjs +948 -299
- package/dist/node.d.cts +220 -1
- package/dist/node.d.ts +220 -1
- package/dist/node.js +934 -296
- package/package.json +2 -1
package/dist/cloudflare.js
CHANGED
|
@@ -57,10 +57,220 @@ var init_DocumentQueryTranslator = __esm({
|
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
// src/
|
|
60
|
+
// src/utils/yjsValues.ts
|
|
61
61
|
import * as Y from "yjs";
|
|
62
|
+
function isStringSetYMap(value) {
|
|
63
|
+
if (!(value instanceof Y.Map)) return false;
|
|
64
|
+
for (const v of value.values()) {
|
|
65
|
+
if (v !== true) return false;
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
var init_yjsValues = __esm({
|
|
70
|
+
"src/utils/yjsValues.ts"() {
|
|
71
|
+
"use strict";
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// src/models/writeLifecycle.ts
|
|
76
|
+
import * as Y2 from "yjs";
|
|
77
|
+
import { ulid } from "ulid";
|
|
78
|
+
function assertNever(x) {
|
|
79
|
+
throw new Error(`Unhandled field type: ${String(x)}`);
|
|
80
|
+
}
|
|
81
|
+
function fieldWriteKind(type) {
|
|
82
|
+
switch (type) {
|
|
83
|
+
case "string":
|
|
84
|
+
case "number":
|
|
85
|
+
case "boolean":
|
|
86
|
+
case "date":
|
|
87
|
+
case "id":
|
|
88
|
+
return "scalar";
|
|
89
|
+
case "stringset":
|
|
90
|
+
return "stringset";
|
|
91
|
+
default:
|
|
92
|
+
return assertNever(type);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function isKnownFieldType(type) {
|
|
96
|
+
return KNOWN_FIELD_TYPES.has(type);
|
|
97
|
+
}
|
|
98
|
+
function ensureStringSetYMap(rm, fieldName) {
|
|
99
|
+
const nested = rm.get(fieldName);
|
|
100
|
+
if (nested instanceof Y2.Map) return nested;
|
|
101
|
+
const fresh = new Y2.Map();
|
|
102
|
+
if (nested && typeof nested === "object") {
|
|
103
|
+
for (const [member, marker] of Object.entries(
|
|
104
|
+
nested
|
|
105
|
+
)) {
|
|
106
|
+
if (Boolean(marker)) fresh.set(member, true);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
rm.set(fieldName, fresh);
|
|
110
|
+
return fresh;
|
|
111
|
+
}
|
|
112
|
+
function applyStringSetDelta(target, delta) {
|
|
113
|
+
if (delta.clear) {
|
|
114
|
+
for (const member of Array.from(target.keys())) target.delete(member);
|
|
115
|
+
}
|
|
116
|
+
if (delta.remove) {
|
|
117
|
+
for (const member of delta.remove) target.delete(String(member));
|
|
118
|
+
}
|
|
119
|
+
if (delta.add) {
|
|
120
|
+
for (const member of delta.add) {
|
|
121
|
+
const key = String(member);
|
|
122
|
+
if (target.get(key) !== true) target.set(key, true);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function replaceStringSet(rm, fieldName, members) {
|
|
127
|
+
const target = ensureStringSetYMap(rm, fieldName);
|
|
128
|
+
const desired = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const member of members) desired.add(String(member));
|
|
130
|
+
for (const existing of Array.from(target.keys())) {
|
|
131
|
+
if (!desired.has(existing)) target.delete(existing);
|
|
132
|
+
}
|
|
133
|
+
for (const member of desired) {
|
|
134
|
+
if (target.get(member) !== true) target.set(member, true);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function applyStringSetChange(recordYMap, fieldName, change) {
|
|
138
|
+
const target = ensureStringSetYMap(recordYMap, fieldName);
|
|
139
|
+
applyStringSetDelta(target, {
|
|
140
|
+
add: change.additions,
|
|
141
|
+
remove: change.removals
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function parseStringSetOp(value) {
|
|
145
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Y2.AbstractType) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const keys = Object.keys(value);
|
|
149
|
+
const opKeys = keys.filter((k) => k.startsWith("$"));
|
|
150
|
+
if (opKeys.length === 0) return null;
|
|
151
|
+
const known = /* @__PURE__ */ new Set(["$add", "$remove", "$clear"]);
|
|
152
|
+
const unknown = keys.filter((k) => !known.has(k));
|
|
153
|
+
if (unknown.length > 0) {
|
|
154
|
+
throw new Error(
|
|
155
|
+
`Invalid stringset op: unexpected key(s) [${unknown.join(", ")}]. Only $add, $remove and $clear are supported.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
const obj = value;
|
|
159
|
+
const toMembers = (raw, opName) => {
|
|
160
|
+
if (raw === void 0) return [];
|
|
161
|
+
if (!Array.isArray(raw)) {
|
|
162
|
+
throw new Error(`Invalid stringset op: ${opName} must be an array.`);
|
|
163
|
+
}
|
|
164
|
+
return raw.map((m) => String(m));
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
add: toMembers(obj.$add, "$add"),
|
|
168
|
+
remove: toMembers(obj.$remove, "$remove"),
|
|
169
|
+
clear: obj.$clear === true
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function writeField(rm, declaredType, key, value, modelName) {
|
|
173
|
+
const kind = declaredType && isKnownFieldType(declaredType) ? fieldWriteKind(declaredType) : "scalar";
|
|
174
|
+
if (Array.isArray(value)) {
|
|
175
|
+
if (kind !== "stringset") {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Cannot write array value to field "${key}" on model "${modelName}": its declared type could not be resolved to a collection (stringset). Collection fields require schema metadata in the document (_meta_${modelName}); the model must be saved by a client at least once before a workflow writes one of its collection fields.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
replaceStringSet(rm, key, value);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const op = parseStringSetOp(value);
|
|
184
|
+
if (op) {
|
|
185
|
+
if (kind !== "stringset") {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Cannot apply a stringset op ({ $add/$remove/$clear }) to field "${key}" on model "${modelName}": its declared type is ${declaredType ? `"${declaredType}"` : "unresolved"}, not a collection (stringset). Op-objects are only valid for stringset / refersToMany fields with schema metadata (_meta_${modelName}).`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
applyStringSetDelta(ensureStringSetYMap(rm, key), op);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (kind === "stringset") {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Field "${key}" on model "${modelName}" is a stringset and requires an array (replace) or { $add/$remove/$clear } (delta) value; received ${value === null ? "null" : typeof value}.`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
rm.set(key, value);
|
|
199
|
+
}
|
|
200
|
+
function registerFunctionDefaultGenerator(name, fn) {
|
|
201
|
+
FUNCTION_DEFAULT_GENERATORS.set(name, fn);
|
|
202
|
+
}
|
|
203
|
+
function decodeFunctionDefault(name) {
|
|
204
|
+
return FUNCTION_DEFAULT_GENERATORS.get(name);
|
|
205
|
+
}
|
|
206
|
+
function resolveDefaultValue(rawDefault, opts = {}) {
|
|
207
|
+
if (typeof rawDefault === "function") return rawDefault();
|
|
208
|
+
if (typeof rawDefault === "string" && rawDefault.startsWith("$")) {
|
|
209
|
+
if (rawDefault.startsWith("$$")) return rawDefault.slice(1);
|
|
210
|
+
const name = rawDefault.slice(1);
|
|
211
|
+
const gen = opts.decode?.(name) ?? decodeFunctionDefault(name);
|
|
212
|
+
if (!gen) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`Unknown function default "${rawDefault}" for field "${opts.fieldName ?? "?"}"${opts.modelName ? ` on model "${opts.modelName}"` : ""}: no generator is registered for "${name}". Register it via registerFunctionDefaultGenerator("${name}", fn) so the server can populate the field the same way the client does.`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return gen();
|
|
218
|
+
}
|
|
219
|
+
return rawDefault;
|
|
220
|
+
}
|
|
221
|
+
function applyDefaultsFromSchema(fields, data, opts = {}) {
|
|
222
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
223
|
+
if (fieldName === "id") continue;
|
|
224
|
+
if (!field || field.default === void 0) continue;
|
|
225
|
+
if (field.default === UNKNOWN_FUNCTION_DEFAULT) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== void 0) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
data[fieldName] = resolveDefaultValue(field.default, {
|
|
232
|
+
fieldName,
|
|
233
|
+
modelName: opts.modelName,
|
|
234
|
+
decode: opts.decodeFunctionDefault
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return data;
|
|
238
|
+
}
|
|
239
|
+
function applyAutoStampsFromSchema(fields, data, opts) {
|
|
240
|
+
const { isNew, now } = opts;
|
|
241
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
242
|
+
const stamp = field?.autoStamp;
|
|
243
|
+
if (!stamp) continue;
|
|
244
|
+
const explicit = Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== null && data[fieldName] !== void 0;
|
|
245
|
+
if (explicit) continue;
|
|
246
|
+
if (stamp === "create" && !isNew) continue;
|
|
247
|
+
data[fieldName] = now;
|
|
248
|
+
}
|
|
249
|
+
return data;
|
|
250
|
+
}
|
|
251
|
+
var KNOWN_FIELD_TYPE_MAP, KNOWN_FIELD_TYPES, FUNCTION_DEFAULT_GENERATORS, UNKNOWN_FUNCTION_DEFAULT;
|
|
252
|
+
var init_writeLifecycle = __esm({
|
|
253
|
+
"src/models/writeLifecycle.ts"() {
|
|
254
|
+
"use strict";
|
|
255
|
+
KNOWN_FIELD_TYPE_MAP = {
|
|
256
|
+
string: true,
|
|
257
|
+
number: true,
|
|
258
|
+
boolean: true,
|
|
259
|
+
date: true,
|
|
260
|
+
id: true,
|
|
261
|
+
stringset: true
|
|
262
|
+
};
|
|
263
|
+
KNOWN_FIELD_TYPES = new Set(Object.keys(KNOWN_FIELD_TYPE_MAP));
|
|
264
|
+
FUNCTION_DEFAULT_GENERATORS = /* @__PURE__ */ new Map();
|
|
265
|
+
registerFunctionDefaultGenerator("generate_ulid", () => ulid());
|
|
266
|
+
UNKNOWN_FUNCTION_DEFAULT = "$unknown_function";
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// src/models/metaSync.ts
|
|
271
|
+
import * as Y3 from "yjs";
|
|
62
272
|
function inferFieldType(value) {
|
|
63
|
-
if (value
|
|
273
|
+
if (isStringSetYMap(value)) return "stringset";
|
|
64
274
|
switch (typeof value) {
|
|
65
275
|
case "string":
|
|
66
276
|
return "string";
|
|
@@ -79,7 +289,10 @@ function encodeDefault(value) {
|
|
|
79
289
|
if (value === void 0 || value === null) return void 0;
|
|
80
290
|
if (typeof value === "function") {
|
|
81
291
|
const name = KNOWN_FUNCTION_DEFAULTS.get(value);
|
|
82
|
-
return name ? `$${name}` :
|
|
292
|
+
return name ? `$${name}` : UNKNOWN_FUNCTION_DEFAULT;
|
|
293
|
+
}
|
|
294
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
295
|
+
return `$${value}`;
|
|
83
296
|
}
|
|
84
297
|
return value;
|
|
85
298
|
}
|
|
@@ -105,7 +318,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
105
318
|
if (compoundConstraints.length > 0) {
|
|
106
319
|
let constraints = meta.get("_constraints");
|
|
107
320
|
if (!constraints) {
|
|
108
|
-
constraints = new
|
|
321
|
+
constraints = new Y3.Map();
|
|
109
322
|
meta.set("_constraints", constraints);
|
|
110
323
|
}
|
|
111
324
|
for (const constraint of compoundConstraints) {
|
|
@@ -116,7 +329,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
116
329
|
if (relationships && Object.keys(relationships).length > 0) {
|
|
117
330
|
let rels = meta.get("_relationships");
|
|
118
331
|
if (!rels) {
|
|
119
|
-
rels = new
|
|
332
|
+
rels = new Y3.Map();
|
|
120
333
|
meta.set("_relationships", rels);
|
|
121
334
|
}
|
|
122
335
|
for (const [relName, relConfig] of Object.entries(relationships)) {
|
|
@@ -128,7 +341,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
128
341
|
function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
129
342
|
let fieldMeta = metaMap.get(fieldName);
|
|
130
343
|
if (!fieldMeta) {
|
|
131
|
-
fieldMeta = new
|
|
344
|
+
fieldMeta = new Y3.Map();
|
|
132
345
|
metaMap.set(fieldName, fieldMeta);
|
|
133
346
|
}
|
|
134
347
|
setIfChanged(fieldMeta, "type", fieldOpts.type);
|
|
@@ -136,6 +349,7 @@ function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
|
136
349
|
if (fieldOpts.unique) setIfChanged(fieldMeta, "unique", true);
|
|
137
350
|
if (fieldOpts.required) setIfChanged(fieldMeta, "required", true);
|
|
138
351
|
if (fieldOpts.autoAssign) setIfChanged(fieldMeta, "autoAssign", true);
|
|
352
|
+
if (fieldOpts.autoStamp) setIfChanged(fieldMeta, "autoStamp", fieldOpts.autoStamp);
|
|
139
353
|
if (fieldOpts.maxLength !== void 0) setIfChanged(fieldMeta, "maxLength", fieldOpts.maxLength);
|
|
140
354
|
if (fieldOpts.maxCount !== void 0) setIfChanged(fieldMeta, "maxCount", fieldOpts.maxCount);
|
|
141
355
|
const encoded = encodeDefault(fieldOpts.default);
|
|
@@ -144,7 +358,7 @@ function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
|
144
358
|
function syncConstraintMeta(constraintsMap, constraint) {
|
|
145
359
|
let cMeta = constraintsMap.get(constraint.name);
|
|
146
360
|
if (!cMeta) {
|
|
147
|
-
cMeta = new
|
|
361
|
+
cMeta = new Y3.Map();
|
|
148
362
|
constraintsMap.set(constraint.name, cMeta);
|
|
149
363
|
}
|
|
150
364
|
setIfChanged(cMeta, "type", "unique");
|
|
@@ -154,7 +368,7 @@ function syncConstraintMeta(constraintsMap, constraint) {
|
|
|
154
368
|
function syncRelationshipMeta(relsMap, relName, relConfig) {
|
|
155
369
|
let relMeta = relsMap.get(relName);
|
|
156
370
|
if (!relMeta) {
|
|
157
|
-
relMeta = new
|
|
371
|
+
relMeta = new Y3.Map();
|
|
158
372
|
relsMap.set(relName, relMeta);
|
|
159
373
|
}
|
|
160
374
|
for (const [key, value] of Object.entries(relConfig)) {
|
|
@@ -169,7 +383,7 @@ function syncInferredMeta(yDoc, modelName, recordData) {
|
|
|
169
383
|
if (fieldName.startsWith("_")) continue;
|
|
170
384
|
let fieldMeta = meta.get(fieldName);
|
|
171
385
|
if (!fieldMeta) {
|
|
172
|
-
fieldMeta = new
|
|
386
|
+
fieldMeta = new Y3.Map();
|
|
173
387
|
meta.set(fieldName, fieldMeta);
|
|
174
388
|
}
|
|
175
389
|
if (!fieldMeta.has("type")) {
|
|
@@ -189,16 +403,43 @@ var KNOWN_FUNCTION_DEFAULTS, _syncedCache;
|
|
|
189
403
|
var init_metaSync = __esm({
|
|
190
404
|
"src/models/metaSync.ts"() {
|
|
191
405
|
"use strict";
|
|
406
|
+
init_yjsValues();
|
|
407
|
+
init_writeLifecycle();
|
|
192
408
|
KNOWN_FUNCTION_DEFAULTS = /* @__PURE__ */ new WeakMap();
|
|
193
409
|
_syncedCache = /* @__PURE__ */ new WeakMap();
|
|
194
410
|
}
|
|
195
411
|
});
|
|
196
412
|
|
|
413
|
+
// src/utils/uniqueIndex.ts
|
|
414
|
+
import * as Y4 from "yjs";
|
|
415
|
+
function buildUniqueKey(recordData, fields) {
|
|
416
|
+
const keyParts = [];
|
|
417
|
+
for (const field of fields) {
|
|
418
|
+
const value = recordData instanceof Y4.Map ? recordData.get(field) : recordData[field];
|
|
419
|
+
if (value === null || value === void 0) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
keyParts.push(String(value));
|
|
423
|
+
}
|
|
424
|
+
return keyParts.join("|");
|
|
425
|
+
}
|
|
426
|
+
function uniqueIndexMapName(modelName, constraintName) {
|
|
427
|
+
return `_uniqueIdx_${modelName}_${constraintName}`;
|
|
428
|
+
}
|
|
429
|
+
function fieldUniqueConstraintName(modelName, fieldName) {
|
|
430
|
+
return `${modelName}_${fieldName}_unique`;
|
|
431
|
+
}
|
|
432
|
+
var init_uniqueIndex = __esm({
|
|
433
|
+
"src/utils/uniqueIndex.ts"() {
|
|
434
|
+
"use strict";
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
|
|
197
438
|
// src/models/BaseModel.ts
|
|
198
|
-
import * as
|
|
199
|
-
import { ulid } from "ulid";
|
|
439
|
+
import * as Y5 from "yjs";
|
|
440
|
+
import { ulid as ulid2 } from "ulid";
|
|
200
441
|
function generateULID() {
|
|
201
|
-
return
|
|
442
|
+
return ulid2();
|
|
202
443
|
}
|
|
203
444
|
var Logger;
|
|
204
445
|
var init_BaseModel = __esm({
|
|
@@ -210,6 +451,9 @@ var init_BaseModel = __esm({
|
|
|
210
451
|
init_CursorManager();
|
|
211
452
|
init_sql();
|
|
212
453
|
init_metaSync();
|
|
454
|
+
init_writeLifecycle();
|
|
455
|
+
init_yjsValues();
|
|
456
|
+
init_uniqueIndex();
|
|
213
457
|
Logger = class {
|
|
214
458
|
static _logLevel = 1 /* ERROR */;
|
|
215
459
|
static _logCallback = null;
|
|
@@ -1176,7 +1420,8 @@ function connectDoDb(options) {
|
|
|
1176
1420
|
}
|
|
1177
1421
|
|
|
1178
1422
|
// src/utils/yDocSchema.ts
|
|
1179
|
-
|
|
1423
|
+
init_yjsValues();
|
|
1424
|
+
import * as Y6 from "yjs";
|
|
1180
1425
|
function discoverSchema(yDoc) {
|
|
1181
1426
|
const models = {};
|
|
1182
1427
|
const metaNames = /* @__PURE__ */ new Set();
|
|
@@ -1210,7 +1455,7 @@ function discoverModelNames(yDoc) {
|
|
|
1210
1455
|
function materializeMap(yDoc, key) {
|
|
1211
1456
|
try {
|
|
1212
1457
|
const map = yDoc.getMap(key);
|
|
1213
|
-
return map instanceof
|
|
1458
|
+
return map instanceof Y6.Map ? map : null;
|
|
1214
1459
|
} catch {
|
|
1215
1460
|
return null;
|
|
1216
1461
|
}
|
|
@@ -1220,11 +1465,11 @@ function readModelMeta(metaMap) {
|
|
|
1220
1465
|
let constraints;
|
|
1221
1466
|
let relationships;
|
|
1222
1467
|
for (const [key, value] of metaMap.entries()) {
|
|
1223
|
-
if (key === "_constraints" && value instanceof
|
|
1468
|
+
if (key === "_constraints" && value instanceof Y6.Map) {
|
|
1224
1469
|
constraints = readConstraints(value);
|
|
1225
|
-
} else if (key === "_relationships" && value instanceof
|
|
1470
|
+
} else if (key === "_relationships" && value instanceof Y6.Map) {
|
|
1226
1471
|
relationships = readRelationships(value);
|
|
1227
|
-
} else if (value instanceof
|
|
1472
|
+
} else if (value instanceof Y6.Map) {
|
|
1228
1473
|
fields[key] = readFieldMeta(value);
|
|
1229
1474
|
}
|
|
1230
1475
|
}
|
|
@@ -1243,6 +1488,10 @@ function readFieldMeta(fieldMap) {
|
|
|
1243
1488
|
if (fieldMap.get("unique") === true) field.unique = true;
|
|
1244
1489
|
if (fieldMap.get("required") === true) field.required = true;
|
|
1245
1490
|
if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
|
|
1491
|
+
const autoStamp = fieldMap.get("autoStamp");
|
|
1492
|
+
if (typeof autoStamp === "string" && (autoStamp === "create" || autoStamp === "update" || autoStamp === "both")) {
|
|
1493
|
+
field.autoStamp = autoStamp;
|
|
1494
|
+
}
|
|
1246
1495
|
const def = fieldMap.get("default");
|
|
1247
1496
|
if (def !== void 0) field.default = def;
|
|
1248
1497
|
const maxLength = fieldMap.get("maxLength");
|
|
@@ -1255,7 +1504,7 @@ function inferModelFromData(dataMap) {
|
|
|
1255
1504
|
const fields = {};
|
|
1256
1505
|
let sampled = 0;
|
|
1257
1506
|
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
1258
|
-
if (!(recordValue instanceof
|
|
1507
|
+
if (!(recordValue instanceof Y6.Map)) continue;
|
|
1259
1508
|
if (++sampled > 5) break;
|
|
1260
1509
|
for (const [fieldName, value] of recordValue.entries()) {
|
|
1261
1510
|
if (fieldName.startsWith("_")) continue;
|
|
@@ -1268,7 +1517,7 @@ function inferModelFromData(dataMap) {
|
|
|
1268
1517
|
return { fields };
|
|
1269
1518
|
}
|
|
1270
1519
|
function inferTypeFromValue(value) {
|
|
1271
|
-
if (value
|
|
1520
|
+
if (isStringSetYMap(value)) return "stringset";
|
|
1272
1521
|
switch (typeof value) {
|
|
1273
1522
|
case "string":
|
|
1274
1523
|
return "string";
|
|
@@ -1283,7 +1532,7 @@ function inferTypeFromValue(value) {
|
|
|
1283
1532
|
function readConstraints(constraintsMap) {
|
|
1284
1533
|
const out = {};
|
|
1285
1534
|
for (const [name, value] of constraintsMap.entries()) {
|
|
1286
|
-
if (!(value instanceof
|
|
1535
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
1287
1536
|
let fields = [];
|
|
1288
1537
|
const rawFields = value.get("fields");
|
|
1289
1538
|
if (typeof rawFields === "string") {
|
|
@@ -1302,7 +1551,7 @@ function readConstraints(constraintsMap) {
|
|
|
1302
1551
|
function readRelationships(relsMap) {
|
|
1303
1552
|
const out = {};
|
|
1304
1553
|
for (const [name, value] of relsMap.entries()) {
|
|
1305
|
-
if (!(value instanceof
|
|
1554
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
1306
1555
|
const rel = {};
|
|
1307
1556
|
for (const [k, v] of value.entries()) {
|
|
1308
1557
|
rel[k] = v;
|
|
@@ -1313,6 +1562,7 @@ function readRelationships(relsMap) {
|
|
|
1313
1562
|
}
|
|
1314
1563
|
var CAMEL_TO_SNAKE = {
|
|
1315
1564
|
autoAssign: "auto_assign",
|
|
1565
|
+
autoStamp: "auto_stamp",
|
|
1316
1566
|
maxLength: "max_length",
|
|
1317
1567
|
maxCount: "max_count",
|
|
1318
1568
|
relatedIdField: "related_id_field",
|
|
@@ -1343,6 +1593,7 @@ function schemaToToml(schema) {
|
|
|
1343
1593
|
lines.push(`[models.${modelName}.fields.${fieldName}]`);
|
|
1344
1594
|
lines.push(`type = ${tomlValue(field.type)}`);
|
|
1345
1595
|
if (field.autoAssign) lines.push("auto_assign = true");
|
|
1596
|
+
if (field.autoStamp) lines.push(`auto_stamp = ${tomlValue(field.autoStamp)}`);
|
|
1346
1597
|
if (field.indexed) lines.push("indexed = true");
|
|
1347
1598
|
if (field.unique) lines.push("unique = true");
|
|
1348
1599
|
if (field.required) lines.push("required = true");
|
|
@@ -1379,6 +1630,7 @@ import { parse as parseToml } from "smol-toml";
|
|
|
1379
1630
|
// src/models/schema.ts
|
|
1380
1631
|
init_BaseModel();
|
|
1381
1632
|
init_ModelRegistry();
|
|
1633
|
+
init_uniqueIndex();
|
|
1382
1634
|
function defineModelSchema(input) {
|
|
1383
1635
|
const { name, fields } = input;
|
|
1384
1636
|
const options = {
|
|
@@ -1421,7 +1673,7 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
|
|
|
1421
1673
|
for (const [fieldName, options] of fields.entries()) {
|
|
1422
1674
|
if (options.unique) {
|
|
1423
1675
|
resolved.push({
|
|
1424
|
-
name:
|
|
1676
|
+
name: fieldUniqueConstraintName(modelName, fieldName),
|
|
1425
1677
|
fields: [fieldName]
|
|
1426
1678
|
});
|
|
1427
1679
|
}
|
|
@@ -1466,10 +1718,13 @@ var KNOWN_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
|
1466
1718
|
"unique",
|
|
1467
1719
|
"required",
|
|
1468
1720
|
"auto_assign",
|
|
1721
|
+
"auto_stamp",
|
|
1469
1722
|
"max_length",
|
|
1470
1723
|
"max_count",
|
|
1471
|
-
"default"
|
|
1724
|
+
"default",
|
|
1725
|
+
"enum"
|
|
1472
1726
|
]);
|
|
1727
|
+
var VALID_AUTO_STAMP_VALUES = /* @__PURE__ */ new Set(["create", "update", "both"]);
|
|
1473
1728
|
var KNOWN_MODEL_KEYS = /* @__PURE__ */ new Set([
|
|
1474
1729
|
"fields",
|
|
1475
1730
|
"relationships",
|
|
@@ -1511,9 +1766,37 @@ function parseFieldOptions(raw, context, strict) {
|
|
|
1511
1766
|
if (raw.unique === true) opts.unique = true;
|
|
1512
1767
|
if (raw.required === true) opts.required = true;
|
|
1513
1768
|
if (raw.auto_assign === true) opts.autoAssign = true;
|
|
1769
|
+
if (raw.auto_stamp !== void 0) {
|
|
1770
|
+
if (typeof raw.auto_stamp !== "string" || !VALID_AUTO_STAMP_VALUES.has(raw.auto_stamp)) {
|
|
1771
|
+
throw new Error(
|
|
1772
|
+
`${context}: invalid auto_stamp value "${raw.auto_stamp}". Must be one of: ${[
|
|
1773
|
+
...VALID_AUTO_STAMP_VALUES
|
|
1774
|
+
].join(", ")}`
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
opts.autoStamp = raw.auto_stamp;
|
|
1778
|
+
}
|
|
1514
1779
|
if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
|
|
1515
1780
|
if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
|
|
1516
1781
|
if (raw.default !== void 0) opts.default = raw.default;
|
|
1782
|
+
if (raw.enum !== void 0) {
|
|
1783
|
+
if (raw.type !== "string") {
|
|
1784
|
+
throw new Error(
|
|
1785
|
+
`${context}: \`enum\` is only valid on a "string" field, not "${raw.type}".`
|
|
1786
|
+
);
|
|
1787
|
+
}
|
|
1788
|
+
if (!Array.isArray(raw.enum) || raw.enum.length === 0) {
|
|
1789
|
+
throw new Error(
|
|
1790
|
+
`${context}: \`enum\` must be a non-empty array of strings.`
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
if (!raw.enum.every((v) => typeof v === "string")) {
|
|
1794
|
+
throw new Error(
|
|
1795
|
+
`${context}: \`enum\` values must all be strings.`
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
opts.enum = [...raw.enum];
|
|
1799
|
+
}
|
|
1517
1800
|
return opts;
|
|
1518
1801
|
}
|
|
1519
1802
|
function requireField(raw, field, context) {
|
|
@@ -1636,20 +1919,39 @@ function loadSchemaFromTomlString(tomlString, options = {}) {
|
|
|
1636
1919
|
}
|
|
1637
1920
|
|
|
1638
1921
|
// src/cloudflare.ts
|
|
1922
|
+
init_uniqueIndex();
|
|
1639
1923
|
init_metaSync();
|
|
1924
|
+
init_writeLifecycle();
|
|
1640
1925
|
export {
|
|
1641
1926
|
DOClientEngine,
|
|
1927
|
+
applyAutoStampsFromSchema,
|
|
1928
|
+
applyDefaultsFromSchema,
|
|
1929
|
+
applyStringSetChange,
|
|
1930
|
+
applyStringSetDelta,
|
|
1931
|
+
assertNever,
|
|
1932
|
+
buildUniqueKey,
|
|
1642
1933
|
clearMetaSyncCache,
|
|
1643
1934
|
connectDoDb,
|
|
1935
|
+
decodeFunctionDefault,
|
|
1644
1936
|
discoverModelNames,
|
|
1645
1937
|
discoverSchema,
|
|
1938
|
+
ensureStringSetYMap,
|
|
1939
|
+
fieldUniqueConstraintName,
|
|
1940
|
+
fieldWriteKind,
|
|
1646
1941
|
getActiveDOEngine,
|
|
1647
1942
|
inferFieldType,
|
|
1648
1943
|
initJsBaoDO,
|
|
1944
|
+
isKnownFieldType,
|
|
1649
1945
|
loadSchemaFromTomlString,
|
|
1946
|
+
parseStringSetOp,
|
|
1650
1947
|
registerFunctionDefault,
|
|
1948
|
+
registerFunctionDefaultGenerator,
|
|
1949
|
+
replaceStringSet,
|
|
1651
1950
|
resetJsBaoDO,
|
|
1951
|
+
resolveDefaultValue,
|
|
1652
1952
|
schemaToToml,
|
|
1653
1953
|
syncInferredMeta,
|
|
1654
|
-
syncModelMeta
|
|
1954
|
+
syncModelMeta,
|
|
1955
|
+
uniqueIndexMapName,
|
|
1956
|
+
writeField
|
|
1655
1957
|
};
|