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.
@@ -1,3 +1,5 @@
1
+ import * as Y from 'yjs';
2
+
1
3
  interface RefersToRelationshipConfig {
2
4
  type: "refersTo";
3
5
  model: string;
@@ -716,12 +718,22 @@ interface QueryOptions {
716
718
  direction?: 1 | -1;
717
719
  include?: IncludeSpec[];
718
720
  }
721
+ interface PaginatedResult<T> {
722
+ data: T[];
723
+ nextCursor?: string;
724
+ prevCursor?: string;
725
+ hasMore: boolean;
726
+ }
719
727
  interface TranslatedQuery {
720
728
  sql: string;
721
729
  params: any[];
722
730
  sortFields: string[];
723
731
  sortDirections?: (1 | -1)[];
724
732
  }
733
+ type ProjectedResult<T, P extends ProjectionSpec> = {
734
+ [K in keyof P]: K extends keyof T ? T[K] : never;
735
+ };
736
+ type QueryResult<T, P extends ProjectionSpec | undefined> = P extends ProjectionSpec ? ProjectedResult<T, P> : T;
725
737
 
726
738
  /**
727
739
  * JSON Query Translator
@@ -849,18 +861,18 @@ declare class JsonQueryTranslator {
849
861
  * Describes a StringSet membership check in a groupBy clause.
850
862
  * Groups records by whether they have a specific value in a StringSet field.
851
863
  */
852
- interface StringSetMembership {
864
+ interface StringSetMembership$1 {
853
865
  field: string;
854
866
  contains: string;
855
867
  }
856
868
  /**
857
869
  * A groupBy field can be a plain field name or a StringSet membership check.
858
870
  */
859
- type GroupByField = string | StringSetMembership;
871
+ type GroupByField$1 = string | StringSetMembership$1;
860
872
  /**
861
873
  * An aggregation operation (count, sum, avg, min, max).
862
874
  */
863
- interface AggregationOperation {
875
+ interface AggregationOperation$1 {
864
876
  type: "count" | "sum" | "avg" | "min" | "max";
865
877
  /** Required for sum, avg, min, max; not used for count */
866
878
  field?: string;
@@ -868,9 +880,9 @@ interface AggregationOperation {
868
880
  /**
869
881
  * Options for an aggregation query.
870
882
  */
871
- interface AggregationOptions {
872
- groupBy: GroupByField[];
873
- operations: AggregationOperation[];
883
+ interface AggregationOptions$1 {
884
+ groupBy: GroupByField$1[];
885
+ operations: AggregationOperation$1[];
874
886
  filter?: DocumentFilter;
875
887
  limit?: number;
876
888
  sort?: {
@@ -883,7 +895,7 @@ interface AggregationOptions {
883
895
  /**
884
896
  * Result of an aggregation query — nested object keyed by group values.
885
897
  */
886
- type AggregationResult = Record<string, any> | Record<string, any>[];
898
+ type AggregationResult$1 = Record<string, any> | Record<string, any>[];
887
899
 
888
900
  /**
889
901
  * Hook type definitions for Durable Object access control.
@@ -1084,10 +1096,10 @@ interface UniqueConstraintListResponse {
1084
1096
  }
1085
1097
  interface AggregateRequest {
1086
1098
  modelName: string;
1087
- options: AggregationOptions;
1099
+ options: AggregationOptions$1;
1088
1100
  }
1089
1101
  interface AggregateResponse {
1090
- result: AggregationResult;
1102
+ result: AggregationResult$1;
1091
1103
  }
1092
1104
  interface SyncIndexesRequest {
1093
1105
  models: Array<{
@@ -1236,7 +1248,7 @@ declare function createDatabaseDO(config?: DatabaseDOConfig): {
1236
1248
  _handleStringSetRemove(request: Request, _docId: string): Promise<Response>;
1237
1249
  _handleAggregate(request: Request, docId: string): Promise<Response>;
1238
1250
  /** @internal — Build SQL for StringSet facet aggregation */
1239
- _buildStringSetFacetSql(modelName: string, facetField: string, aggOptions: AggregationOptions, filter: DocumentFilter, translator: JsonQueryTranslator): {
1251
+ _buildStringSetFacetSql(modelName: string, facetField: string, aggOptions: AggregationOptions$1, filter: DocumentFilter, translator: JsonQueryTranslator): {
1240
1252
  sql: string;
1241
1253
  params: any[];
1242
1254
  };
@@ -1244,7 +1256,7 @@ declare function createDatabaseDO(config?: DatabaseDOConfig): {
1244
1256
  _buildRegularAggregationSql(modelName: string, regularGroupBy: string[], stringSetMemberships: Array<{
1245
1257
  field: string;
1246
1258
  contains: string;
1247
- }>, aggOptions: AggregationOptions, filter: DocumentFilter, translator: JsonQueryTranslator): {
1259
+ }>, aggOptions: AggregationOptions$1, filter: DocumentFilter, translator: JsonQueryTranslator): {
1248
1260
  sql: string;
1249
1261
  params: any[];
1250
1262
  aliasMap: Array<{
@@ -1254,13 +1266,13 @@ declare function createDatabaseDO(config?: DatabaseDOConfig): {
1254
1266
  }>;
1255
1267
  };
1256
1268
  /** @internal — Extract operation value(s) from a row. Flattens single-op results. */
1257
- _extractOpValue(row: any, operations: AggregationOptions["operations"]): any;
1269
+ _extractOpValue(row: any, operations: AggregationOptions$1["operations"]): any;
1258
1270
  /** @internal — Process raw aggregation rows into nested result */
1259
- _processAggregationResults(results: any[], aggOptions: AggregationOptions, aliasMap: Array<{
1271
+ _processAggregationResults(results: any[], aggOptions: AggregationOptions$1, aliasMap: Array<{
1260
1272
  alias: string;
1261
1273
  field: string;
1262
1274
  contains: string;
1263
- }>, stringSetFacetField: string | null): AggregationResult;
1275
+ }>, stringSetFacetField: string | null): AggregationResult$1;
1264
1276
  /** @internal */
1265
1277
  /** @internal — Batch sync: compare desired indexes against _indexes table, register missing */
1266
1278
  _handleIndexesSync(request: Request): Promise<Response>;
@@ -1395,4 +1407,494 @@ interface Env {
1395
1407
  */
1396
1408
  declare function handleRequest(request: Request, env: Env): Promise<Response>;
1397
1409
 
1398
- export { type AfterQueryContext, type AfterQueryResult, type AggregateRequest, type AggregateResponse, type AggregationOperation, type AggregationOptions, type AggregationResult, type BatchOperation, type BatchOperationResult, type BatchRequest, type BatchResponse, type BeforeDeleteContext, type BeforeQueryContext, type BeforeQueryResult, type BeforeSaveContext, type CountRequest, type CountResponse, type DatabaseDOConfig, type DatabaseDOHooks, type DeleteRequest, type DeleteResponse, type DocumentDOConfig, type DropIndexRequest, type DropIndexResponse, type DropUniqueConstraintRequest, type DropUniqueConstraintResponse, DurableObjectEngine, type DurableObjectEngineOptions, type DurableObjectId, type DurableObjectNamespace, type DurableObjectState, type DurableObjectStorage, type DurableObjectStub, type Env, type ErrorResponse, type GroupByField, type HookContext, type HookResult, type IncrementRequest, type IncrementResponse, type IndexEntry, type IndexListResponse, JsonQueryTranslator, type JsonQueryTranslatorOptions, JsonSchemaDDL, type JsonSchemaOptions, type PatchRequest, type PatchResponse, type QueryRequest, type QueryResponse, type RegisterIndexRequest, type RegisterIndexResponse, type RegisterUniqueConstraintRequest, type RegisterUniqueConstraintResponse, type SaveRequest, type SaveResponse, type SchemaConstraintInfo, type SchemaFieldInfo, type SchemaModelInfo, type SchemaResponse, type SqlStorage, type SqlStorageCursor, type StringSetMembership, type StringSetUpdateRequest, type StringSetUpdateResponse, type SyncIndexesRequest, type SyncIndexesResponse, type UniqueConstraintEntry, type UniqueConstraintListResponse, createDatabaseDO, createDocumentDO, handleRequest };
1410
+ /**
1411
+ * YDoc Schema Discovery
1412
+ *
1413
+ * Reads _meta_* YMaps from a YDoc and returns a plain JSON description
1414
+ * of the schema. Works with any YDoc — no BaseModel or database needed.
1415
+ *
1416
+ * Usage:
1417
+ * import { discoverSchema } from "js-bao";
1418
+ * const schema = discoverSchema(yDoc);
1419
+ */
1420
+
1421
+ interface DiscoveredField {
1422
+ type: string;
1423
+ indexed?: boolean;
1424
+ unique?: boolean;
1425
+ required?: boolean;
1426
+ default?: string | number | boolean;
1427
+ autoAssign?: boolean;
1428
+ maxLength?: number;
1429
+ maxCount?: number;
1430
+ }
1431
+ interface DiscoveredConstraint {
1432
+ type: string;
1433
+ fields: string[];
1434
+ }
1435
+ interface DiscoveredRelationship {
1436
+ type: string;
1437
+ model: string;
1438
+ [key: string]: any;
1439
+ }
1440
+ interface DiscoveredModel {
1441
+ fields: Record<string, DiscoveredField>;
1442
+ constraints?: Record<string, DiscoveredConstraint>;
1443
+ relationships?: Record<string, DiscoveredRelationship>;
1444
+ }
1445
+ interface DiscoveredSchema {
1446
+ models: Record<string, DiscoveredModel>;
1447
+ }
1448
+ /**
1449
+ * Discover the schema embedded in a YDoc by reading its `_meta_*` maps.
1450
+ *
1451
+ * Returns a plain JSON object describing every model that has metadata.
1452
+ * Does not require BaseModel, a database, or any schema registration —
1453
+ * just a Y.Doc.
1454
+ */
1455
+ declare function discoverSchema(yDoc: Y.Doc): DiscoveredSchema;
1456
+ /**
1457
+ * List model names that have data in the YDoc (non-`_` prefixed top-level maps).
1458
+ */
1459
+ declare function discoverModelNames(yDoc: Y.Doc): string[];
1460
+ /**
1461
+ * Convert a DiscoveredSchema to a TOML string matching the js-bao
1462
+ * schema format.
1463
+ *
1464
+ * Usage:
1465
+ * const schema = discoverSchema(yDoc);
1466
+ * const toml = schemaToToml(schema);
1467
+ */
1468
+ declare function schemaToToml(schema: DiscoveredSchema): string;
1469
+
1470
+ interface StringSetChangeTracker {
1471
+ markStringSetChange(fieldName: string, operation: "add" | "remove" | "clear", value?: string): void;
1472
+ }
1473
+
1474
+ type DocumentPermissionHint = "read" | "read-write";
1475
+ interface SaveOptions {
1476
+ targetDocument?: string;
1477
+ forceWrite?: boolean;
1478
+ upsertOn?: string;
1479
+ }
1480
+
1481
+ declare class DocumentQueryTranslator {
1482
+ private modelName;
1483
+ private schema;
1484
+ private tableName;
1485
+ private quotedTableName;
1486
+ private fieldSqlCache;
1487
+ constructor(modelName: string, schema: Map<string, FieldOptions>);
1488
+ private getQuotedField;
1489
+ /**
1490
+ * Translate document filter and options to SQL for find operations
1491
+ */
1492
+ translateFind(filter: DocumentFilter, options?: QueryOptions): TranslatedQuery;
1493
+ /**
1494
+ * Translate document filter to SQL for count operations
1495
+ */
1496
+ translateCount(filter: DocumentFilter, options?: Pick<QueryOptions, "documents">): {
1497
+ sql: string;
1498
+ params: any[];
1499
+ };
1500
+ /**
1501
+ * Translate document filter to SQL WHERE clause
1502
+ */
1503
+ translateFilter(filter: DocumentFilter): {
1504
+ sql: string;
1505
+ params: any[];
1506
+ };
1507
+ /**
1508
+ * Translate logical operators ($and, $or)
1509
+ */
1510
+ private translateLogicalOperator;
1511
+ /**
1512
+ * Translate field condition to SQL
1513
+ */
1514
+ private translateFieldCondition;
1515
+ /**
1516
+ * Translate field operators to SQL
1517
+ */
1518
+ private translateFieldOperators;
1519
+ /**
1520
+ * Translate individual operator to SQL
1521
+ */
1522
+ private translateOperator;
1523
+ /**
1524
+ * Build SELECT clause based on projection
1525
+ */
1526
+ private buildSelectClause;
1527
+ /**
1528
+ * Build LIMIT clause
1529
+ */
1530
+ private buildLimitClause;
1531
+ /**
1532
+ * Build pagination WHERE clause from cursor
1533
+ */
1534
+ private buildPaginationClause;
1535
+ /**
1536
+ * Validate that field exists in schema
1537
+ */
1538
+ private validateField;
1539
+ /**
1540
+ * Validate projection fields
1541
+ */
1542
+ private validateProjection;
1543
+ /**
1544
+ * Validate operator is supported for field type
1545
+ */
1546
+ private validateOperatorForType;
1547
+ /**
1548
+ * Validate field value matches expected type
1549
+ */
1550
+ private validateFieldValue;
1551
+ /**
1552
+ * Validate array values for $in/$nin operators
1553
+ */
1554
+ private validateArrayValues;
1555
+ /**
1556
+ * Check if value is a primitive (not an object with operators)
1557
+ */
1558
+ private isPrimitiveValue;
1559
+ /**
1560
+ * Get the type of a value for validation
1561
+ */
1562
+ private getValueType;
1563
+ /**
1564
+ * Check if value type is compatible with field type
1565
+ */
1566
+ private isTypeCompatible;
1567
+ /**
1568
+ * Convert value for SQLite compatibility
1569
+ */
1570
+ private convertValueForSQLite;
1571
+ private normalizeDocumentIds;
1572
+ private buildDocumentClause;
1573
+ }
1574
+
1575
+ interface StringSetMembership {
1576
+ field: string;
1577
+ contains: string;
1578
+ }
1579
+ type GroupByField = string | StringSetMembership;
1580
+ interface AggregationOperation {
1581
+ type: "count" | "sum" | "avg" | "min" | "max";
1582
+ field?: string;
1583
+ }
1584
+ interface AggregationOptions {
1585
+ groupBy: GroupByField[];
1586
+ operations: AggregationOperation[];
1587
+ filter?: DocumentFilter;
1588
+ limit?: number;
1589
+ sort?: {
1590
+ field: string;
1591
+ direction: 1 | -1;
1592
+ };
1593
+ }
1594
+ type AggregationResult = Record<string, any> | Record<string, any>[];
1595
+ interface AggregationAliasDebugInfo {
1596
+ field: string;
1597
+ contains: string;
1598
+ originalAlias: string;
1599
+ }
1600
+ interface AggregationAliasDetail extends AggregationAliasDebugInfo {
1601
+ alias: string;
1602
+ membershipKey: string;
1603
+ }
1604
+ interface AggregationQueryPlan {
1605
+ sql: string;
1606
+ params: any[];
1607
+ aliasMetadata?: AggregationAliasDetail[];
1608
+ }
1609
+ declare enum LogLevel {
1610
+ SILENT = 0,
1611
+ ERROR = 1,
1612
+ WARN = 2,
1613
+ INFO = 3,
1614
+ DEBUG = 4,
1615
+ VERBOSE = 5
1616
+ }
1617
+ declare class BaseModel implements StringSetChangeTracker {
1618
+ static modelName?: string;
1619
+ private static listenersMap;
1620
+ private static modelNameToDefaultDocId;
1621
+ private static globalDefaultDocId;
1622
+ private static defaultDocChangedListeners;
1623
+ private static modelDocMappingChangedListeners;
1624
+ private static readonly DEFAULT_LEGACY_DOC_ID;
1625
+ protected static dbInstance: DatabaseEngine | null;
1626
+ protected static connectedDocuments: Map<string, {
1627
+ yDoc: Y.Doc;
1628
+ permissionHint: DocumentPermissionHint;
1629
+ }>;
1630
+ protected static documentYMaps: Map<string, Y.Map<any>>;
1631
+ private _localChanges;
1632
+ private _isDirty;
1633
+ private _isLoadingFromYjs;
1634
+ private _stringSetFields;
1635
+ protected _constructorProvidedId: boolean;
1636
+ protected _constructorProvidedFields: Set<string>;
1637
+ private _metaDocId;
1638
+ private _metaPermissionHint;
1639
+ /**
1640
+ * Returns the document id this instance is associated with, or null if not resolved yet.
1641
+ */
1642
+ getDocumentId(): string | null;
1643
+ id: string;
1644
+ type: string;
1645
+ static setLogLevel(level: LogLevel): void;
1646
+ static getLogLevel(): LogLevel;
1647
+ static setModelDefaultDocumentId(modelName: string, docId: string): void;
1648
+ static removeModelDefaultDocumentId(modelName: string): void;
1649
+ static clearModelDefaultDocumentIds(): void;
1650
+ static setGlobalDefaultDocumentId(docId: string): void;
1651
+ static clearGlobalDefaultDocumentId(): void;
1652
+ static getModelDefaultDocumentMapping(): Record<string, string>;
1653
+ static getDocumentIdForModel(modelName: string): string | undefined;
1654
+ static getGlobalDefaultDocumentId(): string | undefined;
1655
+ static onDefaultDocChanged(listener: (payload: {
1656
+ previous?: string;
1657
+ current?: string;
1658
+ }) => void): () => void;
1659
+ static onModelDocMappingChanged(listener: (payload: {
1660
+ modelName: string;
1661
+ previous?: string;
1662
+ current?: string;
1663
+ }) => void): () => void;
1664
+ static _clearMappingsForDocId(docId: string): void;
1665
+ private static attachFieldAccessorsSet;
1666
+ static attachFieldAccessors(modelClass: typeof BaseModel, fields: Map<string, FieldOptions>): void;
1667
+ constructor(data?: Partial<any>);
1668
+ private ensureLocalChanges;
1669
+ private hasLocalChange;
1670
+ private getFromYjs;
1671
+ private getValue;
1672
+ private setValue;
1673
+ get isDirty(): boolean;
1674
+ get hasUnsavedChanges(): boolean;
1675
+ private clearLocalChanges;
1676
+ discardChanges(): void;
1677
+ protected validateFieldValue(fieldKey: string, value: any): void;
1678
+ protected validateBeforeSave(): void;
1679
+ getChangedFields(): string[];
1680
+ getOriginalValue(fieldKey: string): any;
1681
+ getCurrentValue(fieldKey: string): any;
1682
+ hasFieldChanged(fieldKey: string): boolean;
1683
+ markStringSetChange(fieldName: string, operation: "add" | "remove" | "clear", value?: string): void;
1684
+ private getStringSetCurrentValues;
1685
+ private getStringSetFromYjs;
1686
+ private getOrCreateStringSet;
1687
+ static initialize(_yDoc: Y.Doc, _db: DatabaseEngine): Promise<void>;
1688
+ static initializeForDocument(yDoc: Y.Doc, db: DatabaseEngine, docId: string, permissionHint: DocumentPermissionHint): Promise<void>;
1689
+ static cleanupDocumentData(docId: string): Promise<void>;
1690
+ static subscribe(callback: () => void): () => void;
1691
+ protected static notifyListeners(): void;
1692
+ /**
1693
+ * Legacy migration method - no longer needed in the new multidoc architecture.
1694
+ * Data migration is now handled during document initialization.
1695
+ */
1696
+ static migrateToNestedYMaps(): Promise<void>;
1697
+ /**
1698
+ * Utility to diff current instance data against YJS nested map data
1699
+ * Returns object with added, modified, and removed fields
1700
+ */
1701
+ protected _diffWithYjsData(): {
1702
+ added: Record<string, any>;
1703
+ modified: Record<string, any>;
1704
+ removed: string[];
1705
+ };
1706
+ /**
1707
+ * Deep equality check for comparing field values
1708
+ */
1709
+ protected _deepEqual(a: any, b: any): boolean;
1710
+ protected static _buildKeyFromValues(fields: string[], keyValues: any[], modelName: string, constraintName: string): string | null;
1711
+ protected _buildUniqueKey(fields: string[], data: Record<string, any>, modelName: string, constraintName: string): string | null;
1712
+ save(options?: SaveOptions): Promise<void>;
1713
+ delete(): Promise<void>;
1714
+ protected getCurrentJSState(): Record<string, any>;
1715
+ protected toJSON(): Record<string, any>;
1716
+ static find<T extends BaseModel>(this: new (...args: any[]) => T, id: string): Promise<T | null>;
1717
+ /**
1718
+ * Document-style query API - returns paginated results
1719
+ */
1720
+ static query<T extends BaseModel, P extends ProjectionSpec | undefined = undefined>(this: new (...args: any[]) => T, filter?: DocumentFilter, options?: QueryOptions & {
1721
+ projection?: P;
1722
+ }): Promise<PaginatedResult<QueryResult<T, P>>>;
1723
+ /**
1724
+ * Main aggregation API - performs grouping, faceting, and statistical operations
1725
+ * @param options Aggregation configuration with groupBy, operations, filter, limit, and sort
1726
+ * @returns Nested object structure with aggregation results
1727
+ *
1728
+ * @example
1729
+ * // Simple facet count
1730
+ * const tagCounts = await Model.aggregate({
1731
+ * groupBy: ['tags'],
1732
+ * operations: [{ type: 'count' }]
1733
+ * });
1734
+ * // Result: { red: 15, blue: 8, green: 12 }
1735
+ *
1736
+ * @example
1737
+ * // Multi-dimensional grouping with multiple operations
1738
+ * const categoryStats = await Model.aggregate({
1739
+ * groupBy: ['category', 'status'],
1740
+ * operations: [
1741
+ * { type: 'count' },
1742
+ * { type: 'sum', field: 'amount' },
1743
+ * { type: 'avg', field: 'score' }
1744
+ * ],
1745
+ * filter: { active: true },
1746
+ * sort: { field: 'count', direction: 'desc' },
1747
+ * limit: 10
1748
+ * });
1749
+ *
1750
+ * @example
1751
+ * // StringSet membership grouping
1752
+ * const urgentCounts = await Model.aggregate({
1753
+ * groupBy: [{ field: 'tags', contains: 'urgent' }],
1754
+ * operations: [{ type: 'count' }]
1755
+ * });
1756
+ * // Result: { true: 5, false: 23 }
1757
+ */
1758
+ static aggregate<T extends BaseModel>(this: new (...args: any[]) => T, options: AggregationOptions): Promise<AggregationResult>;
1759
+ /**
1760
+ * Build SQL query for structured aggregation
1761
+ */
1762
+ protected static buildAggregationQuery(options: AggregationOptions, schema: any, modelName: string): AggregationQueryPlan;
1763
+ /**
1764
+ * Get the proper database table name (should match database engine naming)
1765
+ */
1766
+ protected static getDatabaseTableName(modelName: string): string;
1767
+ /**
1768
+ * Get the proper database junction table name for StringSet fields
1769
+ */
1770
+ protected static getDatabaseJunctionTableName(modelName: string, fieldName: string): string;
1771
+ private static buildMembershipKey;
1772
+ /**
1773
+ * Build query for StringSet facet counts
1774
+ */
1775
+ protected static buildStringSetFacetQuery(stringSetFields: string[], options: AggregationOptions, translator: DocumentQueryTranslator, modelName: string): AggregationQueryPlan;
1776
+ /**
1777
+ * Build query for regular field aggregation
1778
+ */
1779
+ protected static buildRegularAggregationQuery(regularGroupBy: string[], stringSetMemberships: StringSetMembership[], options: AggregationOptions, translator: DocumentQueryTranslator, modelName: string): AggregationQueryPlan;
1780
+ /**
1781
+ * Process aggregation results into nested structure
1782
+ */
1783
+ protected static processAggregationResults(results: any[], options: AggregationOptions, aliasMetadata?: AggregationAliasDetail[]): AggregationResult;
1784
+ /**
1785
+ * Document-style query API - returns single result or null
1786
+ */
1787
+ static queryOne<T extends BaseModel, P extends ProjectionSpec | undefined = undefined>(this: new (...args: any[]) => T, filter?: DocumentFilter, options?: Omit<QueryOptions, "limit" | "uniqueStartKey" | "direction"> & {
1788
+ projection?: P;
1789
+ }): Promise<QueryResult<T, P> | null>;
1790
+ /**
1791
+ * Document-style count API
1792
+ */
1793
+ static count(this: new (...args: any[]) => any, filter?: DocumentFilter, options?: Pick<QueryOptions, "documents">): Promise<number>;
1794
+ static findAll<T extends BaseModel>(this: new (...args: any[]) => T): Promise<T[]>;
1795
+ static findByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, value: any | any[]): Promise<T | null>;
1796
+ static upsertByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, uniqueLookupValue: any | any[], dataToUpsert: Partial<Omit<InstanceType<new (...args: any[]) => T>, keyof BaseModel | "toJSON">> & {
1797
+ id?: string;
1798
+ }, options?: {
1799
+ objectMustExist?: boolean;
1800
+ objectMustNotExist?: boolean;
1801
+ targetDocument?: string;
1802
+ }): Promise<T>;
1803
+ /**
1804
+ * Execute a callback with automatic transaction handling for all modified models
1805
+ */
1806
+ static withTransaction<T>(callback: () => Promise<T> | T): Promise<T>;
1807
+ /**
1808
+ * Sets up deep observation on a nested YMap to sync field-level changes to the database
1809
+ */
1810
+ protected static setupNestedYMapObserver(recordId: string, recordYMap: Y.Map<any>): void;
1811
+ /**
1812
+ * Sets up deep observation on a nested YMap for a specific document to sync field-level changes to the database
1813
+ */
1814
+ protected static setupNestedYMapObserverForDocument(recordId: string, recordYMap: Y.Map<any>, docId: string, permissionHint: DocumentPermissionHint): void;
1815
+ }
1816
+
1817
+ interface ResolvedUniqueConstraint {
1818
+ name: string;
1819
+ fields: string[];
1820
+ }
1821
+ interface ModelSchemaRuntimeShape {
1822
+ class: typeof BaseModel;
1823
+ options: ModelOptions;
1824
+ fields: Map<string, FieldOptions>;
1825
+ resolvedUniqueConstraints: ResolvedUniqueConstraint[];
1826
+ }
1827
+ interface DefinedModelSchema<TFields extends Record<string, FieldOptions> = Record<string, FieldOptions>> {
1828
+ name: string;
1829
+ fields: TFields;
1830
+ options: ModelOptions;
1831
+ runtimeShape?: ModelSchemaRuntimeShape;
1832
+ buildRuntimeShape(modelClass: typeof BaseModel): ModelSchemaRuntimeShape;
1833
+ }
1834
+
1835
+ /**
1836
+ * TOML Schema Loader
1837
+ *
1838
+ * Parses a TOML schema file and returns an array of DefinedModelSchema
1839
+ * objects. Can be used in place of manual `defineModelSchema()` calls.
1840
+ *
1841
+ * TOML conventions:
1842
+ * - Property names are snake_case (auto_assign, max_count, …)
1843
+ * - Model names and field names are as-is (user-chosen)
1844
+ * - Relationships live under [models.*.relationships.*]
1845
+ * - Compound unique constraints are [[models.*.unique_constraints]]
1846
+ */
1847
+
1848
+ /**
1849
+ * Parse a TOML string and return an array of DefinedModelSchema objects.
1850
+ */
1851
+ declare function loadSchemaFromTomlString(tomlString: string): DefinedModelSchema[];
1852
+
1853
+ /**
1854
+ * Meta Sync — writes _meta_* YMaps into a YDoc.
1855
+ *
1856
+ * Each model with data in a YDoc gets a `_meta_{modelName}` YMap that
1857
+ * describes the model's fields, constraints, and relationships. This
1858
+ * lets any language that can read a YDoc discover the schema without
1859
+ * external configuration.
1860
+ *
1861
+ * Two modes:
1862
+ * 1. **Schema-aware** — full schema known (from defineModelSchema / TOML).
1863
+ * Writes field metadata, constraints, and relationships.
1864
+ * 2. **Infer-on-write** — no schema. Infers types from record values.
1865
+ */
1866
+
1867
+ /**
1868
+ * Infer a _meta_ type string from a JS runtime value.
1869
+ */
1870
+ declare function inferFieldType(value: unknown): "string" | "number" | "boolean" | "stringset" | null;
1871
+ /**
1872
+ * Register a named function default so metaSync can encode it.
1873
+ * Called once per known default generator.
1874
+ */
1875
+ declare function registerFunctionDefault(fn: Function, name: string): void;
1876
+ /**
1877
+ * Clear the sync cache for a specific doc (or all docs).
1878
+ * Useful for testing or when schema changes at runtime.
1879
+ */
1880
+ declare function clearMetaSyncCache(yDoc?: Y.Doc): void;
1881
+ /**
1882
+ * Sync full schema metadata into `_meta_{modelName}` inside a YDoc.
1883
+ *
1884
+ * Call this inside an existing `yDoc.transact()`. Y.Map `.set()` on
1885
+ * identical values is a CRDT no-op so there is no overhead after the
1886
+ * first write.
1887
+ *
1888
+ * Skips the sync if this (yDoc, modelName) pair has already been synced
1889
+ * in the current session.
1890
+ */
1891
+ declare function syncModelMeta(yDoc: Y.Doc, modelName: string, schema: ModelSchemaRuntimeShape): void;
1892
+ /**
1893
+ * Infer-on-write: when no schema is available, infer field types from
1894
+ * the record data and write minimal _meta_.
1895
+ *
1896
+ * Call inside an existing `yDoc.transact()`.
1897
+ */
1898
+ declare function syncInferredMeta(yDoc: Y.Doc, modelName: string, recordData: Record<string, any>): void;
1899
+
1900
+ export { type AfterQueryContext, type AfterQueryResult, type AggregateRequest, type AggregateResponse, type AggregationOperation$1 as AggregationOperation, type AggregationOptions$1 as AggregationOptions, type AggregationResult$1 as AggregationResult, type BatchOperation, type BatchOperationResult, type BatchRequest, type BatchResponse, type BeforeDeleteContext, type BeforeQueryContext, type BeforeQueryResult, type BeforeSaveContext, type CountRequest, type CountResponse, type DatabaseDOConfig, type DatabaseDOHooks, type DeleteRequest, type DeleteResponse, type DiscoveredConstraint, type DiscoveredField, type DiscoveredModel, type DiscoveredRelationship, type DiscoveredSchema, type DocumentDOConfig, type DropIndexRequest, type DropIndexResponse, type DropUniqueConstraintRequest, type DropUniqueConstraintResponse, DurableObjectEngine, type DurableObjectEngineOptions, type DurableObjectId, type DurableObjectNamespace, type DurableObjectState, type DurableObjectStorage, type DurableObjectStub, type Env, type ErrorResponse, type GroupByField$1 as GroupByField, type HookContext, type HookResult, type IncrementRequest, type IncrementResponse, type IndexEntry, type IndexListResponse, JsonQueryTranslator, type JsonQueryTranslatorOptions, JsonSchemaDDL, type JsonSchemaOptions, type PatchRequest, type PatchResponse, type QueryRequest, type QueryResponse, type RegisterIndexRequest, type RegisterIndexResponse, type RegisterUniqueConstraintRequest, type RegisterUniqueConstraintResponse, type SaveRequest, type SaveResponse, type SchemaConstraintInfo, type SchemaFieldInfo, type SchemaModelInfo, type SchemaResponse, type SqlStorage, type SqlStorageCursor, type StringSetMembership$1 as StringSetMembership, type StringSetUpdateRequest, type StringSetUpdateResponse, type SyncIndexesRequest, type SyncIndexesResponse, type UniqueConstraintEntry, type UniqueConstraintListResponse, clearMetaSyncCache, createDatabaseDO, createDocumentDO, discoverModelNames, discoverSchema, handleRequest, inferFieldType, loadSchemaFromTomlString, registerFunctionDefault, schemaToToml, syncInferredMeta, syncModelMeta };