js-bao 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +367 -1
- package/dist/browser.d.cts +126 -1
- package/dist/browser.d.ts +126 -1
- package/dist/browser.js +367 -1
- package/dist/client.cjs +16 -11
- package/dist/client.d.cts +3 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.js +16 -11
- package/dist/cloudflare-do.cjs +937 -286
- package/dist/cloudflare-do.d.cts +517 -15
- package/dist/cloudflare-do.d.ts +517 -15
- package/dist/cloudflare-do.js +928 -286
- package/dist/cloudflare.cjs +573 -18
- package/dist/cloudflare.d.cts +147 -2
- package/dist/cloudflare.d.ts +147 -2
- package/dist/cloudflare.js +573 -18
- package/dist/codegen.cjs +6 -6
- package/dist/index.cjs +19 -10
- package/dist/index.js +19 -10
- package/dist/node.cjs +388 -6
- package/dist/node.d.cts +131 -1
- package/dist/node.d.ts +131 -1
- package/dist/node.js +377 -5
- package/package.json +6 -6
package/dist/browser.js
CHANGED
|
@@ -1163,6 +1163,19 @@ var init_DocumentQueryTranslator = __esm({
|
|
|
1163
1163
|
|
|
1164
1164
|
// src/models/metaSync.ts
|
|
1165
1165
|
import * as Y from "yjs";
|
|
1166
|
+
function inferFieldType(value) {
|
|
1167
|
+
if (value instanceof Y.Map) return "stringset";
|
|
1168
|
+
switch (typeof value) {
|
|
1169
|
+
case "string":
|
|
1170
|
+
return "string";
|
|
1171
|
+
case "number":
|
|
1172
|
+
return "number";
|
|
1173
|
+
case "boolean":
|
|
1174
|
+
return "boolean";
|
|
1175
|
+
default:
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1166
1179
|
function registerFunctionDefault(fn, name) {
|
|
1167
1180
|
KNOWN_FUNCTION_DEFAULTS.set(fn, name);
|
|
1168
1181
|
}
|
|
@@ -1174,6 +1187,11 @@ function encodeDefault(value) {
|
|
|
1174
1187
|
}
|
|
1175
1188
|
return value;
|
|
1176
1189
|
}
|
|
1190
|
+
function clearMetaSyncCache(yDoc) {
|
|
1191
|
+
if (yDoc) {
|
|
1192
|
+
_syncedCache.delete(yDoc);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1177
1195
|
function syncModelMeta(yDoc, modelName, schema) {
|
|
1178
1196
|
let synced = _syncedCache.get(yDoc);
|
|
1179
1197
|
if (synced?.has(modelName)) return;
|
|
@@ -1249,6 +1267,23 @@ function syncRelationshipMeta(relsMap, relName, relConfig) {
|
|
|
1249
1267
|
}
|
|
1250
1268
|
}
|
|
1251
1269
|
}
|
|
1270
|
+
function syncInferredMeta(yDoc, modelName, recordData) {
|
|
1271
|
+
const meta = yDoc.getMap(`_meta_${modelName}`);
|
|
1272
|
+
for (const [fieldName, value] of Object.entries(recordData)) {
|
|
1273
|
+
if (fieldName.startsWith("_")) continue;
|
|
1274
|
+
let fieldMeta = meta.get(fieldName);
|
|
1275
|
+
if (!fieldMeta) {
|
|
1276
|
+
fieldMeta = new Y.Map();
|
|
1277
|
+
meta.set(fieldName, fieldMeta);
|
|
1278
|
+
}
|
|
1279
|
+
if (!fieldMeta.has("type")) {
|
|
1280
|
+
const inferredType = inferFieldType(value);
|
|
1281
|
+
if (inferredType) {
|
|
1282
|
+
fieldMeta.set("type", inferredType);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1252
1287
|
function setIfChanged(map, key, value) {
|
|
1253
1288
|
if (map.get(key) !== value) {
|
|
1254
1289
|
map.set(key, value);
|
|
@@ -6510,6 +6545,328 @@ function attachAndRegisterModel(modelClass, schema) {
|
|
|
6510
6545
|
const runtimeShape = attachSchemaToClass(modelClass, schema);
|
|
6511
6546
|
autoRegisterModel(modelClass, runtimeShape);
|
|
6512
6547
|
}
|
|
6548
|
+
|
|
6549
|
+
// src/utils/yDocSchema.ts
|
|
6550
|
+
import * as Y3 from "yjs";
|
|
6551
|
+
function discoverSchema(yDoc) {
|
|
6552
|
+
const models = {};
|
|
6553
|
+
const metaNames = /* @__PURE__ */ new Set();
|
|
6554
|
+
for (const key of yDoc.share.keys()) {
|
|
6555
|
+
if (!key.startsWith("_meta_")) continue;
|
|
6556
|
+
const map = materializeMap(yDoc, key);
|
|
6557
|
+
if (!map) continue;
|
|
6558
|
+
const modelName = key.slice("_meta_".length);
|
|
6559
|
+
metaNames.add(modelName);
|
|
6560
|
+
models[modelName] = readModelMeta(map);
|
|
6561
|
+
}
|
|
6562
|
+
for (const key of yDoc.share.keys()) {
|
|
6563
|
+
if (key.startsWith("_")) continue;
|
|
6564
|
+
if (metaNames.has(key)) continue;
|
|
6565
|
+
const map = materializeMap(yDoc, key);
|
|
6566
|
+
if (!map || map.size === 0) continue;
|
|
6567
|
+
const inferred = inferModelFromData(map);
|
|
6568
|
+
if (inferred) models[key] = inferred;
|
|
6569
|
+
}
|
|
6570
|
+
return { models };
|
|
6571
|
+
}
|
|
6572
|
+
function discoverModelNames(yDoc) {
|
|
6573
|
+
const names = [];
|
|
6574
|
+
for (const key of yDoc.share.keys()) {
|
|
6575
|
+
if (key.startsWith("_")) continue;
|
|
6576
|
+
const map = materializeMap(yDoc, key);
|
|
6577
|
+
if (map) names.push(key);
|
|
6578
|
+
}
|
|
6579
|
+
return names.sort();
|
|
6580
|
+
}
|
|
6581
|
+
function materializeMap(yDoc, key) {
|
|
6582
|
+
try {
|
|
6583
|
+
const map = yDoc.getMap(key);
|
|
6584
|
+
return map instanceof Y3.Map ? map : null;
|
|
6585
|
+
} catch {
|
|
6586
|
+
return null;
|
|
6587
|
+
}
|
|
6588
|
+
}
|
|
6589
|
+
function readModelMeta(metaMap) {
|
|
6590
|
+
const fields = {};
|
|
6591
|
+
let constraints;
|
|
6592
|
+
let relationships;
|
|
6593
|
+
for (const [key, value] of metaMap.entries()) {
|
|
6594
|
+
if (key === "_constraints" && value instanceof Y3.Map) {
|
|
6595
|
+
constraints = readConstraints(value);
|
|
6596
|
+
} else if (key === "_relationships" && value instanceof Y3.Map) {
|
|
6597
|
+
relationships = readRelationships(value);
|
|
6598
|
+
} else if (value instanceof Y3.Map) {
|
|
6599
|
+
fields[key] = readFieldMeta(value);
|
|
6600
|
+
}
|
|
6601
|
+
}
|
|
6602
|
+
const model = { fields };
|
|
6603
|
+
if (constraints && Object.keys(constraints).length > 0) {
|
|
6604
|
+
model.constraints = constraints;
|
|
6605
|
+
}
|
|
6606
|
+
if (relationships && Object.keys(relationships).length > 0) {
|
|
6607
|
+
model.relationships = relationships;
|
|
6608
|
+
}
|
|
6609
|
+
return model;
|
|
6610
|
+
}
|
|
6611
|
+
function readFieldMeta(fieldMap) {
|
|
6612
|
+
const field = { type: fieldMap.get("type") ?? "unknown" };
|
|
6613
|
+
if (fieldMap.get("indexed") === true) field.indexed = true;
|
|
6614
|
+
if (fieldMap.get("unique") === true) field.unique = true;
|
|
6615
|
+
if (fieldMap.get("required") === true) field.required = true;
|
|
6616
|
+
if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
|
|
6617
|
+
const def = fieldMap.get("default");
|
|
6618
|
+
if (def !== void 0) field.default = def;
|
|
6619
|
+
const maxLength = fieldMap.get("maxLength");
|
|
6620
|
+
if (maxLength !== void 0) field.maxLength = maxLength;
|
|
6621
|
+
const maxCount = fieldMap.get("maxCount");
|
|
6622
|
+
if (maxCount !== void 0) field.maxCount = maxCount;
|
|
6623
|
+
return field;
|
|
6624
|
+
}
|
|
6625
|
+
function inferModelFromData(dataMap) {
|
|
6626
|
+
const fields = {};
|
|
6627
|
+
let sampled = 0;
|
|
6628
|
+
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
6629
|
+
if (!(recordValue instanceof Y3.Map)) continue;
|
|
6630
|
+
if (++sampled > 5) break;
|
|
6631
|
+
for (const [fieldName, value] of recordValue.entries()) {
|
|
6632
|
+
if (fieldName.startsWith("_")) continue;
|
|
6633
|
+
if (fields[fieldName]) continue;
|
|
6634
|
+
const type = inferTypeFromValue(value);
|
|
6635
|
+
if (type) fields[fieldName] = { type };
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
if (Object.keys(fields).length === 0) return null;
|
|
6639
|
+
return { fields };
|
|
6640
|
+
}
|
|
6641
|
+
function inferTypeFromValue(value) {
|
|
6642
|
+
if (value instanceof Y3.Map) return "stringset";
|
|
6643
|
+
switch (typeof value) {
|
|
6644
|
+
case "string":
|
|
6645
|
+
return "string";
|
|
6646
|
+
case "number":
|
|
6647
|
+
return "number";
|
|
6648
|
+
case "boolean":
|
|
6649
|
+
return "boolean";
|
|
6650
|
+
default:
|
|
6651
|
+
return null;
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
function readConstraints(constraintsMap) {
|
|
6655
|
+
const out = {};
|
|
6656
|
+
for (const [name, value] of constraintsMap.entries()) {
|
|
6657
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
6658
|
+
let fields = [];
|
|
6659
|
+
const rawFields = value.get("fields");
|
|
6660
|
+
if (typeof rawFields === "string") {
|
|
6661
|
+
try {
|
|
6662
|
+
fields = JSON.parse(rawFields);
|
|
6663
|
+
} catch {
|
|
6664
|
+
}
|
|
6665
|
+
}
|
|
6666
|
+
out[name] = {
|
|
6667
|
+
type: value.get("type") ?? "unknown",
|
|
6668
|
+
fields
|
|
6669
|
+
};
|
|
6670
|
+
}
|
|
6671
|
+
return out;
|
|
6672
|
+
}
|
|
6673
|
+
function readRelationships(relsMap) {
|
|
6674
|
+
const out = {};
|
|
6675
|
+
for (const [name, value] of relsMap.entries()) {
|
|
6676
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
6677
|
+
const rel = {};
|
|
6678
|
+
for (const [k, v] of value.entries()) {
|
|
6679
|
+
rel[k] = v;
|
|
6680
|
+
}
|
|
6681
|
+
out[name] = rel;
|
|
6682
|
+
}
|
|
6683
|
+
return out;
|
|
6684
|
+
}
|
|
6685
|
+
var CAMEL_TO_SNAKE = {
|
|
6686
|
+
autoAssign: "auto_assign",
|
|
6687
|
+
maxLength: "max_length",
|
|
6688
|
+
maxCount: "max_count",
|
|
6689
|
+
relatedIdField: "related_id_field",
|
|
6690
|
+
joinModel: "join_model",
|
|
6691
|
+
joinModelLocalField: "join_model_local_field",
|
|
6692
|
+
joinModelRelatedField: "join_model_related_field",
|
|
6693
|
+
joinModelOrderByField: "join_model_order_by_field",
|
|
6694
|
+
joinModelOrderDirection: "join_model_order_direction",
|
|
6695
|
+
orderByField: "order_by_field",
|
|
6696
|
+
orderDirection: "order_direction"
|
|
6697
|
+
};
|
|
6698
|
+
function toSnake(key) {
|
|
6699
|
+
return CAMEL_TO_SNAKE[key] ?? key;
|
|
6700
|
+
}
|
|
6701
|
+
function tomlValue(v) {
|
|
6702
|
+
if (typeof v === "string") {
|
|
6703
|
+
return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
|
|
6704
|
+
}
|
|
6705
|
+
return String(v);
|
|
6706
|
+
}
|
|
6707
|
+
function schemaToToml(schema) {
|
|
6708
|
+
const lines = [];
|
|
6709
|
+
for (const [modelName, model] of Object.entries(schema.models)) {
|
|
6710
|
+
if (lines.length > 0) lines.push("", "");
|
|
6711
|
+
lines.push(`[models.${modelName}]`);
|
|
6712
|
+
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
6713
|
+
lines.push("");
|
|
6714
|
+
lines.push(`[models.${modelName}.fields.${fieldName}]`);
|
|
6715
|
+
lines.push(`type = ${tomlValue(field.type)}`);
|
|
6716
|
+
if (field.autoAssign) lines.push("auto_assign = true");
|
|
6717
|
+
if (field.indexed) lines.push("indexed = true");
|
|
6718
|
+
if (field.unique) lines.push("unique = true");
|
|
6719
|
+
if (field.required) lines.push("required = true");
|
|
6720
|
+
if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
|
|
6721
|
+
if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
|
|
6722
|
+
if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
|
|
6723
|
+
}
|
|
6724
|
+
if (model.relationships) {
|
|
6725
|
+
for (const [relName, rel] of Object.entries(model.relationships)) {
|
|
6726
|
+
lines.push("");
|
|
6727
|
+
lines.push(`[models.${modelName}.relationships.${relName}]`);
|
|
6728
|
+
for (const [k, v] of Object.entries(rel)) {
|
|
6729
|
+
if (v === void 0) continue;
|
|
6730
|
+
lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6733
|
+
}
|
|
6734
|
+
if (model.constraints) {
|
|
6735
|
+
for (const [cName, c] of Object.entries(model.constraints)) {
|
|
6736
|
+
lines.push("");
|
|
6737
|
+
lines.push(`[[models.${modelName}.unique_constraints]]`);
|
|
6738
|
+
lines.push(`name = ${tomlValue(cName)}`);
|
|
6739
|
+
lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
|
|
6740
|
+
}
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
lines.push("");
|
|
6744
|
+
return lines.join("\n");
|
|
6745
|
+
}
|
|
6746
|
+
|
|
6747
|
+
// src/models/tomlLoader.ts
|
|
6748
|
+
import { parse as parseToml } from "smol-toml";
|
|
6749
|
+
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
6750
|
+
"string",
|
|
6751
|
+
"number",
|
|
6752
|
+
"boolean",
|
|
6753
|
+
"date",
|
|
6754
|
+
"id",
|
|
6755
|
+
"stringset"
|
|
6756
|
+
]);
|
|
6757
|
+
function parseFieldOptions(raw) {
|
|
6758
|
+
if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
|
|
6759
|
+
throw new Error(
|
|
6760
|
+
`Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
|
|
6761
|
+
);
|
|
6762
|
+
}
|
|
6763
|
+
const opts = { type: raw.type };
|
|
6764
|
+
if (raw.indexed === true) opts.indexed = true;
|
|
6765
|
+
if (raw.unique === true) opts.unique = true;
|
|
6766
|
+
if (raw.required === true) opts.required = true;
|
|
6767
|
+
if (raw.auto_assign === true) opts.autoAssign = true;
|
|
6768
|
+
if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
|
|
6769
|
+
if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
|
|
6770
|
+
if (raw.default !== void 0) opts.default = raw.default;
|
|
6771
|
+
return opts;
|
|
6772
|
+
}
|
|
6773
|
+
function requireField(raw, field, context) {
|
|
6774
|
+
if (!raw[field]) {
|
|
6775
|
+
throw new Error(`Relationship ${context}: missing required field "${field}"`);
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6778
|
+
function parseRelationship(raw) {
|
|
6779
|
+
const type = raw.type;
|
|
6780
|
+
if (type === "refersTo") {
|
|
6781
|
+
requireField(raw, "model", "refersTo");
|
|
6782
|
+
requireField(raw, "related_id_field", "refersTo");
|
|
6783
|
+
return {
|
|
6784
|
+
type: "refersTo",
|
|
6785
|
+
model: raw.model,
|
|
6786
|
+
relatedIdField: raw.related_id_field
|
|
6787
|
+
};
|
|
6788
|
+
}
|
|
6789
|
+
if (type === "hasMany") {
|
|
6790
|
+
requireField(raw, "model", "hasMany");
|
|
6791
|
+
requireField(raw, "related_id_field", "hasMany");
|
|
6792
|
+
const rel = {
|
|
6793
|
+
type: "hasMany",
|
|
6794
|
+
model: raw.model,
|
|
6795
|
+
relatedIdField: raw.related_id_field
|
|
6796
|
+
};
|
|
6797
|
+
if (raw.order_by_field) rel.orderByField = raw.order_by_field;
|
|
6798
|
+
if (raw.order_direction) rel.orderDirection = raw.order_direction;
|
|
6799
|
+
return rel;
|
|
6800
|
+
}
|
|
6801
|
+
if (type === "hasManyThrough") {
|
|
6802
|
+
requireField(raw, "model", "hasManyThrough");
|
|
6803
|
+
requireField(raw, "join_model", "hasManyThrough");
|
|
6804
|
+
requireField(raw, "join_model_local_field", "hasManyThrough");
|
|
6805
|
+
requireField(raw, "join_model_related_field", "hasManyThrough");
|
|
6806
|
+
const rel = {
|
|
6807
|
+
type: "hasManyThrough",
|
|
6808
|
+
model: raw.model,
|
|
6809
|
+
joinModel: raw.join_model,
|
|
6810
|
+
joinModelLocalField: raw.join_model_local_field,
|
|
6811
|
+
joinModelRelatedField: raw.join_model_related_field
|
|
6812
|
+
};
|
|
6813
|
+
if (raw.join_model_order_by_field)
|
|
6814
|
+
rel.joinModelOrderByField = raw.join_model_order_by_field;
|
|
6815
|
+
if (raw.join_model_order_direction)
|
|
6816
|
+
rel.joinModelOrderDirection = raw.join_model_order_direction;
|
|
6817
|
+
return rel;
|
|
6818
|
+
}
|
|
6819
|
+
throw new Error(`Unknown relationship type: ${type}`);
|
|
6820
|
+
}
|
|
6821
|
+
function loadSchemaFromTomlString(tomlString) {
|
|
6822
|
+
const parsed = parseToml(tomlString);
|
|
6823
|
+
const models = parsed.models;
|
|
6824
|
+
if (!models || typeof models !== "object") {
|
|
6825
|
+
throw new Error("TOML schema must have a [models] section");
|
|
6826
|
+
}
|
|
6827
|
+
const schemas = [];
|
|
6828
|
+
for (const [modelName, modelDef] of Object.entries(models)) {
|
|
6829
|
+
const fields = {};
|
|
6830
|
+
if (modelDef.fields) {
|
|
6831
|
+
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
6832
|
+
fields[fieldName] = parseFieldOptions(fieldDef);
|
|
6833
|
+
}
|
|
6834
|
+
}
|
|
6835
|
+
let relationships;
|
|
6836
|
+
if (modelDef.relationships) {
|
|
6837
|
+
relationships = {};
|
|
6838
|
+
for (const [relName, relDef] of Object.entries(
|
|
6839
|
+
modelDef.relationships
|
|
6840
|
+
)) {
|
|
6841
|
+
relationships[relName] = parseRelationship(relDef);
|
|
6842
|
+
}
|
|
6843
|
+
}
|
|
6844
|
+
let uniqueConstraints;
|
|
6845
|
+
if (modelDef.unique_constraints) {
|
|
6846
|
+
uniqueConstraints = [];
|
|
6847
|
+
for (const raw of modelDef.unique_constraints) {
|
|
6848
|
+
uniqueConstraints.push({
|
|
6849
|
+
name: raw.name,
|
|
6850
|
+
fields: [...raw.fields]
|
|
6851
|
+
});
|
|
6852
|
+
}
|
|
6853
|
+
}
|
|
6854
|
+
schemas.push(
|
|
6855
|
+
defineModelSchema({
|
|
6856
|
+
name: modelName,
|
|
6857
|
+
fields,
|
|
6858
|
+
options: {
|
|
6859
|
+
uniqueConstraints,
|
|
6860
|
+
relationships
|
|
6861
|
+
}
|
|
6862
|
+
})
|
|
6863
|
+
);
|
|
6864
|
+
}
|
|
6865
|
+
return schemas;
|
|
6866
|
+
}
|
|
6867
|
+
|
|
6868
|
+
// src/browser.ts
|
|
6869
|
+
init_metaSync();
|
|
6513
6870
|
export {
|
|
6514
6871
|
BaseModel2 as BaseModel,
|
|
6515
6872
|
DatabaseEngine,
|
|
@@ -6526,13 +6883,22 @@ export {
|
|
|
6526
6883
|
attachAndRegisterModel,
|
|
6527
6884
|
attachSchemaToClass,
|
|
6528
6885
|
autoRegisterModel,
|
|
6886
|
+
clearMetaSyncCache,
|
|
6529
6887
|
createModelClass,
|
|
6530
6888
|
defineModelSchema,
|
|
6531
6889
|
detectEnvironment,
|
|
6890
|
+
discoverModelNames,
|
|
6891
|
+
discoverSchema,
|
|
6532
6892
|
features,
|
|
6533
6893
|
generateULID,
|
|
6894
|
+
inferFieldType,
|
|
6534
6895
|
initJsBao,
|
|
6535
6896
|
isBrowser,
|
|
6536
6897
|
isNode,
|
|
6537
|
-
|
|
6898
|
+
loadSchemaFromTomlString,
|
|
6899
|
+
registerFunctionDefault,
|
|
6900
|
+
resetJsBao,
|
|
6901
|
+
schemaToToml,
|
|
6902
|
+
syncInferredMeta,
|
|
6903
|
+
syncModelMeta
|
|
6538
6904
|
};
|
package/dist/client.cjs
CHANGED
|
@@ -337,7 +337,8 @@ var DOClientEngine = class extends DatabaseEngine {
|
|
|
337
337
|
data,
|
|
338
338
|
stringSets,
|
|
339
339
|
ifNotExists: options?.ifNotExists,
|
|
340
|
-
condition: options?.condition
|
|
340
|
+
condition: options?.condition,
|
|
341
|
+
upsertOn: options?.upsertOn
|
|
341
342
|
};
|
|
342
343
|
const response = await this.doFetch("/save", request);
|
|
343
344
|
return response.id;
|
|
@@ -670,22 +671,24 @@ function createModelAccessor(engine, modelName) {
|
|
|
670
671
|
return result.data.length > 0 ? result.data[0] : null;
|
|
671
672
|
},
|
|
672
673
|
save: (data, options) => {
|
|
673
|
-
if (!data.id) {
|
|
674
|
-
throw new Error("Record must have an 'id' field");
|
|
675
|
-
}
|
|
676
674
|
let stringSets;
|
|
677
675
|
let ifNotExists;
|
|
678
676
|
let condition;
|
|
677
|
+
let upsertOn;
|
|
679
678
|
if (options && typeof options === "object") {
|
|
680
|
-
if (options.ifNotExists !== void 0 || options.stringSets !== void 0 || options.condition !== void 0) {
|
|
679
|
+
if (options.ifNotExists !== void 0 || options.stringSets !== void 0 || options.condition !== void 0 || options.upsertOn !== void 0) {
|
|
681
680
|
stringSets = options.stringSets;
|
|
682
681
|
ifNotExists = options.ifNotExists;
|
|
683
682
|
condition = options.condition;
|
|
683
|
+
upsertOn = options.upsertOn;
|
|
684
684
|
} else {
|
|
685
685
|
stringSets = options;
|
|
686
686
|
}
|
|
687
687
|
}
|
|
688
|
-
|
|
688
|
+
if (!data.id && !upsertOn) {
|
|
689
|
+
throw new Error("Record must have an 'id' field (or use upsertOn)");
|
|
690
|
+
}
|
|
691
|
+
return engine.saveModel(modelName, data.id, data, stringSets, { ifNotExists, condition, upsertOn });
|
|
689
692
|
},
|
|
690
693
|
patch: (id, data, options) => {
|
|
691
694
|
let stringSets;
|
|
@@ -772,22 +775,24 @@ function connectDoDb(options) {
|
|
|
772
775
|
return result.data.length > 0 ? result.data[0] : null;
|
|
773
776
|
},
|
|
774
777
|
save: (model, data, options2) => {
|
|
775
|
-
if (!data.id) {
|
|
776
|
-
throw new Error("Record must have an 'id' field");
|
|
777
|
-
}
|
|
778
778
|
let stringSets;
|
|
779
779
|
let ifNotExists;
|
|
780
780
|
let condition;
|
|
781
|
+
let upsertOn;
|
|
781
782
|
if (options2 && typeof options2 === "object") {
|
|
782
|
-
if (options2.ifNotExists !== void 0 || options2.stringSets !== void 0 || options2.condition !== void 0) {
|
|
783
|
+
if (options2.ifNotExists !== void 0 || options2.stringSets !== void 0 || options2.condition !== void 0 || options2.upsertOn !== void 0) {
|
|
783
784
|
stringSets = options2.stringSets;
|
|
784
785
|
ifNotExists = options2.ifNotExists;
|
|
785
786
|
condition = options2.condition;
|
|
787
|
+
upsertOn = options2.upsertOn;
|
|
786
788
|
} else {
|
|
787
789
|
stringSets = options2;
|
|
788
790
|
}
|
|
789
791
|
}
|
|
790
|
-
|
|
792
|
+
if (!data.id && !upsertOn) {
|
|
793
|
+
throw new Error("Record must have an 'id' field (or use upsertOn)");
|
|
794
|
+
}
|
|
795
|
+
return engine.saveModel(resolveModelName(model), data.id, data, stringSets, { ifNotExists, condition, upsertOn });
|
|
791
796
|
},
|
|
792
797
|
patch: (model, id2, data, options2) => {
|
|
793
798
|
let stringSets;
|
package/dist/client.d.cts
CHANGED
|
@@ -825,9 +825,10 @@ declare class DOClientEngine extends DatabaseEngine {
|
|
|
825
825
|
/**
|
|
826
826
|
* Save a record to the DO.
|
|
827
827
|
*/
|
|
828
|
-
saveModel(modelName: string, id: string, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
828
|
+
saveModel(modelName: string, id: string | undefined, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
829
829
|
ifNotExists?: boolean;
|
|
830
830
|
condition?: DocumentFilter;
|
|
831
|
+
upsertOn?: string;
|
|
831
832
|
}): Promise<string>;
|
|
832
833
|
/**
|
|
833
834
|
* Patch (partial update) a record in the DO.
|
|
@@ -1017,6 +1018,7 @@ interface SaveOptions {
|
|
|
1017
1018
|
stringSets?: Record<string, string[]>;
|
|
1018
1019
|
ifNotExists?: boolean;
|
|
1019
1020
|
condition?: DocumentFilter;
|
|
1021
|
+
upsertOn?: string;
|
|
1020
1022
|
}
|
|
1021
1023
|
interface PatchOptions {
|
|
1022
1024
|
stringSets?: Record<string, string[]>;
|
package/dist/client.d.ts
CHANGED
|
@@ -825,9 +825,10 @@ declare class DOClientEngine extends DatabaseEngine {
|
|
|
825
825
|
/**
|
|
826
826
|
* Save a record to the DO.
|
|
827
827
|
*/
|
|
828
|
-
saveModel(modelName: string, id: string, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
828
|
+
saveModel(modelName: string, id: string | undefined, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
829
829
|
ifNotExists?: boolean;
|
|
830
830
|
condition?: DocumentFilter;
|
|
831
|
+
upsertOn?: string;
|
|
831
832
|
}): Promise<string>;
|
|
832
833
|
/**
|
|
833
834
|
* Patch (partial update) a record in the DO.
|
|
@@ -1017,6 +1018,7 @@ interface SaveOptions {
|
|
|
1017
1018
|
stringSets?: Record<string, string[]>;
|
|
1018
1019
|
ifNotExists?: boolean;
|
|
1019
1020
|
condition?: DocumentFilter;
|
|
1021
|
+
upsertOn?: string;
|
|
1020
1022
|
}
|
|
1021
1023
|
interface PatchOptions {
|
|
1022
1024
|
stringSets?: Record<string, string[]>;
|
package/dist/client.js
CHANGED
|
@@ -302,7 +302,8 @@ var DOClientEngine = class extends DatabaseEngine {
|
|
|
302
302
|
data,
|
|
303
303
|
stringSets,
|
|
304
304
|
ifNotExists: options?.ifNotExists,
|
|
305
|
-
condition: options?.condition
|
|
305
|
+
condition: options?.condition,
|
|
306
|
+
upsertOn: options?.upsertOn
|
|
306
307
|
};
|
|
307
308
|
const response = await this.doFetch("/save", request);
|
|
308
309
|
return response.id;
|
|
@@ -635,22 +636,24 @@ function createModelAccessor(engine, modelName) {
|
|
|
635
636
|
return result.data.length > 0 ? result.data[0] : null;
|
|
636
637
|
},
|
|
637
638
|
save: (data, options) => {
|
|
638
|
-
if (!data.id) {
|
|
639
|
-
throw new Error("Record must have an 'id' field");
|
|
640
|
-
}
|
|
641
639
|
let stringSets;
|
|
642
640
|
let ifNotExists;
|
|
643
641
|
let condition;
|
|
642
|
+
let upsertOn;
|
|
644
643
|
if (options && typeof options === "object") {
|
|
645
|
-
if (options.ifNotExists !== void 0 || options.stringSets !== void 0 || options.condition !== void 0) {
|
|
644
|
+
if (options.ifNotExists !== void 0 || options.stringSets !== void 0 || options.condition !== void 0 || options.upsertOn !== void 0) {
|
|
646
645
|
stringSets = options.stringSets;
|
|
647
646
|
ifNotExists = options.ifNotExists;
|
|
648
647
|
condition = options.condition;
|
|
648
|
+
upsertOn = options.upsertOn;
|
|
649
649
|
} else {
|
|
650
650
|
stringSets = options;
|
|
651
651
|
}
|
|
652
652
|
}
|
|
653
|
-
|
|
653
|
+
if (!data.id && !upsertOn) {
|
|
654
|
+
throw new Error("Record must have an 'id' field (or use upsertOn)");
|
|
655
|
+
}
|
|
656
|
+
return engine.saveModel(modelName, data.id, data, stringSets, { ifNotExists, condition, upsertOn });
|
|
654
657
|
},
|
|
655
658
|
patch: (id, data, options) => {
|
|
656
659
|
let stringSets;
|
|
@@ -737,22 +740,24 @@ function connectDoDb(options) {
|
|
|
737
740
|
return result.data.length > 0 ? result.data[0] : null;
|
|
738
741
|
},
|
|
739
742
|
save: (model, data, options2) => {
|
|
740
|
-
if (!data.id) {
|
|
741
|
-
throw new Error("Record must have an 'id' field");
|
|
742
|
-
}
|
|
743
743
|
let stringSets;
|
|
744
744
|
let ifNotExists;
|
|
745
745
|
let condition;
|
|
746
|
+
let upsertOn;
|
|
746
747
|
if (options2 && typeof options2 === "object") {
|
|
747
|
-
if (options2.ifNotExists !== void 0 || options2.stringSets !== void 0 || options2.condition !== void 0) {
|
|
748
|
+
if (options2.ifNotExists !== void 0 || options2.stringSets !== void 0 || options2.condition !== void 0 || options2.upsertOn !== void 0) {
|
|
748
749
|
stringSets = options2.stringSets;
|
|
749
750
|
ifNotExists = options2.ifNotExists;
|
|
750
751
|
condition = options2.condition;
|
|
752
|
+
upsertOn = options2.upsertOn;
|
|
751
753
|
} else {
|
|
752
754
|
stringSets = options2;
|
|
753
755
|
}
|
|
754
756
|
}
|
|
755
|
-
|
|
757
|
+
if (!data.id && !upsertOn) {
|
|
758
|
+
throw new Error("Record must have an 'id' field (or use upsertOn)");
|
|
759
|
+
}
|
|
760
|
+
return engine.saveModel(resolveModelName(model), data.id, data, stringSets, { ifNotExists, condition, upsertOn });
|
|
756
761
|
},
|
|
757
762
|
patch: (model, id2, data, options2) => {
|
|
758
763
|
let stringSets;
|