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.cjs
CHANGED
|
@@ -1184,6 +1184,19 @@ var init_DocumentQueryTranslator = __esm({
|
|
|
1184
1184
|
});
|
|
1185
1185
|
|
|
1186
1186
|
// src/models/metaSync.ts
|
|
1187
|
+
function inferFieldType(value) {
|
|
1188
|
+
if (value instanceof Y.Map) return "stringset";
|
|
1189
|
+
switch (typeof value) {
|
|
1190
|
+
case "string":
|
|
1191
|
+
return "string";
|
|
1192
|
+
case "number":
|
|
1193
|
+
return "number";
|
|
1194
|
+
case "boolean":
|
|
1195
|
+
return "boolean";
|
|
1196
|
+
default:
|
|
1197
|
+
return null;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1187
1200
|
function registerFunctionDefault(fn, name) {
|
|
1188
1201
|
KNOWN_FUNCTION_DEFAULTS.set(fn, name);
|
|
1189
1202
|
}
|
|
@@ -1195,6 +1208,11 @@ function encodeDefault(value) {
|
|
|
1195
1208
|
}
|
|
1196
1209
|
return value;
|
|
1197
1210
|
}
|
|
1211
|
+
function clearMetaSyncCache(yDoc) {
|
|
1212
|
+
if (yDoc) {
|
|
1213
|
+
_syncedCache.delete(yDoc);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1198
1216
|
function syncModelMeta(yDoc, modelName, schema) {
|
|
1199
1217
|
let synced = _syncedCache.get(yDoc);
|
|
1200
1218
|
if (synced?.has(modelName)) return;
|
|
@@ -1270,6 +1288,23 @@ function syncRelationshipMeta(relsMap, relName, relConfig) {
|
|
|
1270
1288
|
}
|
|
1271
1289
|
}
|
|
1272
1290
|
}
|
|
1291
|
+
function syncInferredMeta(yDoc, modelName, recordData) {
|
|
1292
|
+
const meta = yDoc.getMap(`_meta_${modelName}`);
|
|
1293
|
+
for (const [fieldName, value] of Object.entries(recordData)) {
|
|
1294
|
+
if (fieldName.startsWith("_")) continue;
|
|
1295
|
+
let fieldMeta = meta.get(fieldName);
|
|
1296
|
+
if (!fieldMeta) {
|
|
1297
|
+
fieldMeta = new Y.Map();
|
|
1298
|
+
meta.set(fieldName, fieldMeta);
|
|
1299
|
+
}
|
|
1300
|
+
if (!fieldMeta.has("type")) {
|
|
1301
|
+
const inferredType = inferFieldType(value);
|
|
1302
|
+
if (inferredType) {
|
|
1303
|
+
fieldMeta.set("type", inferredType);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1273
1308
|
function setIfChanged(map, key, value) {
|
|
1274
1309
|
if (map.get(key) !== value) {
|
|
1275
1310
|
map.set(key, value);
|
|
@@ -1599,11 +1634,11 @@ var init_ModelRegistry = __esm({
|
|
|
1599
1634
|
init_relationshipManager();
|
|
1600
1635
|
ModelRegistry = class _ModelRegistry {
|
|
1601
1636
|
static instance;
|
|
1602
|
-
// Stores globally registered model classes by their name
|
|
1637
|
+
// Stores globally registered model classes by their name
|
|
1603
1638
|
models = /* @__PURE__ */ new Map();
|
|
1604
|
-
// Stores options for globally registered models
|
|
1639
|
+
// Stores options for globally registered models
|
|
1605
1640
|
modelOptions = /* @__PURE__ */ new Map();
|
|
1606
|
-
// Stores fields for globally registered models (
|
|
1641
|
+
// Stores fields for globally registered models (or a static getter on class)
|
|
1607
1642
|
// For simplicity, let's assume fields can be derived or are less critical for this registry part
|
|
1608
1643
|
// private modelFields: Map<string, Map<string, FieldOptions>> = new Map();
|
|
1609
1644
|
// Holds the subset of models explicitly set for the current initialization session
|
|
@@ -1621,7 +1656,7 @@ var init_ModelRegistry = __esm({
|
|
|
1621
1656
|
registerModel(modelClass, options, fields) {
|
|
1622
1657
|
if (!options.name) {
|
|
1623
1658
|
throw new Error(
|
|
1624
|
-
`[ModelRegistry] Model class is missing a name in its
|
|
1659
|
+
`[ModelRegistry] Model class is missing a name in its options. Ensure the schema passed to defineModelSchema/createModelClass/attachAndRegisterModel includes a 'name' property.`
|
|
1625
1660
|
);
|
|
1626
1661
|
}
|
|
1627
1662
|
if (this.models.has(options.name)) {
|
|
@@ -1665,7 +1700,7 @@ var init_ModelRegistry = __esm({
|
|
|
1665
1700
|
}
|
|
1666
1701
|
return infos;
|
|
1667
1702
|
}
|
|
1668
|
-
// Helper to get model name from class (
|
|
1703
|
+
// Helper to get model name from class (set by attachAndRegisterModel/createModelClass)
|
|
1669
1704
|
getModelNameFromClass(modelClass) {
|
|
1670
1705
|
return modelClass.modelName;
|
|
1671
1706
|
}
|
|
@@ -1676,13 +1711,13 @@ var init_ModelRegistry = __esm({
|
|
|
1676
1711
|
const modelName = this.getModelNameFromClass(modelClass);
|
|
1677
1712
|
if (!modelName) {
|
|
1678
1713
|
console.warn(
|
|
1679
|
-
`[ModelRegistry] A model class provided to setExplicitModelsForSession does not have a static 'modelName' property or it's undefined. It will be ignored. Ensure
|
|
1714
|
+
`[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.`
|
|
1680
1715
|
);
|
|
1681
1716
|
return;
|
|
1682
1717
|
}
|
|
1683
1718
|
if (!this.models.has(modelName) || this.models.get(modelName) !== modelClass) {
|
|
1684
1719
|
console.warn(
|
|
1685
|
-
`[ModelRegistry] Model class with name ${modelName} provided to setExplicitModelsForSession was not found in the global
|
|
1720
|
+
`[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.`
|
|
1686
1721
|
);
|
|
1687
1722
|
return;
|
|
1688
1723
|
}
|
|
@@ -1712,7 +1747,7 @@ var init_ModelRegistry = __esm({
|
|
|
1712
1747
|
} else {
|
|
1713
1748
|
this.activeSessionModels = null;
|
|
1714
1749
|
console.log(
|
|
1715
|
-
"[ModelRegistry] No explicit models specified for session (undefined), will use all
|
|
1750
|
+
"[ModelRegistry] No explicit models specified for session (undefined), will use all globally registered models."
|
|
1716
1751
|
);
|
|
1717
1752
|
}
|
|
1718
1753
|
this.validateSessionModels();
|
|
@@ -1723,7 +1758,7 @@ var init_ModelRegistry = __esm({
|
|
|
1723
1758
|
const modelsToInitialize = this.activeSessionModels || this.models;
|
|
1724
1759
|
if (modelsToInitialize.size === 0) {
|
|
1725
1760
|
console.warn(
|
|
1726
|
-
"[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via
|
|
1761
|
+
"[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1727
1762
|
);
|
|
1728
1763
|
return;
|
|
1729
1764
|
}
|
|
@@ -1754,7 +1789,7 @@ var init_ModelRegistry = __esm({
|
|
|
1754
1789
|
const modelsToInitialize = this.activeSessionModels || this.models;
|
|
1755
1790
|
if (modelsToInitialize.size === 0) {
|
|
1756
1791
|
Logger.warn(
|
|
1757
|
-
"[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via
|
|
1792
|
+
"[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1758
1793
|
);
|
|
1759
1794
|
return;
|
|
1760
1795
|
}
|
|
@@ -1792,7 +1827,7 @@ var init_ModelRegistry = __esm({
|
|
|
1792
1827
|
const modelsToCleanup = this.activeSessionModels || this.models;
|
|
1793
1828
|
if (modelsToCleanup.size === 0) {
|
|
1794
1829
|
console.warn(
|
|
1795
|
-
"[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via
|
|
1830
|
+
"[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
|
|
1796
1831
|
);
|
|
1797
1832
|
return;
|
|
1798
1833
|
}
|
|
@@ -2556,7 +2591,7 @@ var init_BaseModel = __esm({
|
|
|
2556
2591
|
getDocumentId() {
|
|
2557
2592
|
return this._metaDocId;
|
|
2558
2593
|
}
|
|
2559
|
-
// id is
|
|
2594
|
+
// id is a plain property. Subclasses define it via defineModelSchema.
|
|
2560
2595
|
id;
|
|
2561
2596
|
type;
|
|
2562
2597
|
// This should be the modelName from ModelOptions
|
|
@@ -3103,7 +3138,7 @@ var init_BaseModel = __esm({
|
|
|
3103
3138
|
const verboseEnabled = Logger.getLogLevel() >= 5 /* VERBOSE */;
|
|
3104
3139
|
if (!schema || !schema.options || !schema.options.name || !schema.resolvedUniqueConstraints) {
|
|
3105
3140
|
throw new Error(
|
|
3106
|
-
`[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to
|
|
3141
|
+
`[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to call attachAndRegisterModel (or autoRegisterModel) for this model?`
|
|
3107
3142
|
);
|
|
3108
3143
|
}
|
|
3109
3144
|
const modelName = schema.options.name;
|
|
@@ -5498,11 +5533,11 @@ var init_BaseModel = __esm({
|
|
|
5498
5533
|
});
|
|
5499
5534
|
|
|
5500
5535
|
// src/engines/SqljsEngine.ts
|
|
5501
|
-
var
|
|
5536
|
+
var import_sql4, import_async_mutex, SQL_WASM_URL, TransactionalSQLJSOperations, SqljsEngine;
|
|
5502
5537
|
var init_SqljsEngine = __esm({
|
|
5503
5538
|
"src/engines/SqljsEngine.ts"() {
|
|
5504
5539
|
"use strict";
|
|
5505
|
-
|
|
5540
|
+
import_sql4 = __toESM(require("sql.js"), 1);
|
|
5506
5541
|
init_BaseModel();
|
|
5507
5542
|
import_async_mutex = require("async-mutex");
|
|
5508
5543
|
init_sql();
|
|
@@ -5579,7 +5614,7 @@ var init_SqljsEngine = __esm({
|
|
|
5579
5614
|
"[SqljsEngine] Attempting to load SQL.js WASM from:",
|
|
5580
5615
|
locateFileConfig("sql-wasm.wasm")
|
|
5581
5616
|
);
|
|
5582
|
-
_SqljsEngine.SQL = await (0,
|
|
5617
|
+
_SqljsEngine.SQL = await (0, import_sql4.default)({
|
|
5583
5618
|
locateFile: locateFileConfig
|
|
5584
5619
|
});
|
|
5585
5620
|
Logger.info("[SqljsEngine] SQL.js WASM loaded successfully.");
|
|
@@ -6626,10 +6661,8 @@ __export(node_exports, {
|
|
|
6626
6661
|
BaseModel: () => BaseModel2,
|
|
6627
6662
|
DatabaseEngine: () => DatabaseEngine,
|
|
6628
6663
|
DatabaseFactory: () => NodeDatabaseFactory,
|
|
6629
|
-
Field: () => Field,
|
|
6630
6664
|
LogLevel: () => LogLevel,
|
|
6631
6665
|
Logger: () => Logger,
|
|
6632
|
-
Model: () => Model,
|
|
6633
6666
|
ModelRegistry: () => ModelRegistry,
|
|
6634
6667
|
RecordNotFoundError: () => RecordNotFoundError,
|
|
6635
6668
|
SqljsEngine: () => SqljsEngine,
|
|
@@ -6638,150 +6671,35 @@ __export(node_exports, {
|
|
|
6638
6671
|
attachAndRegisterModel: () => attachAndRegisterModel,
|
|
6639
6672
|
attachSchemaToClass: () => attachSchemaToClass,
|
|
6640
6673
|
autoRegisterModel: () => autoRegisterModel,
|
|
6674
|
+
clearMetaSyncCache: () => clearMetaSyncCache,
|
|
6641
6675
|
constants: () => constants,
|
|
6642
6676
|
createModelClass: () => createModelClass,
|
|
6643
6677
|
defineModelSchema: () => defineModelSchema,
|
|
6644
6678
|
detectEnvironment: () => detectEnvironment,
|
|
6679
|
+
discoverModelNames: () => discoverModelNames,
|
|
6680
|
+
discoverSchema: () => discoverSchema,
|
|
6645
6681
|
dumpYDocToPlain: () => dumpYDocToPlain,
|
|
6646
6682
|
features: () => features,
|
|
6647
6683
|
generateULID: () => generateULID,
|
|
6648
6684
|
getRecommendedNodeEngine: () => getRecommendedNodeEngine,
|
|
6685
|
+
inferFieldType: () => inferFieldType,
|
|
6649
6686
|
initJsBao: () => initJsBao,
|
|
6650
6687
|
isBrowser: () => isBrowser,
|
|
6651
6688
|
isNode: () => isNode,
|
|
6652
6689
|
isNodeModuleAvailable: () => isNodeModuleAvailable,
|
|
6690
|
+
loadSchemaFromToml: () => loadSchemaFromToml,
|
|
6691
|
+
loadSchemaFromTomlString: () => loadSchemaFromTomlString,
|
|
6692
|
+
registerFunctionDefault: () => registerFunctionDefault,
|
|
6653
6693
|
resetJsBao: () => resetJsBao,
|
|
6654
|
-
|
|
6694
|
+
schemaToToml: () => schemaToToml,
|
|
6695
|
+
summarizePlainYDoc: () => summarizePlainYDoc,
|
|
6696
|
+
syncInferredMeta: () => syncInferredMeta,
|
|
6697
|
+
syncModelMeta: () => syncModelMeta
|
|
6655
6698
|
});
|
|
6656
6699
|
module.exports = __toCommonJS(node_exports);
|
|
6657
6700
|
init_BaseModel();
|
|
6658
6701
|
init_ModelRegistry();
|
|
6659
6702
|
|
|
6660
|
-
// src/models/decorators.ts
|
|
6661
|
-
init_ModelRegistry();
|
|
6662
|
-
init_BaseModel();
|
|
6663
|
-
init_sql();
|
|
6664
|
-
var SCHEMA_FIELDS_PROPERTY = "_jsbaoSchemaFields";
|
|
6665
|
-
function Field(options) {
|
|
6666
|
-
return function(target, propertyKey) {
|
|
6667
|
-
const fieldName = String(propertyKey);
|
|
6668
|
-
const modelConstructor = target.constructor || target;
|
|
6669
|
-
assertValidIdentifier(
|
|
6670
|
-
fieldName,
|
|
6671
|
-
`[Field Decorator] Invalid field name on ${modelConstructor?.name || "unknown"}`
|
|
6672
|
-
);
|
|
6673
|
-
if (!modelConstructor) {
|
|
6674
|
-
console.error(
|
|
6675
|
-
"[Field Decorator] Could not determine model constructor for field:",
|
|
6676
|
-
fieldName,
|
|
6677
|
-
"Target:",
|
|
6678
|
-
target
|
|
6679
|
-
);
|
|
6680
|
-
throw new Error(
|
|
6681
|
-
`Failed to resolve model constructor for field '${fieldName}'.`
|
|
6682
|
-
);
|
|
6683
|
-
}
|
|
6684
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
6685
|
-
modelConstructor,
|
|
6686
|
-
SCHEMA_FIELDS_PROPERTY
|
|
6687
|
-
)) {
|
|
6688
|
-
modelConstructor[SCHEMA_FIELDS_PROPERTY] = /* @__PURE__ */ new Map();
|
|
6689
|
-
}
|
|
6690
|
-
modelConstructor[SCHEMA_FIELDS_PROPERTY].set(
|
|
6691
|
-
fieldName,
|
|
6692
|
-
options
|
|
6693
|
-
);
|
|
6694
|
-
Logger.debug(
|
|
6695
|
-
`[Field Decorator] Staged field "${fieldName}" for class ${modelConstructor.name}:`,
|
|
6696
|
-
options
|
|
6697
|
-
);
|
|
6698
|
-
};
|
|
6699
|
-
}
|
|
6700
|
-
function Model(options) {
|
|
6701
|
-
return function(targetClass) {
|
|
6702
|
-
Logger.debug(
|
|
6703
|
-
`[Model Decorator] Registering model:`,
|
|
6704
|
-
targetClass.name,
|
|
6705
|
-
options
|
|
6706
|
-
);
|
|
6707
|
-
assertValidIdentifier(
|
|
6708
|
-
options.name,
|
|
6709
|
-
`[Model Decorator] Invalid model name for ${targetClass.name}`
|
|
6710
|
-
);
|
|
6711
|
-
const registry = ModelRegistry.getInstance();
|
|
6712
|
-
targetClass.modelName = options.name;
|
|
6713
|
-
targetClass.getSchema = () => {
|
|
6714
|
-
const combinedFields = /* @__PURE__ */ new Map();
|
|
6715
|
-
const hierarchyStack = [];
|
|
6716
|
-
let currentEvalClass = targetClass;
|
|
6717
|
-
while (currentEvalClass && currentEvalClass.prototype) {
|
|
6718
|
-
hierarchyStack.push(currentEvalClass);
|
|
6719
|
-
const parentPrototype = Object.getPrototypeOf(
|
|
6720
|
-
currentEvalClass.prototype
|
|
6721
|
-
);
|
|
6722
|
-
currentEvalClass = parentPrototype ? parentPrototype.constructor : null;
|
|
6723
|
-
if (currentEvalClass === Object) break;
|
|
6724
|
-
}
|
|
6725
|
-
for (let i = hierarchyStack.length - 1; i >= 0; i--) {
|
|
6726
|
-
const cls = hierarchyStack[i];
|
|
6727
|
-
if (Object.prototype.hasOwnProperty.call(cls, SCHEMA_FIELDS_PROPERTY)) {
|
|
6728
|
-
const fieldsForClass = cls[SCHEMA_FIELDS_PROPERTY];
|
|
6729
|
-
fieldsForClass.forEach((fieldOpts, fieldName) => {
|
|
6730
|
-
combinedFields.set(fieldName, fieldOpts);
|
|
6731
|
-
});
|
|
6732
|
-
}
|
|
6733
|
-
}
|
|
6734
|
-
const resolvedUniqueConstraints = [];
|
|
6735
|
-
combinedFields.forEach((fieldOpts, fieldName) => {
|
|
6736
|
-
if (fieldOpts.unique) {
|
|
6737
|
-
const constraintName = `${options.name}_${fieldName}_unique`;
|
|
6738
|
-
resolvedUniqueConstraints.push({
|
|
6739
|
-
name: constraintName,
|
|
6740
|
-
fields: [fieldName]
|
|
6741
|
-
});
|
|
6742
|
-
}
|
|
6743
|
-
});
|
|
6744
|
-
if (options.uniqueConstraints) {
|
|
6745
|
-
options.uniqueConstraints.forEach(
|
|
6746
|
-
(constraintConfig) => {
|
|
6747
|
-
const allFieldsExist = constraintConfig.fields.every(
|
|
6748
|
-
(f) => combinedFields.has(f)
|
|
6749
|
-
);
|
|
6750
|
-
if (!allFieldsExist) {
|
|
6751
|
-
console.warn(
|
|
6752
|
-
`[Model Decorator] Unique constraint "${constraintConfig.name}" for model "${options.name}" specifies non-existent fields. Skipping.`
|
|
6753
|
-
);
|
|
6754
|
-
return;
|
|
6755
|
-
}
|
|
6756
|
-
if (resolvedUniqueConstraints.some(
|
|
6757
|
-
(rc) => rc.name === constraintConfig.name
|
|
6758
|
-
)) {
|
|
6759
|
-
console.warn(
|
|
6760
|
-
`[Model Decorator] Duplicate unique constraint name "${constraintConfig.name}" in model "${options.name}".`
|
|
6761
|
-
);
|
|
6762
|
-
}
|
|
6763
|
-
resolvedUniqueConstraints.push({
|
|
6764
|
-
name: constraintConfig.name,
|
|
6765
|
-
fields: constraintConfig.fields
|
|
6766
|
-
});
|
|
6767
|
-
}
|
|
6768
|
-
);
|
|
6769
|
-
}
|
|
6770
|
-
return {
|
|
6771
|
-
class: targetClass,
|
|
6772
|
-
options,
|
|
6773
|
-
fields: combinedFields,
|
|
6774
|
-
resolvedUniqueConstraints
|
|
6775
|
-
};
|
|
6776
|
-
};
|
|
6777
|
-
const directFieldsForThisClass = Object.prototype.hasOwnProperty.call(
|
|
6778
|
-
targetClass,
|
|
6779
|
-
SCHEMA_FIELDS_PROPERTY
|
|
6780
|
-
) ? targetClass[SCHEMA_FIELDS_PROPERTY] : /* @__PURE__ */ new Map();
|
|
6781
|
-
registry.registerModel(targetClass, options, directFieldsForThisClass);
|
|
6782
|
-
};
|
|
6783
|
-
}
|
|
6784
|
-
|
|
6785
6703
|
// src/engines/DatabaseEngine.ts
|
|
6786
6704
|
var DatabaseEngine = class {
|
|
6787
6705
|
createTable(_modelName, _schema, _options) {
|
|
@@ -7182,17 +7100,344 @@ function attachAndRegisterModel(modelClass, schema) {
|
|
|
7182
7100
|
autoRegisterModel(modelClass, runtimeShape);
|
|
7183
7101
|
}
|
|
7184
7102
|
|
|
7185
|
-
// src/utils/
|
|
7103
|
+
// src/utils/yDocSchema.ts
|
|
7186
7104
|
var Y3 = __toESM(require("yjs"), 1);
|
|
7105
|
+
function discoverSchema(yDoc) {
|
|
7106
|
+
const models = {};
|
|
7107
|
+
const metaNames = /* @__PURE__ */ new Set();
|
|
7108
|
+
for (const key of yDoc.share.keys()) {
|
|
7109
|
+
if (!key.startsWith("_meta_")) continue;
|
|
7110
|
+
const map = materializeMap(yDoc, key);
|
|
7111
|
+
if (!map) continue;
|
|
7112
|
+
const modelName = key.slice("_meta_".length);
|
|
7113
|
+
metaNames.add(modelName);
|
|
7114
|
+
models[modelName] = readModelMeta(map);
|
|
7115
|
+
}
|
|
7116
|
+
for (const key of yDoc.share.keys()) {
|
|
7117
|
+
if (key.startsWith("_")) continue;
|
|
7118
|
+
if (metaNames.has(key)) continue;
|
|
7119
|
+
const map = materializeMap(yDoc, key);
|
|
7120
|
+
if (!map || map.size === 0) continue;
|
|
7121
|
+
const inferred = inferModelFromData(map);
|
|
7122
|
+
if (inferred) models[key] = inferred;
|
|
7123
|
+
}
|
|
7124
|
+
return { models };
|
|
7125
|
+
}
|
|
7126
|
+
function discoverModelNames(yDoc) {
|
|
7127
|
+
const names = [];
|
|
7128
|
+
for (const key of yDoc.share.keys()) {
|
|
7129
|
+
if (key.startsWith("_")) continue;
|
|
7130
|
+
const map = materializeMap(yDoc, key);
|
|
7131
|
+
if (map) names.push(key);
|
|
7132
|
+
}
|
|
7133
|
+
return names.sort();
|
|
7134
|
+
}
|
|
7135
|
+
function materializeMap(yDoc, key) {
|
|
7136
|
+
try {
|
|
7137
|
+
const map = yDoc.getMap(key);
|
|
7138
|
+
return map instanceof Y3.Map ? map : null;
|
|
7139
|
+
} catch {
|
|
7140
|
+
return null;
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
function readModelMeta(metaMap) {
|
|
7144
|
+
const fields = {};
|
|
7145
|
+
let constraints;
|
|
7146
|
+
let relationships;
|
|
7147
|
+
for (const [key, value] of metaMap.entries()) {
|
|
7148
|
+
if (key === "_constraints" && value instanceof Y3.Map) {
|
|
7149
|
+
constraints = readConstraints(value);
|
|
7150
|
+
} else if (key === "_relationships" && value instanceof Y3.Map) {
|
|
7151
|
+
relationships = readRelationships(value);
|
|
7152
|
+
} else if (value instanceof Y3.Map) {
|
|
7153
|
+
fields[key] = readFieldMeta(value);
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
const model = { fields };
|
|
7157
|
+
if (constraints && Object.keys(constraints).length > 0) {
|
|
7158
|
+
model.constraints = constraints;
|
|
7159
|
+
}
|
|
7160
|
+
if (relationships && Object.keys(relationships).length > 0) {
|
|
7161
|
+
model.relationships = relationships;
|
|
7162
|
+
}
|
|
7163
|
+
return model;
|
|
7164
|
+
}
|
|
7165
|
+
function readFieldMeta(fieldMap) {
|
|
7166
|
+
const field = { type: fieldMap.get("type") ?? "unknown" };
|
|
7167
|
+
if (fieldMap.get("indexed") === true) field.indexed = true;
|
|
7168
|
+
if (fieldMap.get("unique") === true) field.unique = true;
|
|
7169
|
+
if (fieldMap.get("required") === true) field.required = true;
|
|
7170
|
+
if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
|
|
7171
|
+
const def = fieldMap.get("default");
|
|
7172
|
+
if (def !== void 0) field.default = def;
|
|
7173
|
+
const maxLength = fieldMap.get("maxLength");
|
|
7174
|
+
if (maxLength !== void 0) field.maxLength = maxLength;
|
|
7175
|
+
const maxCount = fieldMap.get("maxCount");
|
|
7176
|
+
if (maxCount !== void 0) field.maxCount = maxCount;
|
|
7177
|
+
return field;
|
|
7178
|
+
}
|
|
7179
|
+
function inferModelFromData(dataMap) {
|
|
7180
|
+
const fields = {};
|
|
7181
|
+
let sampled = 0;
|
|
7182
|
+
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
7183
|
+
if (!(recordValue instanceof Y3.Map)) continue;
|
|
7184
|
+
if (++sampled > 5) break;
|
|
7185
|
+
for (const [fieldName, value] of recordValue.entries()) {
|
|
7186
|
+
if (fieldName.startsWith("_")) continue;
|
|
7187
|
+
if (fields[fieldName]) continue;
|
|
7188
|
+
const type = inferTypeFromValue(value);
|
|
7189
|
+
if (type) fields[fieldName] = { type };
|
|
7190
|
+
}
|
|
7191
|
+
}
|
|
7192
|
+
if (Object.keys(fields).length === 0) return null;
|
|
7193
|
+
return { fields };
|
|
7194
|
+
}
|
|
7195
|
+
function inferTypeFromValue(value) {
|
|
7196
|
+
if (value instanceof Y3.Map) return "stringset";
|
|
7197
|
+
switch (typeof value) {
|
|
7198
|
+
case "string":
|
|
7199
|
+
return "string";
|
|
7200
|
+
case "number":
|
|
7201
|
+
return "number";
|
|
7202
|
+
case "boolean":
|
|
7203
|
+
return "boolean";
|
|
7204
|
+
default:
|
|
7205
|
+
return null;
|
|
7206
|
+
}
|
|
7207
|
+
}
|
|
7208
|
+
function readConstraints(constraintsMap) {
|
|
7209
|
+
const out = {};
|
|
7210
|
+
for (const [name, value] of constraintsMap.entries()) {
|
|
7211
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
7212
|
+
let fields = [];
|
|
7213
|
+
const rawFields = value.get("fields");
|
|
7214
|
+
if (typeof rawFields === "string") {
|
|
7215
|
+
try {
|
|
7216
|
+
fields = JSON.parse(rawFields);
|
|
7217
|
+
} catch {
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
out[name] = {
|
|
7221
|
+
type: value.get("type") ?? "unknown",
|
|
7222
|
+
fields
|
|
7223
|
+
};
|
|
7224
|
+
}
|
|
7225
|
+
return out;
|
|
7226
|
+
}
|
|
7227
|
+
function readRelationships(relsMap) {
|
|
7228
|
+
const out = {};
|
|
7229
|
+
for (const [name, value] of relsMap.entries()) {
|
|
7230
|
+
if (!(value instanceof Y3.Map)) continue;
|
|
7231
|
+
const rel = {};
|
|
7232
|
+
for (const [k, v] of value.entries()) {
|
|
7233
|
+
rel[k] = v;
|
|
7234
|
+
}
|
|
7235
|
+
out[name] = rel;
|
|
7236
|
+
}
|
|
7237
|
+
return out;
|
|
7238
|
+
}
|
|
7239
|
+
var CAMEL_TO_SNAKE = {
|
|
7240
|
+
autoAssign: "auto_assign",
|
|
7241
|
+
maxLength: "max_length",
|
|
7242
|
+
maxCount: "max_count",
|
|
7243
|
+
relatedIdField: "related_id_field",
|
|
7244
|
+
joinModel: "join_model",
|
|
7245
|
+
joinModelLocalField: "join_model_local_field",
|
|
7246
|
+
joinModelRelatedField: "join_model_related_field",
|
|
7247
|
+
joinModelOrderByField: "join_model_order_by_field",
|
|
7248
|
+
joinModelOrderDirection: "join_model_order_direction",
|
|
7249
|
+
orderByField: "order_by_field",
|
|
7250
|
+
orderDirection: "order_direction"
|
|
7251
|
+
};
|
|
7252
|
+
function toSnake(key) {
|
|
7253
|
+
return CAMEL_TO_SNAKE[key] ?? key;
|
|
7254
|
+
}
|
|
7255
|
+
function tomlValue(v) {
|
|
7256
|
+
if (typeof v === "string") {
|
|
7257
|
+
return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
|
|
7258
|
+
}
|
|
7259
|
+
return String(v);
|
|
7260
|
+
}
|
|
7261
|
+
function schemaToToml(schema) {
|
|
7262
|
+
const lines = [];
|
|
7263
|
+
for (const [modelName, model] of Object.entries(schema.models)) {
|
|
7264
|
+
if (lines.length > 0) lines.push("", "");
|
|
7265
|
+
lines.push(`[models.${modelName}]`);
|
|
7266
|
+
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
7267
|
+
lines.push("");
|
|
7268
|
+
lines.push(`[models.${modelName}.fields.${fieldName}]`);
|
|
7269
|
+
lines.push(`type = ${tomlValue(field.type)}`);
|
|
7270
|
+
if (field.autoAssign) lines.push("auto_assign = true");
|
|
7271
|
+
if (field.indexed) lines.push("indexed = true");
|
|
7272
|
+
if (field.unique) lines.push("unique = true");
|
|
7273
|
+
if (field.required) lines.push("required = true");
|
|
7274
|
+
if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
|
|
7275
|
+
if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
|
|
7276
|
+
if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
|
|
7277
|
+
}
|
|
7278
|
+
if (model.relationships) {
|
|
7279
|
+
for (const [relName, rel] of Object.entries(model.relationships)) {
|
|
7280
|
+
lines.push("");
|
|
7281
|
+
lines.push(`[models.${modelName}.relationships.${relName}]`);
|
|
7282
|
+
for (const [k, v] of Object.entries(rel)) {
|
|
7283
|
+
if (v === void 0) continue;
|
|
7284
|
+
lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
|
|
7285
|
+
}
|
|
7286
|
+
}
|
|
7287
|
+
}
|
|
7288
|
+
if (model.constraints) {
|
|
7289
|
+
for (const [cName, c] of Object.entries(model.constraints)) {
|
|
7290
|
+
lines.push("");
|
|
7291
|
+
lines.push(`[[models.${modelName}.unique_constraints]]`);
|
|
7292
|
+
lines.push(`name = ${tomlValue(cName)}`);
|
|
7293
|
+
lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7296
|
+
}
|
|
7297
|
+
lines.push("");
|
|
7298
|
+
return lines.join("\n");
|
|
7299
|
+
}
|
|
7300
|
+
|
|
7301
|
+
// src/models/tomlLoader.ts
|
|
7302
|
+
var import_smol_toml = require("smol-toml");
|
|
7303
|
+
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
7304
|
+
"string",
|
|
7305
|
+
"number",
|
|
7306
|
+
"boolean",
|
|
7307
|
+
"date",
|
|
7308
|
+
"id",
|
|
7309
|
+
"stringset"
|
|
7310
|
+
]);
|
|
7311
|
+
function parseFieldOptions(raw) {
|
|
7312
|
+
if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
|
|
7313
|
+
throw new Error(
|
|
7314
|
+
`Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
|
|
7315
|
+
);
|
|
7316
|
+
}
|
|
7317
|
+
const opts = { type: raw.type };
|
|
7318
|
+
if (raw.indexed === true) opts.indexed = true;
|
|
7319
|
+
if (raw.unique === true) opts.unique = true;
|
|
7320
|
+
if (raw.required === true) opts.required = true;
|
|
7321
|
+
if (raw.auto_assign === true) opts.autoAssign = true;
|
|
7322
|
+
if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
|
|
7323
|
+
if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
|
|
7324
|
+
if (raw.default !== void 0) opts.default = raw.default;
|
|
7325
|
+
return opts;
|
|
7326
|
+
}
|
|
7327
|
+
function requireField(raw, field, context) {
|
|
7328
|
+
if (!raw[field]) {
|
|
7329
|
+
throw new Error(`Relationship ${context}: missing required field "${field}"`);
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
function parseRelationship(raw) {
|
|
7333
|
+
const type = raw.type;
|
|
7334
|
+
if (type === "refersTo") {
|
|
7335
|
+
requireField(raw, "model", "refersTo");
|
|
7336
|
+
requireField(raw, "related_id_field", "refersTo");
|
|
7337
|
+
return {
|
|
7338
|
+
type: "refersTo",
|
|
7339
|
+
model: raw.model,
|
|
7340
|
+
relatedIdField: raw.related_id_field
|
|
7341
|
+
};
|
|
7342
|
+
}
|
|
7343
|
+
if (type === "hasMany") {
|
|
7344
|
+
requireField(raw, "model", "hasMany");
|
|
7345
|
+
requireField(raw, "related_id_field", "hasMany");
|
|
7346
|
+
const rel = {
|
|
7347
|
+
type: "hasMany",
|
|
7348
|
+
model: raw.model,
|
|
7349
|
+
relatedIdField: raw.related_id_field
|
|
7350
|
+
};
|
|
7351
|
+
if (raw.order_by_field) rel.orderByField = raw.order_by_field;
|
|
7352
|
+
if (raw.order_direction) rel.orderDirection = raw.order_direction;
|
|
7353
|
+
return rel;
|
|
7354
|
+
}
|
|
7355
|
+
if (type === "hasManyThrough") {
|
|
7356
|
+
requireField(raw, "model", "hasManyThrough");
|
|
7357
|
+
requireField(raw, "join_model", "hasManyThrough");
|
|
7358
|
+
requireField(raw, "join_model_local_field", "hasManyThrough");
|
|
7359
|
+
requireField(raw, "join_model_related_field", "hasManyThrough");
|
|
7360
|
+
const rel = {
|
|
7361
|
+
type: "hasManyThrough",
|
|
7362
|
+
model: raw.model,
|
|
7363
|
+
joinModel: raw.join_model,
|
|
7364
|
+
joinModelLocalField: raw.join_model_local_field,
|
|
7365
|
+
joinModelRelatedField: raw.join_model_related_field
|
|
7366
|
+
};
|
|
7367
|
+
if (raw.join_model_order_by_field)
|
|
7368
|
+
rel.joinModelOrderByField = raw.join_model_order_by_field;
|
|
7369
|
+
if (raw.join_model_order_direction)
|
|
7370
|
+
rel.joinModelOrderDirection = raw.join_model_order_direction;
|
|
7371
|
+
return rel;
|
|
7372
|
+
}
|
|
7373
|
+
throw new Error(`Unknown relationship type: ${type}`);
|
|
7374
|
+
}
|
|
7375
|
+
function loadSchemaFromTomlString(tomlString) {
|
|
7376
|
+
const parsed = (0, import_smol_toml.parse)(tomlString);
|
|
7377
|
+
const models = parsed.models;
|
|
7378
|
+
if (!models || typeof models !== "object") {
|
|
7379
|
+
throw new Error("TOML schema must have a [models] section");
|
|
7380
|
+
}
|
|
7381
|
+
const schemas = [];
|
|
7382
|
+
for (const [modelName, modelDef] of Object.entries(models)) {
|
|
7383
|
+
const fields = {};
|
|
7384
|
+
if (modelDef.fields) {
|
|
7385
|
+
for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
|
|
7386
|
+
fields[fieldName] = parseFieldOptions(fieldDef);
|
|
7387
|
+
}
|
|
7388
|
+
}
|
|
7389
|
+
let relationships;
|
|
7390
|
+
if (modelDef.relationships) {
|
|
7391
|
+
relationships = {};
|
|
7392
|
+
for (const [relName, relDef] of Object.entries(
|
|
7393
|
+
modelDef.relationships
|
|
7394
|
+
)) {
|
|
7395
|
+
relationships[relName] = parseRelationship(relDef);
|
|
7396
|
+
}
|
|
7397
|
+
}
|
|
7398
|
+
let uniqueConstraints;
|
|
7399
|
+
if (modelDef.unique_constraints) {
|
|
7400
|
+
uniqueConstraints = [];
|
|
7401
|
+
for (const raw of modelDef.unique_constraints) {
|
|
7402
|
+
uniqueConstraints.push({
|
|
7403
|
+
name: raw.name,
|
|
7404
|
+
fields: [...raw.fields]
|
|
7405
|
+
});
|
|
7406
|
+
}
|
|
7407
|
+
}
|
|
7408
|
+
schemas.push(
|
|
7409
|
+
defineModelSchema({
|
|
7410
|
+
name: modelName,
|
|
7411
|
+
fields,
|
|
7412
|
+
options: {
|
|
7413
|
+
uniqueConstraints,
|
|
7414
|
+
relationships
|
|
7415
|
+
}
|
|
7416
|
+
})
|
|
7417
|
+
);
|
|
7418
|
+
}
|
|
7419
|
+
return schemas;
|
|
7420
|
+
}
|
|
7421
|
+
async function loadSchemaFromToml(filePath) {
|
|
7422
|
+
const { readFile } = await import("fs/promises");
|
|
7423
|
+
const content = await readFile(filePath, "utf-8");
|
|
7424
|
+
return loadSchemaFromTomlString(content);
|
|
7425
|
+
}
|
|
7426
|
+
|
|
7427
|
+
// src/node.ts
|
|
7428
|
+
init_metaSync();
|
|
7429
|
+
|
|
7430
|
+
// src/utils/yDocDump.ts
|
|
7431
|
+
var Y4 = __toESM(require("yjs"), 1);
|
|
7187
7432
|
function toPlain(value) {
|
|
7188
|
-
if (value instanceof
|
|
7433
|
+
if (value instanceof Y4.Map) {
|
|
7189
7434
|
const obj = {};
|
|
7190
7435
|
value.forEach((v, k) => {
|
|
7191
7436
|
obj[k] = toPlain(v);
|
|
7192
7437
|
});
|
|
7193
7438
|
return obj;
|
|
7194
7439
|
}
|
|
7195
|
-
if (value instanceof
|
|
7440
|
+
if (value instanceof Y4.Array) {
|
|
7196
7441
|
return value.toArray().map((item) => toPlain(item));
|
|
7197
7442
|
}
|
|
7198
7443
|
return value;
|
|
@@ -7201,7 +7446,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
|
|
|
7201
7446
|
const result = {};
|
|
7202
7447
|
const includeIndexes = !!options.includeIndexes;
|
|
7203
7448
|
yDoc.share.forEach((type, name) => {
|
|
7204
|
-
if (!(type instanceof
|
|
7449
|
+
if (!(type instanceof Y4.Map)) return;
|
|
7205
7450
|
if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
|
|
7206
7451
|
const records = {};
|
|
7207
7452
|
type.forEach((recordValue, recordId) => {
|
|
@@ -7255,10 +7500,8 @@ async function getRecommendedNodeEngine() {
|
|
|
7255
7500
|
BaseModel,
|
|
7256
7501
|
DatabaseEngine,
|
|
7257
7502
|
DatabaseFactory,
|
|
7258
|
-
Field,
|
|
7259
7503
|
LogLevel,
|
|
7260
7504
|
Logger,
|
|
7261
|
-
Model,
|
|
7262
7505
|
ModelRegistry,
|
|
7263
7506
|
RecordNotFoundError,
|
|
7264
7507
|
SqljsEngine,
|
|
@@ -7267,18 +7510,28 @@ async function getRecommendedNodeEngine() {
|
|
|
7267
7510
|
attachAndRegisterModel,
|
|
7268
7511
|
attachSchemaToClass,
|
|
7269
7512
|
autoRegisterModel,
|
|
7513
|
+
clearMetaSyncCache,
|
|
7270
7514
|
constants,
|
|
7271
7515
|
createModelClass,
|
|
7272
7516
|
defineModelSchema,
|
|
7273
7517
|
detectEnvironment,
|
|
7518
|
+
discoverModelNames,
|
|
7519
|
+
discoverSchema,
|
|
7274
7520
|
dumpYDocToPlain,
|
|
7275
7521
|
features,
|
|
7276
7522
|
generateULID,
|
|
7277
7523
|
getRecommendedNodeEngine,
|
|
7524
|
+
inferFieldType,
|
|
7278
7525
|
initJsBao,
|
|
7279
7526
|
isBrowser,
|
|
7280
7527
|
isNode,
|
|
7281
7528
|
isNodeModuleAvailable,
|
|
7529
|
+
loadSchemaFromToml,
|
|
7530
|
+
loadSchemaFromTomlString,
|
|
7531
|
+
registerFunctionDefault,
|
|
7282
7532
|
resetJsBao,
|
|
7283
|
-
|
|
7533
|
+
schemaToToml,
|
|
7534
|
+
summarizePlainYDoc,
|
|
7535
|
+
syncInferredMeta,
|
|
7536
|
+
syncModelMeta
|
|
7284
7537
|
});
|