@monlite/core 0.5.0 → 0.7.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/index.d.cts CHANGED
@@ -67,6 +67,11 @@ interface FieldFilter<V = any> {
67
67
  has?: any;
68
68
  /** Field presence. `true` requires the field to exist, `false` requires absence. */
69
69
  exists?: boolean;
70
+ /**
71
+ * Case sensitivity for `contains`/`startsWith`/`endsWith`. Default is
72
+ * case-sensitive; `"insensitive"` matches case-insensitively (ASCII).
73
+ */
74
+ mode?: "default" | "insensitive";
70
75
  }
71
76
  /** A value used directly as a filter is shorthand for `{ equals: value }`. */
72
77
  type FilterInput<V> = V | FieldFilter<V>;
@@ -220,6 +225,8 @@ interface MonliteOptions {
220
225
  readonly?: boolean;
221
226
  /** Use SQLite WAL journal mode for better concurrency. Default `true`. */
222
227
  wal?: boolean;
228
+ /** Milliseconds to wait on a locked database before erroring. Default `5000`. */
229
+ busyTimeout?: number;
223
230
  /** Verbose logger for executed SQL (debugging). */
224
231
  verbose?: (sql: string) => void;
225
232
  }
@@ -245,6 +252,8 @@ declare class Collection<T = Doc> {
245
252
  private readonly trackPath;
246
253
  constructor(mon: Monlite, name: string, options?: CollectionOptions);
247
254
  private get db();
255
+ /** Run a DB operation, normalizing driver errors into typed MonliteErrors. */
256
+ private guard;
248
257
  /** Native column names declared for this collection (structured mode). */
249
258
  get columnNames(): string[];
250
259
  private ensureTable;
@@ -256,14 +265,29 @@ declare class Collection<T = Doc> {
256
265
  private buildInsert;
257
266
  /** Build the `SET` clause + values to persist an updated document. */
258
267
  private buildUpdateSet;
259
- /** Sync store, but only for document collections (structured sync is future work). */
268
+ /** Sync store for recording local changes (both document and structured). */
260
269
  private get recorder();
270
+ /** @internal Read a full document by id (mode-aware), synchronously. */
271
+ getRaw(id: string): WithId<T> | null;
272
+ /**
273
+ * @internal Apply a remote change to storage WITHOUT recording it to the
274
+ * change feed (the sync store records the `remote` feed row itself). Used by
275
+ * `@monlite/sync` so structured collections sync correctly through the same
276
+ * column/overflow split as local writes.
277
+ */
278
+ applyRemoteWrite(op: "upsert" | "delete", id: string, doc: Record<string, any> | undefined, ts: number): void;
261
279
  create(args: CreateArgs<T>): Promise<WithId<T>>;
262
280
  createMany(args: CreateManyArgs<T>): Promise<{
263
281
  count: number;
264
282
  }>;
265
283
  findMany(args?: FindManyArgs<T>): Promise<WithId<T>[]>;
266
284
  findFirst(args?: FindFirstArgs<T>): Promise<WithId<T> | null>;
285
+ /** Alias of {@link findFirst} for Prisma familiarity. */
286
+ findUnique(args?: FindFirstArgs<T>): Promise<WithId<T> | null>;
287
+ /** Like {@link findFirst} but throws if no document matches. */
288
+ findFirstOrThrow(args?: FindFirstArgs<T>): Promise<WithId<T>>;
289
+ /** True if at least one document matches. */
290
+ exists(where?: WhereInput<T>): Promise<boolean>;
267
291
  findById(id: string): Promise<WithId<T> | null>;
268
292
  count(args?: CountArgs<T>): Promise<number>;
269
293
  /**
@@ -338,7 +362,12 @@ declare class AutoIndexer {
338
362
  * the on-disk column is a plain string, so the format can evolve.)
339
363
  */
340
364
  type Version = string;
341
- declare function makeVersion(ts: number, nodeId: string): Version;
365
+ /**
366
+ * Build a version token. The optional `seq` is a per-node monotonic counter
367
+ * that makes versions unique even within the same millisecond — important so
368
+ * that cursor-based pulls (`> version`) never skip a same-timestamp change.
369
+ */
370
+ declare function makeVersion(ts: number, nodeId: string, seq?: number): Version;
342
371
  declare function compareVersions(a: Version, b: Version): number;
343
372
  declare function versionTs(v: Version): number;
344
373
 
@@ -401,8 +430,10 @@ interface ConflictRow {
401
430
  */
402
431
  declare class SyncStore {
403
432
  private readonly db;
433
+ private readonly mon?;
404
434
  readonly nodeId: string;
405
- constructor(db: Driver, nodeId?: string);
435
+ private versionSeq;
436
+ constructor(db: Driver, nodeId?: string, mon?: Monlite | undefined);
406
437
  private init;
407
438
  private resolveNodeId;
408
439
  /** True if this database tracks sync metadata (always, once constructed). */
@@ -412,7 +443,7 @@ declare class SyncStore {
412
443
  /** Current (latest) version of a document, or null if never recorded. */
413
444
  currentVersion(collection: string, id: string): Version | null;
414
445
  /** Latest unpushed local change per document (the push queue). */
415
- pending(collections?: string[]): LocalChange[];
446
+ pending(collections?: string[], limit?: number): LocalChange[];
416
447
  /** Mark the given changes (and any earlier local rows per doc) as pushed. */
417
448
  markPushed(changes: LocalChange[]): void;
418
449
  /**
@@ -427,7 +458,7 @@ declare class SyncStore {
427
458
  * as RemoteChanges (used when this database acts as a sync *source*, e.g. the
428
459
  * monlite-as-remote adapter). Returns the new watermark to resume from.
429
460
  */
430
- changesSince(seq: number, collections?: string[]): {
461
+ changesSince(seq: number, collections?: string[], limit?: number): {
431
462
  changes: RemoteChange[];
432
463
  maxSeq: number;
433
464
  };
@@ -441,6 +472,7 @@ declare class SyncStore {
441
472
  private recordConflict;
442
473
  conflicts(): ConflictRow[];
443
474
  private readDoc;
475
+ private tableExists;
444
476
  private ensureCollTable;
445
477
  }
446
478
 
@@ -503,15 +535,54 @@ declare function createDb(filename: string, options?: MonliteOptions): Monlite;
503
535
 
504
536
  /** Base error for all monlite-originated failures. */
505
537
  declare class MonliteError extends Error {
506
- constructor(message: string);
538
+ constructor(message: string, options?: {
539
+ cause?: unknown;
540
+ });
507
541
  }
508
542
  /** Thrown when a query/update payload is malformed. */
509
543
  declare class MonliteQueryError extends MonliteError {
510
- constructor(message: string);
544
+ constructor(message: string, options?: {
545
+ cause?: unknown;
546
+ });
547
+ }
548
+ /** A database constraint was violated (base class for the specific kinds). */
549
+ declare class MonliteConstraintError extends MonliteError {
550
+ readonly collection?: string;
551
+ constructor(message: string, options?: {
552
+ cause?: unknown;
553
+ collection?: string;
554
+ });
555
+ }
556
+ /** A UNIQUE (or primary-key) constraint was violated. */
557
+ declare class MonliteUniqueConstraintError extends MonliteConstraintError {
558
+ constructor(message: string, options?: {
559
+ cause?: unknown;
560
+ collection?: string;
561
+ });
562
+ }
563
+ /** A NOT NULL constraint was violated. */
564
+ declare class MonliteNotNullError extends MonliteConstraintError {
565
+ constructor(message: string, options?: {
566
+ cause?: unknown;
567
+ collection?: string;
568
+ });
569
+ }
570
+ /** A FOREIGN KEY constraint was violated. */
571
+ declare class MonliteForeignKeyError extends MonliteConstraintError {
572
+ constructor(message: string, options?: {
573
+ cause?: unknown;
574
+ collection?: string;
575
+ });
511
576
  }
577
+ /**
578
+ * Normalize a raw driver error (better-sqlite3 `SqliteError` or node:sqlite
579
+ * error) into a typed {@link MonliteError}. The two backends differ in error
580
+ * shape, so we sniff both the `code` and the message text.
581
+ */
582
+ declare function normalizeDriverError(err: unknown, collection?: string): MonliteError;
512
583
 
513
584
  declare function objectId(): string;
514
585
  /** True when a value looks like a monlite/ObjectId id (24 hex chars). */
515
586
  declare function isObjectId(value: unknown): value is string;
516
587
 
517
- export { type AggregateArgs, type AggregateResult, type ApplyResult, Collection, type CollectionMode, type CollectionOptions, type CollectionSchema, type ColumnDef, type ColumnInfo, type ColumnType, type ConflictResolver, type ConflictRow, type CountArgs, type CreateArgs, type CreateManyArgs, Monlite as Db, type DeleteArgs, type Doc, type Driver, type DriverName, type FieldFilter, type FieldSelection, type FilterInput, type FindFirstArgs, type FindManyArgs, type GroupByArgs, type GroupByResult, type HavingComparison, type HavingInput, type LocalChange, Monlite, MonliteError, type MonliteOptions, MonliteQueryError, type OrderBy, type PreparedStatement, type RemoteChange, type Select, type SortOrder, type SyncOp, type SyncStateRow, SyncStore, type SystemFields, type UpdateArgs, type UpdateData, type UpdateOperators, type UpsertArgs, type Version, type WhereInput as WhereClause, type WhereInput, type WithId, compareVersions, createDb, isObjectId, makeVersion, objectId, versionTs };
588
+ export { type AggregateArgs, type AggregateResult, type ApplyResult, Collection, type CollectionMode, type CollectionOptions, type CollectionSchema, type ColumnDef, type ColumnInfo, type ColumnType, type ConflictResolver, type ConflictRow, type CountArgs, type CreateArgs, type CreateManyArgs, Monlite as Db, type DeleteArgs, type Doc, type Driver, type DriverName, type FieldFilter, type FieldSelection, type FilterInput, type FindFirstArgs, type FindManyArgs, type GroupByArgs, type GroupByResult, type HavingComparison, type HavingInput, type LocalChange, Monlite, MonliteConstraintError, MonliteError, MonliteForeignKeyError, MonliteNotNullError, type MonliteOptions, MonliteQueryError, MonliteUniqueConstraintError, type OrderBy, type PreparedStatement, type RemoteChange, type Select, type SortOrder, type SyncOp, type SyncStateRow, SyncStore, type SystemFields, type UpdateArgs, type UpdateData, type UpdateOperators, type UpsertArgs, type Version, type WhereInput as WhereClause, type WhereInput, type WithId, compareVersions, createDb, isObjectId, makeVersion, normalizeDriverError, objectId, versionTs };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,11 @@ interface FieldFilter<V = any> {
67
67
  has?: any;
68
68
  /** Field presence. `true` requires the field to exist, `false` requires absence. */
69
69
  exists?: boolean;
70
+ /**
71
+ * Case sensitivity for `contains`/`startsWith`/`endsWith`. Default is
72
+ * case-sensitive; `"insensitive"` matches case-insensitively (ASCII).
73
+ */
74
+ mode?: "default" | "insensitive";
70
75
  }
71
76
  /** A value used directly as a filter is shorthand for `{ equals: value }`. */
72
77
  type FilterInput<V> = V | FieldFilter<V>;
@@ -220,6 +225,8 @@ interface MonliteOptions {
220
225
  readonly?: boolean;
221
226
  /** Use SQLite WAL journal mode for better concurrency. Default `true`. */
222
227
  wal?: boolean;
228
+ /** Milliseconds to wait on a locked database before erroring. Default `5000`. */
229
+ busyTimeout?: number;
223
230
  /** Verbose logger for executed SQL (debugging). */
224
231
  verbose?: (sql: string) => void;
225
232
  }
@@ -245,6 +252,8 @@ declare class Collection<T = Doc> {
245
252
  private readonly trackPath;
246
253
  constructor(mon: Monlite, name: string, options?: CollectionOptions);
247
254
  private get db();
255
+ /** Run a DB operation, normalizing driver errors into typed MonliteErrors. */
256
+ private guard;
248
257
  /** Native column names declared for this collection (structured mode). */
249
258
  get columnNames(): string[];
250
259
  private ensureTable;
@@ -256,14 +265,29 @@ declare class Collection<T = Doc> {
256
265
  private buildInsert;
257
266
  /** Build the `SET` clause + values to persist an updated document. */
258
267
  private buildUpdateSet;
259
- /** Sync store, but only for document collections (structured sync is future work). */
268
+ /** Sync store for recording local changes (both document and structured). */
260
269
  private get recorder();
270
+ /** @internal Read a full document by id (mode-aware), synchronously. */
271
+ getRaw(id: string): WithId<T> | null;
272
+ /**
273
+ * @internal Apply a remote change to storage WITHOUT recording it to the
274
+ * change feed (the sync store records the `remote` feed row itself). Used by
275
+ * `@monlite/sync` so structured collections sync correctly through the same
276
+ * column/overflow split as local writes.
277
+ */
278
+ applyRemoteWrite(op: "upsert" | "delete", id: string, doc: Record<string, any> | undefined, ts: number): void;
261
279
  create(args: CreateArgs<T>): Promise<WithId<T>>;
262
280
  createMany(args: CreateManyArgs<T>): Promise<{
263
281
  count: number;
264
282
  }>;
265
283
  findMany(args?: FindManyArgs<T>): Promise<WithId<T>[]>;
266
284
  findFirst(args?: FindFirstArgs<T>): Promise<WithId<T> | null>;
285
+ /** Alias of {@link findFirst} for Prisma familiarity. */
286
+ findUnique(args?: FindFirstArgs<T>): Promise<WithId<T> | null>;
287
+ /** Like {@link findFirst} but throws if no document matches. */
288
+ findFirstOrThrow(args?: FindFirstArgs<T>): Promise<WithId<T>>;
289
+ /** True if at least one document matches. */
290
+ exists(where?: WhereInput<T>): Promise<boolean>;
267
291
  findById(id: string): Promise<WithId<T> | null>;
268
292
  count(args?: CountArgs<T>): Promise<number>;
269
293
  /**
@@ -338,7 +362,12 @@ declare class AutoIndexer {
338
362
  * the on-disk column is a plain string, so the format can evolve.)
339
363
  */
340
364
  type Version = string;
341
- declare function makeVersion(ts: number, nodeId: string): Version;
365
+ /**
366
+ * Build a version token. The optional `seq` is a per-node monotonic counter
367
+ * that makes versions unique even within the same millisecond — important so
368
+ * that cursor-based pulls (`> version`) never skip a same-timestamp change.
369
+ */
370
+ declare function makeVersion(ts: number, nodeId: string, seq?: number): Version;
342
371
  declare function compareVersions(a: Version, b: Version): number;
343
372
  declare function versionTs(v: Version): number;
344
373
 
@@ -401,8 +430,10 @@ interface ConflictRow {
401
430
  */
402
431
  declare class SyncStore {
403
432
  private readonly db;
433
+ private readonly mon?;
404
434
  readonly nodeId: string;
405
- constructor(db: Driver, nodeId?: string);
435
+ private versionSeq;
436
+ constructor(db: Driver, nodeId?: string, mon?: Monlite | undefined);
406
437
  private init;
407
438
  private resolveNodeId;
408
439
  /** True if this database tracks sync metadata (always, once constructed). */
@@ -412,7 +443,7 @@ declare class SyncStore {
412
443
  /** Current (latest) version of a document, or null if never recorded. */
413
444
  currentVersion(collection: string, id: string): Version | null;
414
445
  /** Latest unpushed local change per document (the push queue). */
415
- pending(collections?: string[]): LocalChange[];
446
+ pending(collections?: string[], limit?: number): LocalChange[];
416
447
  /** Mark the given changes (and any earlier local rows per doc) as pushed. */
417
448
  markPushed(changes: LocalChange[]): void;
418
449
  /**
@@ -427,7 +458,7 @@ declare class SyncStore {
427
458
  * as RemoteChanges (used when this database acts as a sync *source*, e.g. the
428
459
  * monlite-as-remote adapter). Returns the new watermark to resume from.
429
460
  */
430
- changesSince(seq: number, collections?: string[]): {
461
+ changesSince(seq: number, collections?: string[], limit?: number): {
431
462
  changes: RemoteChange[];
432
463
  maxSeq: number;
433
464
  };
@@ -441,6 +472,7 @@ declare class SyncStore {
441
472
  private recordConflict;
442
473
  conflicts(): ConflictRow[];
443
474
  private readDoc;
475
+ private tableExists;
444
476
  private ensureCollTable;
445
477
  }
446
478
 
@@ -503,15 +535,54 @@ declare function createDb(filename: string, options?: MonliteOptions): Monlite;
503
535
 
504
536
  /** Base error for all monlite-originated failures. */
505
537
  declare class MonliteError extends Error {
506
- constructor(message: string);
538
+ constructor(message: string, options?: {
539
+ cause?: unknown;
540
+ });
507
541
  }
508
542
  /** Thrown when a query/update payload is malformed. */
509
543
  declare class MonliteQueryError extends MonliteError {
510
- constructor(message: string);
544
+ constructor(message: string, options?: {
545
+ cause?: unknown;
546
+ });
547
+ }
548
+ /** A database constraint was violated (base class for the specific kinds). */
549
+ declare class MonliteConstraintError extends MonliteError {
550
+ readonly collection?: string;
551
+ constructor(message: string, options?: {
552
+ cause?: unknown;
553
+ collection?: string;
554
+ });
555
+ }
556
+ /** A UNIQUE (or primary-key) constraint was violated. */
557
+ declare class MonliteUniqueConstraintError extends MonliteConstraintError {
558
+ constructor(message: string, options?: {
559
+ cause?: unknown;
560
+ collection?: string;
561
+ });
562
+ }
563
+ /** A NOT NULL constraint was violated. */
564
+ declare class MonliteNotNullError extends MonliteConstraintError {
565
+ constructor(message: string, options?: {
566
+ cause?: unknown;
567
+ collection?: string;
568
+ });
569
+ }
570
+ /** A FOREIGN KEY constraint was violated. */
571
+ declare class MonliteForeignKeyError extends MonliteConstraintError {
572
+ constructor(message: string, options?: {
573
+ cause?: unknown;
574
+ collection?: string;
575
+ });
511
576
  }
577
+ /**
578
+ * Normalize a raw driver error (better-sqlite3 `SqliteError` or node:sqlite
579
+ * error) into a typed {@link MonliteError}. The two backends differ in error
580
+ * shape, so we sniff both the `code` and the message text.
581
+ */
582
+ declare function normalizeDriverError(err: unknown, collection?: string): MonliteError;
512
583
 
513
584
  declare function objectId(): string;
514
585
  /** True when a value looks like a monlite/ObjectId id (24 hex chars). */
515
586
  declare function isObjectId(value: unknown): value is string;
516
587
 
517
- export { type AggregateArgs, type AggregateResult, type ApplyResult, Collection, type CollectionMode, type CollectionOptions, type CollectionSchema, type ColumnDef, type ColumnInfo, type ColumnType, type ConflictResolver, type ConflictRow, type CountArgs, type CreateArgs, type CreateManyArgs, Monlite as Db, type DeleteArgs, type Doc, type Driver, type DriverName, type FieldFilter, type FieldSelection, type FilterInput, type FindFirstArgs, type FindManyArgs, type GroupByArgs, type GroupByResult, type HavingComparison, type HavingInput, type LocalChange, Monlite, MonliteError, type MonliteOptions, MonliteQueryError, type OrderBy, type PreparedStatement, type RemoteChange, type Select, type SortOrder, type SyncOp, type SyncStateRow, SyncStore, type SystemFields, type UpdateArgs, type UpdateData, type UpdateOperators, type UpsertArgs, type Version, type WhereInput as WhereClause, type WhereInput, type WithId, compareVersions, createDb, isObjectId, makeVersion, objectId, versionTs };
588
+ export { type AggregateArgs, type AggregateResult, type ApplyResult, Collection, type CollectionMode, type CollectionOptions, type CollectionSchema, type ColumnDef, type ColumnInfo, type ColumnType, type ConflictResolver, type ConflictRow, type CountArgs, type CreateArgs, type CreateManyArgs, Monlite as Db, type DeleteArgs, type Doc, type Driver, type DriverName, type FieldFilter, type FieldSelection, type FilterInput, type FindFirstArgs, type FindManyArgs, type GroupByArgs, type GroupByResult, type HavingComparison, type HavingInput, type LocalChange, Monlite, MonliteConstraintError, MonliteError, MonliteForeignKeyError, MonliteNotNullError, type MonliteOptions, MonliteQueryError, MonliteUniqueConstraintError, type OrderBy, type PreparedStatement, type RemoteChange, type Select, type SortOrder, type SyncOp, type SyncStateRow, SyncStore, type SystemFields, type UpdateArgs, type UpdateData, type UpdateOperators, type UpsertArgs, type Version, type WhereInput as WhereClause, type WhereInput, type WithId, compareVersions, createDb, isObjectId, makeVersion, normalizeDriverError, objectId, versionTs };