js-bao 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +382 -143
- package/dist/browser.d.cts +127 -5
- package/dist/browser.d.ts +127 -5
- package/dist/browser.js +380 -141
- 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 +7 -15
- package/dist/index.cjs +32 -154
- package/dist/index.d.cts +2 -5
- package/dist/index.d.ts +2 -5
- package/dist/index.js +32 -152
- package/dist/node.cjs +404 -151
- package/dist/node.d.cts +132 -5
- package/dist/node.d.ts +132 -5
- package/dist/node.js +390 -145
- package/package.json +6 -6
package/dist/node.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);
|
|
@@ -1577,11 +1612,11 @@ var init_ModelRegistry = __esm({
|
|
|
1577
1612
|
init_relationshipManager();
|
|
1578
1613
|
ModelRegistry = class _ModelRegistry {
|
|
1579
1614
|
static instance;
|
|
1580
|
-
// Stores globally registered model classes by their name
|
|
1615
|
+
// Stores globally registered model classes by their name
|
|
1581
1616
|
models = /* @__PURE__ */ new Map();
|
|
1582
|
-
// Stores options for globally registered models
|
|
1617
|
+
// Stores options for globally registered models
|
|
1583
1618
|
modelOptions = /* @__PURE__ */ new Map();
|
|
1584
|
-
// Stores fields for globally registered models (
|
|
1619
|
+
// Stores fields for globally registered models (or a static getter on class)
|
|
1585
1620
|
// For simplicity, let's assume fields can be derived or are less critical for this registry part
|
|
1586
1621
|
// private modelFields: Map<string, Map<string, FieldOptions>> = new Map();
|
|
1587
1622
|
// Holds the subset of models explicitly set for the current initialization session
|
|
@@ -1599,7 +1634,7 @@ var init_ModelRegistry = __esm({
|
|
|
1599
1634
|
registerModel(modelClass, options, fields) {
|
|
1600
1635
|
if (!options.name) {
|
|
1601
1636
|
throw new Error(
|
|
1602
|
-
`[ModelRegistry] Model class is missing a name in its
|
|
1637
|
+
`[ModelRegistry] Model class is missing a name in its options. Ensure the schema passed to defineModelSchema/createModelClass/attachAndRegisterModel includes a 'name' property.`
|
|
1603
1638
|
);
|
|
1604
1639
|
}
|
|
1605
1640
|
if (this.models.has(options.name)) {
|
|
@@ -1643,7 +1678,7 @@ var init_ModelRegistry = __esm({
|
|
|
1643
1678
|
}
|
|
1644
1679
|
return infos;
|
|
1645
1680
|
}
|
|
1646
|
-
// Helper to get model name from class (
|
|
1681
|
+
// Helper to get model name from class (set by attachAndRegisterModel/createModelClass)
|
|
1647
1682
|
getModelNameFromClass(modelClass) {
|
|
1648
1683
|
return modelClass.modelName;
|
|
1649
1684
|
}
|
|
@@ -1654,13 +1689,13 @@ var init_ModelRegistry = __esm({
|
|
|
1654
1689
|
const modelName = this.getModelNameFromClass(modelClass);
|
|
1655
1690
|
if (!modelName) {
|
|
1656
1691
|
console.warn(
|
|
1657
|
-
`[ModelRegistry] A model class provided to setExplicitModelsForSession does not have a static 'modelName' property or it's undefined. It will be ignored. Ensure
|
|
1692
|
+
`[ModelRegistry] A model class provided to setExplicitModelsForSession does not have a static 'modelName' property or it's undefined. It will be ignored. Ensure attachAndRegisterModel (or createModelClass) was called for this model.`
|
|
1658
1693
|
);
|
|
1659
1694
|
return;
|
|
1660
1695
|
}
|
|
1661
1696
|
if (!this.models.has(modelName) || this.models.get(modelName) !== modelClass) {
|
|
1662
1697
|
console.warn(
|
|
1663
|
-
`[ModelRegistry] Model class with name ${modelName} provided to setExplicitModelsForSession was not found in the global
|
|
1698
|
+
`[ModelRegistry] Model class with name ${modelName} provided to setExplicitModelsForSession was not found in the global registry or does not match. It will be ignored. Ensure the model file is imported and attachAndRegisterModel (or createModelClass) has run.`
|
|
1664
1699
|
);
|
|
1665
1700
|
return;
|
|
1666
1701
|
}
|
|
@@ -1690,7 +1725,7 @@ var init_ModelRegistry = __esm({
|
|
|
1690
1725
|
} else {
|
|
1691
1726
|
this.activeSessionModels = null;
|
|
1692
1727
|
console.log(
|
|
1693
|
-
"[ModelRegistry] No explicit models specified for session (undefined), will use all
|
|
1728
|
+
"[ModelRegistry] No explicit models specified for session (undefined), will use all globally registered models."
|
|
1694
1729
|
);
|
|
1695
1730
|
}
|
|
1696
1731
|
this.validateSessionModels();
|
|
@@ -1701,7 +1736,7 @@ var init_ModelRegistry = __esm({
|
|
|
1701
1736
|
const modelsToInitialize = this.activeSessionModels || this.models;
|
|
1702
1737
|
if (modelsToInitialize.size === 0) {
|
|
1703
1738
|
console.warn(
|
|
1704
|
-
"[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via
|
|
1739
|
+
"[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1705
1740
|
);
|
|
1706
1741
|
return;
|
|
1707
1742
|
}
|
|
@@ -1732,7 +1767,7 @@ var init_ModelRegistry = __esm({
|
|
|
1732
1767
|
const modelsToInitialize = this.activeSessionModels || this.models;
|
|
1733
1768
|
if (modelsToInitialize.size === 0) {
|
|
1734
1769
|
Logger.warn(
|
|
1735
|
-
"[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via
|
|
1770
|
+
"[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1736
1771
|
);
|
|
1737
1772
|
return;
|
|
1738
1773
|
}
|
|
@@ -1770,7 +1805,7 @@ var init_ModelRegistry = __esm({
|
|
|
1770
1805
|
const modelsToCleanup = this.activeSessionModels || this.models;
|
|
1771
1806
|
if (modelsToCleanup.size === 0) {
|
|
1772
1807
|
console.warn(
|
|
1773
|
-
"[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via
|
|
1808
|
+
"[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1774
1809
|
);
|
|
1775
1810
|
return;
|
|
1776
1811
|
}
|
|
@@ -2534,7 +2569,7 @@ var init_BaseModel = __esm({
|
|
|
2534
2569
|
getDocumentId() {
|
|
2535
2570
|
return this._metaDocId;
|
|
2536
2571
|
}
|
|
2537
|
-
// id is
|
|
2572
|
+
// id is a plain property. Subclasses define it via defineModelSchema.
|
|
2538
2573
|
id;
|
|
2539
2574
|
type;
|
|
2540
2575
|
// This should be the modelName from ModelOptions
|
|
@@ -3081,7 +3116,7 @@ var init_BaseModel = __esm({
|
|
|
3081
3116
|
const verboseEnabled = Logger.getLogLevel() >= 5 /* VERBOSE */;
|
|
3082
3117
|
if (!schema || !schema.options || !schema.options.name || !schema.resolvedUniqueConstraints) {
|
|
3083
3118
|
throw new Error(
|
|
3084
|
-
`[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to
|
|
3119
|
+
`[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to call attachAndRegisterModel (or autoRegisterModel) for this model?`
|
|
3085
3120
|
);
|
|
3086
3121
|
}
|
|
3087
3122
|
const modelName = schema.options.name;
|
|
@@ -6602,131 +6637,6 @@ var init_BrowserDatabaseFactory = __esm({
|
|
|
6602
6637
|
init_BaseModel();
|
|
6603
6638
|
init_ModelRegistry();
|
|
6604
6639
|
|
|
6605
|
-
// src/models/decorators.ts
|
|
6606
|
-
init_ModelRegistry();
|
|
6607
|
-
init_BaseModel();
|
|
6608
|
-
init_sql();
|
|
6609
|
-
var SCHEMA_FIELDS_PROPERTY = "_jsbaoSchemaFields";
|
|
6610
|
-
function Field(options) {
|
|
6611
|
-
return function(target, propertyKey) {
|
|
6612
|
-
const fieldName = String(propertyKey);
|
|
6613
|
-
const modelConstructor = target.constructor || target;
|
|
6614
|
-
assertValidIdentifier(
|
|
6615
|
-
fieldName,
|
|
6616
|
-
`[Field Decorator] Invalid field name on ${modelConstructor?.name || "unknown"}`
|
|
6617
|
-
);
|
|
6618
|
-
if (!modelConstructor) {
|
|
6619
|
-
console.error(
|
|
6620
|
-
"[Field Decorator] Could not determine model constructor for field:",
|
|
6621
|
-
fieldName,
|
|
6622
|
-
"Target:",
|
|
6623
|
-
target
|
|
6624
|
-
);
|
|
6625
|
-
throw new Error(
|
|
6626
|
-
`Failed to resolve model constructor for field '${fieldName}'.`
|
|
6627
|
-
);
|
|
6628
|
-
}
|
|
6629
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
6630
|
-
modelConstructor,
|
|
6631
|
-
SCHEMA_FIELDS_PROPERTY
|
|
6632
|
-
)) {
|
|
6633
|
-
modelConstructor[SCHEMA_FIELDS_PROPERTY] = /* @__PURE__ */ new Map();
|
|
6634
|
-
}
|
|
6635
|
-
modelConstructor[SCHEMA_FIELDS_PROPERTY].set(
|
|
6636
|
-
fieldName,
|
|
6637
|
-
options
|
|
6638
|
-
);
|
|
6639
|
-
Logger.debug(
|
|
6640
|
-
`[Field Decorator] Staged field "${fieldName}" for class ${modelConstructor.name}:`,
|
|
6641
|
-
options
|
|
6642
|
-
);
|
|
6643
|
-
};
|
|
6644
|
-
}
|
|
6645
|
-
function Model(options) {
|
|
6646
|
-
return function(targetClass) {
|
|
6647
|
-
Logger.debug(
|
|
6648
|
-
`[Model Decorator] Registering model:`,
|
|
6649
|
-
targetClass.name,
|
|
6650
|
-
options
|
|
6651
|
-
);
|
|
6652
|
-
assertValidIdentifier(
|
|
6653
|
-
options.name,
|
|
6654
|
-
`[Model Decorator] Invalid model name for ${targetClass.name}`
|
|
6655
|
-
);
|
|
6656
|
-
const registry = ModelRegistry.getInstance();
|
|
6657
|
-
targetClass.modelName = options.name;
|
|
6658
|
-
targetClass.getSchema = () => {
|
|
6659
|
-
const combinedFields = /* @__PURE__ */ new Map();
|
|
6660
|
-
const hierarchyStack = [];
|
|
6661
|
-
let currentEvalClass = targetClass;
|
|
6662
|
-
while (currentEvalClass && currentEvalClass.prototype) {
|
|
6663
|
-
hierarchyStack.push(currentEvalClass);
|
|
6664
|
-
const parentPrototype = Object.getPrototypeOf(
|
|
6665
|
-
currentEvalClass.prototype
|
|
6666
|
-
);
|
|
6667
|
-
currentEvalClass = parentPrototype ? parentPrototype.constructor : null;
|
|
6668
|
-
if (currentEvalClass === Object) break;
|
|
6669
|
-
}
|
|
6670
|
-
for (let i = hierarchyStack.length - 1; i >= 0; i--) {
|
|
6671
|
-
const cls = hierarchyStack[i];
|
|
6672
|
-
if (Object.prototype.hasOwnProperty.call(cls, SCHEMA_FIELDS_PROPERTY)) {
|
|
6673
|
-
const fieldsForClass = cls[SCHEMA_FIELDS_PROPERTY];
|
|
6674
|
-
fieldsForClass.forEach((fieldOpts, fieldName) => {
|
|
6675
|
-
combinedFields.set(fieldName, fieldOpts);
|
|
6676
|
-
});
|
|
6677
|
-
}
|
|
6678
|
-
}
|
|
6679
|
-
const resolvedUniqueConstraints = [];
|
|
6680
|
-
combinedFields.forEach((fieldOpts, fieldName) => {
|
|
6681
|
-
if (fieldOpts.unique) {
|
|
6682
|
-
const constraintName = `${options.name}_${fieldName}_unique`;
|
|
6683
|
-
resolvedUniqueConstraints.push({
|
|
6684
|
-
name: constraintName,
|
|
6685
|
-
fields: [fieldName]
|
|
6686
|
-
});
|
|
6687
|
-
}
|
|
6688
|
-
});
|
|
6689
|
-
if (options.uniqueConstraints) {
|
|
6690
|
-
options.uniqueConstraints.forEach(
|
|
6691
|
-
(constraintConfig) => {
|
|
6692
|
-
const allFieldsExist = constraintConfig.fields.every(
|
|
6693
|
-
(f) => combinedFields.has(f)
|
|
6694
|
-
);
|
|
6695
|
-
if (!allFieldsExist) {
|
|
6696
|
-
console.warn(
|
|
6697
|
-
`[Model Decorator] Unique constraint "${constraintConfig.name}" for model "${options.name}" specifies non-existent fields. Skipping.`
|
|
6698
|
-
);
|
|
6699
|
-
return;
|
|
6700
|
-
}
|
|
6701
|
-
if (resolvedUniqueConstraints.some(
|
|
6702
|
-
(rc) => rc.name === constraintConfig.name
|
|
6703
|
-
)) {
|
|
6704
|
-
console.warn(
|
|
6705
|
-
`[Model Decorator] Duplicate unique constraint name "${constraintConfig.name}" in model "${options.name}".`
|
|
6706
|
-
);
|
|
6707
|
-
}
|
|
6708
|
-
resolvedUniqueConstraints.push({
|
|
6709
|
-
name: constraintConfig.name,
|
|
6710
|
-
fields: constraintConfig.fields
|
|
6711
|
-
});
|
|
6712
|
-
}
|
|
6713
|
-
);
|
|
6714
|
-
}
|
|
6715
|
-
return {
|
|
6716
|
-
class: targetClass,
|
|
6717
|
-
options,
|
|
6718
|
-
fields: combinedFields,
|
|
6719
|
-
resolvedUniqueConstraints
|
|
6720
|
-
};
|
|
6721
|
-
};
|
|
6722
|
-
const directFieldsForThisClass = Object.prototype.hasOwnProperty.call(
|
|
6723
|
-
targetClass,
|
|
6724
|
-
SCHEMA_FIELDS_PROPERTY
|
|
6725
|
-
) ? targetClass[SCHEMA_FIELDS_PROPERTY] : /* @__PURE__ */ new Map();
|
|
6726
|
-
registry.registerModel(targetClass, options, directFieldsForThisClass);
|
|
6727
|
-
};
|
|
6728
|
-
}
|
|
6729
|
-
|
|
6730
6640
|
// src/engines/DatabaseEngine.ts
|
|
6731
6641
|
var DatabaseEngine = class {
|
|
6732
6642
|
createTable(_modelName, _schema, _options) {
|
|
@@ -7127,17 +7037,344 @@ function attachAndRegisterModel(modelClass, schema) {
|
|
|
7127
7037
|
autoRegisterModel(modelClass, runtimeShape);
|
|
7128
7038
|
}
|
|
7129
7039
|
|
|
7130
|
-
// src/utils/
|
|
7040
|
+
// src/utils/yDocSchema.ts
|
|
7131
7041
|
import * as Y3 from "yjs";
|
|
7042
|
+
function discoverSchema(yDoc) {
|
|
7043
|
+
const models = {};
|
|
7044
|
+
const metaNames = /* @__PURE__ */ new Set();
|
|
7045
|
+
for (const key of yDoc.share.keys()) {
|
|
7046
|
+
if (!key.startsWith("_meta_")) continue;
|
|
7047
|
+
const map = materializeMap(yDoc, key);
|
|
7048
|
+
if (!map) continue;
|
|
7049
|
+
const modelName = key.slice("_meta_".length);
|
|
7050
|
+
metaNames.add(modelName);
|
|
7051
|
+
models[modelName] = readModelMeta(map);
|
|
7052
|
+
}
|
|
7053
|
+
for (const key of yDoc.share.keys()) {
|
|
7054
|
+
if (key.startsWith("_")) continue;
|
|
7055
|
+
if (metaNames.has(key)) continue;
|
|
7056
|
+
const map = materializeMap(yDoc, key);
|
|
7057
|
+
if (!map || map.size === 0) continue;
|
|
7058
|
+
const inferred = inferModelFromData(map);
|
|
7059
|
+
if (inferred) models[key] = inferred;
|
|
7060
|
+
}
|
|
7061
|
+
return { models };
|
|
7062
|
+
}
|
|
7063
|
+
function discoverModelNames(yDoc) {
|
|
7064
|
+
const names = [];
|
|
7065
|
+
for (const key of yDoc.share.keys()) {
|
|
7066
|
+
if (key.startsWith("_")) continue;
|
|
7067
|
+
const map = materializeMap(yDoc, key);
|
|
7068
|
+
if (map) names.push(key);
|
|
7069
|
+
}
|
|
7070
|
+
return names.sort();
|
|
7071
|
+
}
|
|
7072
|
+
function materializeMap(yDoc, key) {
|
|
7073
|
+
try {
|
|
7074
|
+
const map = yDoc.getMap(key);
|
|
7075
|
+
return map instanceof Y3.Map ? map : null;
|
|
7076
|
+
} catch {
|
|
7077
|
+
return null;
|
|
7078
|
+
}
|
|
7079
|
+
}
|
|
7080
|
+
function readModelMeta(metaMap) {
|
|
7081
|
+
const fields = {};
|
|
7082
|
+
let constraints;
|
|
7083
|
+
let relationships;
|
|
7084
|
+
for (const [key, value] of metaMap.entries()) {
|
|
7085
|
+
if (key === "_constraints" && value instanceof Y3.Map) {
|
|
7086
|
+
constraints = readConstraints(value);
|
|
7087
|
+
} else if (key === "_relationships" && value instanceof Y3.Map) {
|
|
7088
|
+
relationships = readRelationships(value);
|
|
7089
|
+
} else if (value instanceof Y3.Map) {
|
|
7090
|
+
fields[key] = readFieldMeta(value);
|
|
7091
|
+
}
|
|
7092
|
+
}
|
|
7093
|
+
const model = { fields };
|
|
7094
|
+
if (constraints && Object.keys(constraints).length > 0) {
|
|
7095
|
+
model.constraints = constraints;
|
|
7096
|
+
}
|
|
7097
|
+
if (relationships && Object.keys(relationships).length > 0) {
|
|
7098
|
+
model.relationships = relationships;
|
|
7099
|
+
}
|
|
7100
|
+
return model;
|
|
7101
|
+
}
|
|
7102
|
+
function readFieldMeta(fieldMap) {
|
|
7103
|
+
const field = { type: fieldMap.get("type") ?? "unknown" };
|
|
7104
|
+
if (fieldMap.get("indexed") === true) field.indexed = true;
|
|
7105
|
+
if (fieldMap.get("unique") === true) field.unique = true;
|
|
7106
|
+
if (fieldMap.get("required") === true) field.required = true;
|
|
7107
|
+
if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
|
|
7108
|
+
const def = fieldMap.get("default");
|
|
7109
|
+
if (def !== void 0) field.default = def;
|
|
7110
|
+
const maxLength = fieldMap.get("maxLength");
|
|
7111
|
+
if (maxLength !== void 0) field.maxLength = maxLength;
|
|
7112
|
+
const maxCount = fieldMap.get("maxCount");
|
|
7113
|
+
if (maxCount !== void 0) field.maxCount = maxCount;
|
|
7114
|
+
return field;
|
|
7115
|
+
}
|
|
7116
|
+
function inferModelFromData(dataMap) {
|
|
7117
|
+
const fields = {};
|
|
7118
|
+
let sampled = 0;
|
|
7119
|
+
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
7120
|
+
if (!(recordValue instanceof Y3.Map)) continue;
|
|
7121
|
+
if (++sampled > 5) break;
|
|
7122
|
+
for (const [fieldName, value] of recordValue.entries()) {
|
|
7123
|
+
if (fieldName.startsWith("_")) continue;
|
|
7124
|
+
if (fields[fieldName]) continue;
|
|
7125
|
+
const type = inferTypeFromValue(value);
|
|
7126
|
+
if (type) fields[fieldName] = { type };
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7129
|
+
if (Object.keys(fields).length === 0) return null;
|
|
7130
|
+
return { fields };
|
|
7131
|
+
}
|
|
7132
|
+
function inferTypeFromValue(value) {
|
|
7133
|
+
if (value instanceof Y3.Map) return "stringset";
|
|
7134
|
+
switch (typeof value) {
|
|
7135
|
+
case "string":
|
|
7136
|
+
return "string";
|
|
7137
|
+
case "number":
|
|
7138
|
+
return "number";
|
|
7139
|
+
case "boolean":
|
|
7140
|
+
return "boolean";
|
|
7141
|
+
default:
|
|
7142
|
+
return null;
|
|
7143
|
+
}
|
|
7144
|
+
}
|
|
7145
|
+
function readConstraints(constraintsMap) {
|
|
7146
|
+
const out = {};
|
|
7147
|
+
for (const [name, value] of constraintsMap.entries()) {
|
|
7148
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
7149
|
+
let fields = [];
|
|
7150
|
+
const rawFields = value.get("fields");
|
|
7151
|
+
if (typeof rawFields === "string") {
|
|
7152
|
+
try {
|
|
7153
|
+
fields = JSON.parse(rawFields);
|
|
7154
|
+
} catch {
|
|
7155
|
+
}
|
|
7156
|
+
}
|
|
7157
|
+
out[name] = {
|
|
7158
|
+
type: value.get("type") ?? "unknown",
|
|
7159
|
+
fields
|
|
7160
|
+
};
|
|
7161
|
+
}
|
|
7162
|
+
return out;
|
|
7163
|
+
}
|
|
7164
|
+
function readRelationships(relsMap) {
|
|
7165
|
+
const out = {};
|
|
7166
|
+
for (const [name, value] of relsMap.entries()) {
|
|
7167
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
7168
|
+
const rel = {};
|
|
7169
|
+
for (const [k, v] of value.entries()) {
|
|
7170
|
+
rel[k] = v;
|
|
7171
|
+
}
|
|
7172
|
+
out[name] = rel;
|
|
7173
|
+
}
|
|
7174
|
+
return out;
|
|
7175
|
+
}
|
|
7176
|
+
var CAMEL_TO_SNAKE = {
|
|
7177
|
+
autoAssign: "auto_assign",
|
|
7178
|
+
maxLength: "max_length",
|
|
7179
|
+
maxCount: "max_count",
|
|
7180
|
+
relatedIdField: "related_id_field",
|
|
7181
|
+
joinModel: "join_model",
|
|
7182
|
+
joinModelLocalField: "join_model_local_field",
|
|
7183
|
+
joinModelRelatedField: "join_model_related_field",
|
|
7184
|
+
joinModelOrderByField: "join_model_order_by_field",
|
|
7185
|
+
joinModelOrderDirection: "join_model_order_direction",
|
|
7186
|
+
orderByField: "order_by_field",
|
|
7187
|
+
orderDirection: "order_direction"
|
|
7188
|
+
};
|
|
7189
|
+
function toSnake(key) {
|
|
7190
|
+
return CAMEL_TO_SNAKE[key] ?? key;
|
|
7191
|
+
}
|
|
7192
|
+
function tomlValue(v) {
|
|
7193
|
+
if (typeof v === "string") {
|
|
7194
|
+
return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
|
|
7195
|
+
}
|
|
7196
|
+
return String(v);
|
|
7197
|
+
}
|
|
7198
|
+
function schemaToToml(schema) {
|
|
7199
|
+
const lines = [];
|
|
7200
|
+
for (const [modelName, model] of Object.entries(schema.models)) {
|
|
7201
|
+
if (lines.length > 0) lines.push("", "");
|
|
7202
|
+
lines.push(`[models.${modelName}]`);
|
|
7203
|
+
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
7204
|
+
lines.push("");
|
|
7205
|
+
lines.push(`[models.${modelName}.fields.${fieldName}]`);
|
|
7206
|
+
lines.push(`type = ${tomlValue(field.type)}`);
|
|
7207
|
+
if (field.autoAssign) lines.push("auto_assign = true");
|
|
7208
|
+
if (field.indexed) lines.push("indexed = true");
|
|
7209
|
+
if (field.unique) lines.push("unique = true");
|
|
7210
|
+
if (field.required) lines.push("required = true");
|
|
7211
|
+
if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
|
|
7212
|
+
if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
|
|
7213
|
+
if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
|
|
7214
|
+
}
|
|
7215
|
+
if (model.relationships) {
|
|
7216
|
+
for (const [relName, rel] of Object.entries(model.relationships)) {
|
|
7217
|
+
lines.push("");
|
|
7218
|
+
lines.push(`[models.${modelName}.relationships.${relName}]`);
|
|
7219
|
+
for (const [k, v] of Object.entries(rel)) {
|
|
7220
|
+
if (v === void 0) continue;
|
|
7221
|
+
lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
7225
|
+
if (model.constraints) {
|
|
7226
|
+
for (const [cName, c] of Object.entries(model.constraints)) {
|
|
7227
|
+
lines.push("");
|
|
7228
|
+
lines.push(`[[models.${modelName}.unique_constraints]]`);
|
|
7229
|
+
lines.push(`name = ${tomlValue(cName)}`);
|
|
7230
|
+
lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
|
|
7231
|
+
}
|
|
7232
|
+
}
|
|
7233
|
+
}
|
|
7234
|
+
lines.push("");
|
|
7235
|
+
return lines.join("\n");
|
|
7236
|
+
}
|
|
7237
|
+
|
|
7238
|
+
// src/models/tomlLoader.ts
|
|
7239
|
+
import { parse as parseToml } from "smol-toml";
|
|
7240
|
+
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
7241
|
+
"string",
|
|
7242
|
+
"number",
|
|
7243
|
+
"boolean",
|
|
7244
|
+
"date",
|
|
7245
|
+
"id",
|
|
7246
|
+
"stringset"
|
|
7247
|
+
]);
|
|
7248
|
+
function parseFieldOptions(raw) {
|
|
7249
|
+
if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
|
|
7250
|
+
throw new Error(
|
|
7251
|
+
`Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
|
|
7252
|
+
);
|
|
7253
|
+
}
|
|
7254
|
+
const opts = { type: raw.type };
|
|
7255
|
+
if (raw.indexed === true) opts.indexed = true;
|
|
7256
|
+
if (raw.unique === true) opts.unique = true;
|
|
7257
|
+
if (raw.required === true) opts.required = true;
|
|
7258
|
+
if (raw.auto_assign === true) opts.autoAssign = true;
|
|
7259
|
+
if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
|
|
7260
|
+
if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
|
|
7261
|
+
if (raw.default !== void 0) opts.default = raw.default;
|
|
7262
|
+
return opts;
|
|
7263
|
+
}
|
|
7264
|
+
function requireField(raw, field, context) {
|
|
7265
|
+
if (!raw[field]) {
|
|
7266
|
+
throw new Error(`Relationship ${context}: missing required field "${field}"`);
|
|
7267
|
+
}
|
|
7268
|
+
}
|
|
7269
|
+
function parseRelationship(raw) {
|
|
7270
|
+
const type = raw.type;
|
|
7271
|
+
if (type === "refersTo") {
|
|
7272
|
+
requireField(raw, "model", "refersTo");
|
|
7273
|
+
requireField(raw, "related_id_field", "refersTo");
|
|
7274
|
+
return {
|
|
7275
|
+
type: "refersTo",
|
|
7276
|
+
model: raw.model,
|
|
7277
|
+
relatedIdField: raw.related_id_field
|
|
7278
|
+
};
|
|
7279
|
+
}
|
|
7280
|
+
if (type === "hasMany") {
|
|
7281
|
+
requireField(raw, "model", "hasMany");
|
|
7282
|
+
requireField(raw, "related_id_field", "hasMany");
|
|
7283
|
+
const rel = {
|
|
7284
|
+
type: "hasMany",
|
|
7285
|
+
model: raw.model,
|
|
7286
|
+
relatedIdField: raw.related_id_field
|
|
7287
|
+
};
|
|
7288
|
+
if (raw.order_by_field) rel.orderByField = raw.order_by_field;
|
|
7289
|
+
if (raw.order_direction) rel.orderDirection = raw.order_direction;
|
|
7290
|
+
return rel;
|
|
7291
|
+
}
|
|
7292
|
+
if (type === "hasManyThrough") {
|
|
7293
|
+
requireField(raw, "model", "hasManyThrough");
|
|
7294
|
+
requireField(raw, "join_model", "hasManyThrough");
|
|
7295
|
+
requireField(raw, "join_model_local_field", "hasManyThrough");
|
|
7296
|
+
requireField(raw, "join_model_related_field", "hasManyThrough");
|
|
7297
|
+
const rel = {
|
|
7298
|
+
type: "hasManyThrough",
|
|
7299
|
+
model: raw.model,
|
|
7300
|
+
joinModel: raw.join_model,
|
|
7301
|
+
joinModelLocalField: raw.join_model_local_field,
|
|
7302
|
+
joinModelRelatedField: raw.join_model_related_field
|
|
7303
|
+
};
|
|
7304
|
+
if (raw.join_model_order_by_field)
|
|
7305
|
+
rel.joinModelOrderByField = raw.join_model_order_by_field;
|
|
7306
|
+
if (raw.join_model_order_direction)
|
|
7307
|
+
rel.joinModelOrderDirection = raw.join_model_order_direction;
|
|
7308
|
+
return rel;
|
|
7309
|
+
}
|
|
7310
|
+
throw new Error(`Unknown relationship type: ${type}`);
|
|
7311
|
+
}
|
|
7312
|
+
function loadSchemaFromTomlString(tomlString) {
|
|
7313
|
+
const parsed = parseToml(tomlString);
|
|
7314
|
+
const models = parsed.models;
|
|
7315
|
+
if (!models || typeof models !== "object") {
|
|
7316
|
+
throw new Error("TOML schema must have a [models] section");
|
|
7317
|
+
}
|
|
7318
|
+
const schemas = [];
|
|
7319
|
+
for (const [modelName, modelDef] of Object.entries(models)) {
|
|
7320
|
+
const fields = {};
|
|
7321
|
+
if (modelDef.fields) {
|
|
7322
|
+
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
7323
|
+
fields[fieldName] = parseFieldOptions(fieldDef);
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
let relationships;
|
|
7327
|
+
if (modelDef.relationships) {
|
|
7328
|
+
relationships = {};
|
|
7329
|
+
for (const [relName, relDef] of Object.entries(
|
|
7330
|
+
modelDef.relationships
|
|
7331
|
+
)) {
|
|
7332
|
+
relationships[relName] = parseRelationship(relDef);
|
|
7333
|
+
}
|
|
7334
|
+
}
|
|
7335
|
+
let uniqueConstraints;
|
|
7336
|
+
if (modelDef.unique_constraints) {
|
|
7337
|
+
uniqueConstraints = [];
|
|
7338
|
+
for (const raw of modelDef.unique_constraints) {
|
|
7339
|
+
uniqueConstraints.push({
|
|
7340
|
+
name: raw.name,
|
|
7341
|
+
fields: [...raw.fields]
|
|
7342
|
+
});
|
|
7343
|
+
}
|
|
7344
|
+
}
|
|
7345
|
+
schemas.push(
|
|
7346
|
+
defineModelSchema({
|
|
7347
|
+
name: modelName,
|
|
7348
|
+
fields,
|
|
7349
|
+
options: {
|
|
7350
|
+
uniqueConstraints,
|
|
7351
|
+
relationships
|
|
7352
|
+
}
|
|
7353
|
+
})
|
|
7354
|
+
);
|
|
7355
|
+
}
|
|
7356
|
+
return schemas;
|
|
7357
|
+
}
|
|
7358
|
+
async function loadSchemaFromToml(filePath) {
|
|
7359
|
+
const { readFile } = await import("fs/promises");
|
|
7360
|
+
const content = await readFile(filePath, "utf-8");
|
|
7361
|
+
return loadSchemaFromTomlString(content);
|
|
7362
|
+
}
|
|
7363
|
+
|
|
7364
|
+
// src/node.ts
|
|
7365
|
+
init_metaSync();
|
|
7366
|
+
|
|
7367
|
+
// src/utils/yDocDump.ts
|
|
7368
|
+
import * as Y4 from "yjs";
|
|
7132
7369
|
function toPlain(value) {
|
|
7133
|
-
if (value instanceof
|
|
7370
|
+
if (value instanceof Y4.Map) {
|
|
7134
7371
|
const obj = {};
|
|
7135
7372
|
value.forEach((v, k) => {
|
|
7136
7373
|
obj[k] = toPlain(v);
|
|
7137
7374
|
});
|
|
7138
7375
|
return obj;
|
|
7139
7376
|
}
|
|
7140
|
-
if (value instanceof
|
|
7377
|
+
if (value instanceof Y4.Array) {
|
|
7141
7378
|
return value.toArray().map((item) => toPlain(item));
|
|
7142
7379
|
}
|
|
7143
7380
|
return value;
|
|
@@ -7146,7 +7383,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
|
|
|
7146
7383
|
const result = {};
|
|
7147
7384
|
const includeIndexes = !!options.includeIndexes;
|
|
7148
7385
|
yDoc.share.forEach((type, name) => {
|
|
7149
|
-
if (!(type instanceof
|
|
7386
|
+
if (!(type instanceof Y4.Map)) return;
|
|
7150
7387
|
if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
|
|
7151
7388
|
const records = {};
|
|
7152
7389
|
type.forEach((recordValue, recordId) => {
|
|
@@ -7199,10 +7436,8 @@ export {
|
|
|
7199
7436
|
BaseModel2 as BaseModel,
|
|
7200
7437
|
DatabaseEngine,
|
|
7201
7438
|
NodeDatabaseFactory as DatabaseFactory,
|
|
7202
|
-
Field,
|
|
7203
7439
|
LogLevel,
|
|
7204
7440
|
Logger,
|
|
7205
|
-
Model,
|
|
7206
7441
|
ModelRegistry,
|
|
7207
7442
|
RecordNotFoundError,
|
|
7208
7443
|
SqljsEngine,
|
|
@@ -7211,18 +7446,28 @@ export {
|
|
|
7211
7446
|
attachAndRegisterModel,
|
|
7212
7447
|
attachSchemaToClass,
|
|
7213
7448
|
autoRegisterModel,
|
|
7449
|
+
clearMetaSyncCache,
|
|
7214
7450
|
constants,
|
|
7215
7451
|
createModelClass,
|
|
7216
7452
|
defineModelSchema,
|
|
7217
7453
|
detectEnvironment,
|
|
7454
|
+
discoverModelNames,
|
|
7455
|
+
discoverSchema,
|
|
7218
7456
|
dumpYDocToPlain,
|
|
7219
7457
|
features,
|
|
7220
7458
|
generateULID,
|
|
7221
7459
|
getRecommendedNodeEngine,
|
|
7460
|
+
inferFieldType,
|
|
7222
7461
|
initJsBao,
|
|
7223
7462
|
isBrowser,
|
|
7224
7463
|
isNode,
|
|
7225
7464
|
isNodeModuleAvailable,
|
|
7465
|
+
loadSchemaFromToml,
|
|
7466
|
+
loadSchemaFromTomlString,
|
|
7467
|
+
registerFunctionDefault,
|
|
7226
7468
|
resetJsBao,
|
|
7227
|
-
|
|
7469
|
+
schemaToToml,
|
|
7470
|
+
summarizePlainYDoc,
|
|
7471
|
+
syncInferredMeta,
|
|
7472
|
+
syncModelMeta
|
|
7228
7473
|
};
|