js-bao 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -698,6 +698,27 @@ declare class BaseModel implements StringSetChangeTracker {
698
698
  */
699
699
  static count(this: new (...args: any[]) => any, filter?: DocumentFilter, options?: Pick<QueryOptions, "documents">): Promise<number>;
700
700
  static findAll<T extends BaseModel>(this: new (...args: any[]) => T): Promise<T[]>;
701
+ /**
702
+ * Resolve a record by its unique-constraint field values via an engine query.
703
+ * Used as a fallback when the `_uniqueIdx_<model>_<constraint>` map has no
704
+ * entry for a key.
705
+ *
706
+ * The index map is a cache over the SQLite projection, not the source of
707
+ * truth: every record is loaded into the projection on `initializeForDocument`
708
+ * regardless of index presence, but a record written by a client predating
709
+ * index maintenance (legacy data) is missing from the index. Such a record
710
+ * silently escapes both `upsertByUnique` lookups and the `save()` uniqueness
711
+ * check. A query over the constraint fields finds it reliably.
712
+ *
713
+ * Contract: RESOLVE ONLY. Returns the owning record (with `_metaDocId` set to
714
+ * the document that holds it, via `queryOne`) or `null`. Callers decide
715
+ * whether to heal the missing index entry (write paths) and do their own
716
+ * logging — this method never mutates the index, so read paths stay
717
+ * read-only. Mirrors `buildUniqueKey`: a null/undefined value in any
718
+ * constraint field means the record does not participate in the constraint,
719
+ * so no query runs.
720
+ */
721
+ private static _resolveByUniqueFallback;
701
722
  static findByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, value: any | any[]): Promise<T | null>;
702
723
  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">> & {
703
724
  id?: string;
@@ -1002,6 +1023,41 @@ declare function discoverModelNames(yDoc: Y.Doc): string[];
1002
1023
  */
1003
1024
  declare function schemaToToml(schema: DiscoveredSchema): string;
1004
1025
 
1026
+ /**
1027
+ * Unique-constraint index helpers (shared CRDT contract).
1028
+ *
1029
+ * js-bao enforces unique constraints inside the Yjs document, not via a SQL
1030
+ * `UNIQUE`. Each constraint has a `_uniqueIdx_<model>_<constraint>` map
1031
+ * (uniqueKey -> surviving recordId) and a document observer that
1032
+ * deterministically discards duplicate losers. Both the client write path and
1033
+ * the server-direct write path (`mutateRecord` in js-bao-wss) must derive the
1034
+ * key and the index map name the SAME way, or a server-written record would
1035
+ * not be seen by the client-side resolver. These helpers are the single source
1036
+ * of truth for that derivation so neither side keeps a parallel copy.
1037
+ */
1038
+
1039
+ /**
1040
+ * Build the unique-constraint key for a record over the given fields.
1041
+ *
1042
+ * Mirrors the document-observer conflict resolver: a `null`/`undefined` value
1043
+ * in any field means the record does not participate in the constraint (returns
1044
+ * `null`); otherwise the per-field `String()` values joined by `"|"`. This is
1045
+ * the key the `_uniqueIdx_*` map is read/written with during conflict
1046
+ * resolution, so it is the key the resolver treats as authoritative.
1047
+ */
1048
+ declare function buildUniqueKey(recordData: Y.Map<any> | Record<string, any>, fields: string[]): string | null;
1049
+ /**
1050
+ * Name of the Yjs map that indexes a unique constraint within a document:
1051
+ * `_uniqueIdx_<model>_<constraint>` mapping uniqueKey -> surviving recordId.
1052
+ */
1053
+ declare function uniqueIndexMapName(modelName: string, constraintName: string): string;
1054
+ /**
1055
+ * The constraint name js-bao assigns to a single-field `unique: true` field
1056
+ * (see `resolveUniqueConstraints` in models/schema.ts). Compound constraints
1057
+ * keep their author-given name instead.
1058
+ */
1059
+ declare function fieldUniqueConstraintName(modelName: string, fieldName: string): string;
1060
+
1005
1061
  interface DumpOptions {
1006
1062
  includeIndexes?: boolean;
1007
1063
  }
@@ -1038,4 +1094,4 @@ declare function dumpYDocToPlain(yDoc: Y.Doc, options?: DumpOptions): PlainYDoc;
1038
1094
  */
1039
1095
  declare function summarizePlainYDoc(dump: PlainYDoc): DumpSummary;
1040
1096
 
1041
- export { BaseModel, type ConnectedDocument, type DatabaseConfig, DatabaseEngine, type DiscoveredConstraint, type DiscoveredField, type DiscoveredModel, type DiscoveredRelationship, type DiscoveredSchema, DocumentClosedError, type DocumentConnectionCallback, type DocumentConnectionEvent, type DocumentFilter, type DocumentManager, type DocumentPermissionHint, DocumentResolutionError, type DumpOptions, type DumpSummary, type DumpSummaryEntry, type FieldOptions, type IncludeSpec, type InferAttrs, type InitJsBaoOptions, type InitJsBaoResult, LogLevel, Logger, type ModelConstructor, type ModelOptions, ModelRegistry, type PaginatedResult, type PaginationOptions, type PlainYDoc, type ProjectionSpec, type QueryOptions, type QueryResult, RecordNotFoundError, type SaveOptions, StringSet, UniqueConstraintViolationError, attachAndRegisterModel, attachSchemaToClass, autoRegisterModel, clearMetaSyncCache, createModelClass, defineModelSchema, discoverModelNames, discoverSchema, dumpYDocToPlain, generateULID, inferFieldType, initJsBao, loadSchemaFromToml, loadSchemaFromTomlString, registerFunctionDefault, resetJsBao, schemaToToml, summarizePlainYDoc, syncInferredMeta, syncModelMeta };
1097
+ export { BaseModel, type ConnectedDocument, type DatabaseConfig, DatabaseEngine, type DiscoveredConstraint, type DiscoveredField, type DiscoveredModel, type DiscoveredRelationship, type DiscoveredSchema, DocumentClosedError, type DocumentConnectionCallback, type DocumentConnectionEvent, type DocumentFilter, type DocumentManager, type DocumentPermissionHint, DocumentResolutionError, type DumpOptions, type DumpSummary, type DumpSummaryEntry, type FieldOptions, type IncludeSpec, type InferAttrs, type InitJsBaoOptions, type InitJsBaoResult, LogLevel, Logger, type ModelConstructor, type ModelOptions, ModelRegistry, type PaginatedResult, type PaginationOptions, type PlainYDoc, type ProjectionSpec, type QueryOptions, type QueryResult, RecordNotFoundError, type SaveOptions, StringSet, UniqueConstraintViolationError, attachAndRegisterModel, attachSchemaToClass, autoRegisterModel, buildUniqueKey, clearMetaSyncCache, createModelClass, defineModelSchema, discoverModelNames, discoverSchema, dumpYDocToPlain, fieldUniqueConstraintName, generateULID, inferFieldType, initJsBao, loadSchemaFromToml, loadSchemaFromTomlString, registerFunctionDefault, resetJsBao, schemaToToml, summarizePlainYDoc, syncInferredMeta, syncModelMeta, uniqueIndexMapName };
package/dist/index.d.ts CHANGED
@@ -698,6 +698,27 @@ declare class BaseModel implements StringSetChangeTracker {
698
698
  */
699
699
  static count(this: new (...args: any[]) => any, filter?: DocumentFilter, options?: Pick<QueryOptions, "documents">): Promise<number>;
700
700
  static findAll<T extends BaseModel>(this: new (...args: any[]) => T): Promise<T[]>;
701
+ /**
702
+ * Resolve a record by its unique-constraint field values via an engine query.
703
+ * Used as a fallback when the `_uniqueIdx_<model>_<constraint>` map has no
704
+ * entry for a key.
705
+ *
706
+ * The index map is a cache over the SQLite projection, not the source of
707
+ * truth: every record is loaded into the projection on `initializeForDocument`
708
+ * regardless of index presence, but a record written by a client predating
709
+ * index maintenance (legacy data) is missing from the index. Such a record
710
+ * silently escapes both `upsertByUnique` lookups and the `save()` uniqueness
711
+ * check. A query over the constraint fields finds it reliably.
712
+ *
713
+ * Contract: RESOLVE ONLY. Returns the owning record (with `_metaDocId` set to
714
+ * the document that holds it, via `queryOne`) or `null`. Callers decide
715
+ * whether to heal the missing index entry (write paths) and do their own
716
+ * logging — this method never mutates the index, so read paths stay
717
+ * read-only. Mirrors `buildUniqueKey`: a null/undefined value in any
718
+ * constraint field means the record does not participate in the constraint,
719
+ * so no query runs.
720
+ */
721
+ private static _resolveByUniqueFallback;
701
722
  static findByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, value: any | any[]): Promise<T | null>;
702
723
  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">> & {
703
724
  id?: string;
@@ -1002,6 +1023,41 @@ declare function discoverModelNames(yDoc: Y.Doc): string[];
1002
1023
  */
1003
1024
  declare function schemaToToml(schema: DiscoveredSchema): string;
1004
1025
 
1026
+ /**
1027
+ * Unique-constraint index helpers (shared CRDT contract).
1028
+ *
1029
+ * js-bao enforces unique constraints inside the Yjs document, not via a SQL
1030
+ * `UNIQUE`. Each constraint has a `_uniqueIdx_<model>_<constraint>` map
1031
+ * (uniqueKey -> surviving recordId) and a document observer that
1032
+ * deterministically discards duplicate losers. Both the client write path and
1033
+ * the server-direct write path (`mutateRecord` in js-bao-wss) must derive the
1034
+ * key and the index map name the SAME way, or a server-written record would
1035
+ * not be seen by the client-side resolver. These helpers are the single source
1036
+ * of truth for that derivation so neither side keeps a parallel copy.
1037
+ */
1038
+
1039
+ /**
1040
+ * Build the unique-constraint key for a record over the given fields.
1041
+ *
1042
+ * Mirrors the document-observer conflict resolver: a `null`/`undefined` value
1043
+ * in any field means the record does not participate in the constraint (returns
1044
+ * `null`); otherwise the per-field `String()` values joined by `"|"`. This is
1045
+ * the key the `_uniqueIdx_*` map is read/written with during conflict
1046
+ * resolution, so it is the key the resolver treats as authoritative.
1047
+ */
1048
+ declare function buildUniqueKey(recordData: Y.Map<any> | Record<string, any>, fields: string[]): string | null;
1049
+ /**
1050
+ * Name of the Yjs map that indexes a unique constraint within a document:
1051
+ * `_uniqueIdx_<model>_<constraint>` mapping uniqueKey -> surviving recordId.
1052
+ */
1053
+ declare function uniqueIndexMapName(modelName: string, constraintName: string): string;
1054
+ /**
1055
+ * The constraint name js-bao assigns to a single-field `unique: true` field
1056
+ * (see `resolveUniqueConstraints` in models/schema.ts). Compound constraints
1057
+ * keep their author-given name instead.
1058
+ */
1059
+ declare function fieldUniqueConstraintName(modelName: string, fieldName: string): string;
1060
+
1005
1061
  interface DumpOptions {
1006
1062
  includeIndexes?: boolean;
1007
1063
  }
@@ -1038,4 +1094,4 @@ declare function dumpYDocToPlain(yDoc: Y.Doc, options?: DumpOptions): PlainYDoc;
1038
1094
  */
1039
1095
  declare function summarizePlainYDoc(dump: PlainYDoc): DumpSummary;
1040
1096
 
1041
- export { BaseModel, type ConnectedDocument, type DatabaseConfig, DatabaseEngine, type DiscoveredConstraint, type DiscoveredField, type DiscoveredModel, type DiscoveredRelationship, type DiscoveredSchema, DocumentClosedError, type DocumentConnectionCallback, type DocumentConnectionEvent, type DocumentFilter, type DocumentManager, type DocumentPermissionHint, DocumentResolutionError, type DumpOptions, type DumpSummary, type DumpSummaryEntry, type FieldOptions, type IncludeSpec, type InferAttrs, type InitJsBaoOptions, type InitJsBaoResult, LogLevel, Logger, type ModelConstructor, type ModelOptions, ModelRegistry, type PaginatedResult, type PaginationOptions, type PlainYDoc, type ProjectionSpec, type QueryOptions, type QueryResult, RecordNotFoundError, type SaveOptions, StringSet, UniqueConstraintViolationError, attachAndRegisterModel, attachSchemaToClass, autoRegisterModel, clearMetaSyncCache, createModelClass, defineModelSchema, discoverModelNames, discoverSchema, dumpYDocToPlain, generateULID, inferFieldType, initJsBao, loadSchemaFromToml, loadSchemaFromTomlString, registerFunctionDefault, resetJsBao, schemaToToml, summarizePlainYDoc, syncInferredMeta, syncModelMeta };
1097
+ export { BaseModel, type ConnectedDocument, type DatabaseConfig, DatabaseEngine, type DiscoveredConstraint, type DiscoveredField, type DiscoveredModel, type DiscoveredRelationship, type DiscoveredSchema, DocumentClosedError, type DocumentConnectionCallback, type DocumentConnectionEvent, type DocumentFilter, type DocumentManager, type DocumentPermissionHint, DocumentResolutionError, type DumpOptions, type DumpSummary, type DumpSummaryEntry, type FieldOptions, type IncludeSpec, type InferAttrs, type InitJsBaoOptions, type InitJsBaoResult, LogLevel, Logger, type ModelConstructor, type ModelOptions, ModelRegistry, type PaginatedResult, type PaginationOptions, type PlainYDoc, type ProjectionSpec, type QueryOptions, type QueryResult, RecordNotFoundError, type SaveOptions, StringSet, UniqueConstraintViolationError, attachAndRegisterModel, attachSchemaToClass, autoRegisterModel, buildUniqueKey, clearMetaSyncCache, createModelClass, defineModelSchema, discoverModelNames, discoverSchema, dumpYDocToPlain, fieldUniqueConstraintName, generateULID, inferFieldType, initJsBao, loadSchemaFromToml, loadSchemaFromTomlString, registerFunctionDefault, resetJsBao, schemaToToml, summarizePlainYDoc, syncInferredMeta, syncModelMeta, uniqueIndexMapName };