@monlite/core 0.8.0 → 0.9.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/README.md CHANGED
@@ -525,6 +525,31 @@ db.driverName; // "better-sqlite3" | "node:sqlite"
525
525
 
526
526
  ---
527
527
 
528
+ ## Plugins
529
+
530
+ `@monlite/core` stays lean; heavier or optional capabilities are opt-in plugins
531
+ passed to `createDb`:
532
+
533
+ ```ts
534
+ import { createDb } from "@monlite/core";
535
+ import { fts } from "@monlite/fts";
536
+
537
+ const db = createDb("./app.db", {
538
+ plugins: [fts({ posts: ["title", "body"] })],
539
+ });
540
+
541
+ await db.collection("posts").search("hello world"); // full-text search
542
+ ```
543
+
544
+ | Plugin | Adds |
545
+ |---|---|
546
+ | [`@monlite/fts`](https://www.npmjs.com/package/@monlite/fts) | Full-text search (SQLite FTS5) via `collection.search()` |
547
+
548
+ Write your own against the `MonlitePlugin` interface (`init` / `afterWrite` /
549
+ `collectionMethods` hooks).
550
+
551
+ ---
552
+
528
553
  ## Drivers & zero dependencies
529
554
 
530
555
  monlite talks to SQLite through a tiny driver adapter, so it runs on two
package/dist/index.cjs CHANGED
@@ -952,9 +952,11 @@ var Collection = class {
952
952
  ).run(...values);
953
953
  this.afterWrite([id]);
954
954
  }
955
- /** @internal Notify reactivity watchers that documents changed. */
955
+ /** @internal Notify reactivity watchers and plugins that documents changed. */
956
956
  afterWrite(ids) {
957
+ if (ids.length === 0) return;
957
958
  this.mon.reactor.emit(this.name, ids);
959
+ this.mon.firePluginAfterWrite(this.name, ids);
958
960
  }
959
961
  /* ----------------------------- create ----------------------------- */
960
962
  async create(args) {
@@ -1888,6 +1890,7 @@ var Monlite = class {
1888
1890
  /** @internal Sync metadata store; present only when `{ sync: true }`. */
1889
1891
  $sync;
1890
1892
  collections = /* @__PURE__ */ new Map();
1893
+ plugins;
1891
1894
  closed = false;
1892
1895
  constructor(filename, options = {}) {
1893
1896
  this.driver = createDriver(filename, {
@@ -1905,6 +1908,15 @@ var Monlite = class {
1905
1908
  if (options.sync) {
1906
1909
  this.$sync = new SyncStore(this.driver, options.nodeId, this);
1907
1910
  }
1911
+ this.plugins = options.plugins ?? [];
1912
+ for (const plugin of this.plugins) plugin.init?.(this);
1913
+ }
1914
+ /** @internal Notify plugins that documents changed (post-commit). */
1915
+ firePluginAfterWrite(collection, ids) {
1916
+ if (this.plugins.length === 0 || ids.length === 0) return;
1917
+ for (const plugin of this.plugins) {
1918
+ plugin.afterWrite?.(this, { collection, ids });
1919
+ }
1908
1920
  }
1909
1921
  /** Stable node id for LWW tie-breaking (only when sync is enabled). */
1910
1922
  get nodeId() {
@@ -1930,6 +1942,13 @@ var Monlite = class {
1930
1942
  if (!col) {
1931
1943
  col = new Collection(this, name, options);
1932
1944
  this.collections.set(name, col);
1945
+ for (const plugin of this.plugins) {
1946
+ for (const [method, impl] of Object.entries(
1947
+ plugin.collectionMethods ?? {}
1948
+ )) {
1949
+ col[method] = (...args) => impl(col, ...args);
1950
+ }
1951
+ }
1933
1952
  } else if (options?.schema) {
1934
1953
  const requested = Object.keys(options.schema);
1935
1954
  const existing = new Set(col.columnNames);