@rebasepro/server-mongo 0.16.0 → 0.16.1-canary.g0d7af95

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,8 +1,8 @@
1
1
  import { Db, MongoClient } from "mongodb";
2
2
  import type { BackendBootstrapper } from "@rebasepro/types";
3
- import { MongoDriver } from "./services/MongoDriver";
4
- import { MongoRealtimeService } from "./services/MongoRealtimeService";
5
- import { MongoCollectionRegistry } from "./factory";
3
+ import { MongoDriver } from "./services/MongoDriver.js";
4
+ import { MongoRealtimeService } from "./services/MongoRealtimeService.js";
5
+ import { MongoCollectionRegistry } from "./factory.js";
6
6
  export interface MongoDriverConfig {
7
7
  connection: Db;
8
8
  client: MongoClient;
package/dist/factory.d.ts CHANGED
@@ -6,10 +6,10 @@
6
6
  */
7
7
  import { Db, MongoClient } from "mongodb";
8
8
  import { DataDriver, CollectionConfig } from "@rebasepro/types";
9
- import { MongoDataService } from "./db/MongoDataService";
10
- import { MongoRealtimeService } from "./services/MongoRealtimeService";
11
- import { MongoDriver } from "./services/MongoDriver";
12
- import { MongoHistoryService, HistoryRetentionConfig } from "./services/MongoHistoryService";
9
+ import { MongoDataService } from "./db/MongoDataService.js";
10
+ import { MongoRealtimeService } from "./services/MongoRealtimeService.js";
11
+ import { MongoDriver } from "./services/MongoDriver.js";
12
+ import { MongoHistoryService, HistoryRetentionConfig } from "./services/MongoHistoryService.js";
13
13
  import { BackendConfig, BackendInstance, CollectionRegistryInterface, DataRepository, DatabaseAdmin } from "@rebasepro/types";
14
14
  /**
15
15
  * Configuration for creating a MongoDB backend.
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAyB,MAAM,kBAAkB,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAE7F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,2BAA2B,EAAE,cAAc,EAAwC,aAAa,EAAiD,MAAM,kBAAkB,CAAC;AAEnN;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACrD,IAAI,EAAE,SAAS,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,EAAE,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IACzD,oCAAoC;IACpC,EAAE,EAAE,EAAE,CAAC;IACP,yBAAyB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,MAAM,EAAE,UAAU,CAAC;IACnB,oDAAoD;IACpD,WAAW,EAAE,gBAAgB,CAAC;IAC9B,yCAAyC;IACzC,eAAe,EAAE,oBAAoB,CAAC;IACtC,uDAAuD;IACvD,KAAK,EAAE,aAAa,CAAC;CACxB;AAMD;;GAEG;AACH,qBAAa,uBAAwB,YAAW,2BAA2B;IACvE,gEAAgE;IAChE,OAAO,CAAC,WAAW,CAAuC;IAC1D,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,gBAAgB,CAAC,CAAM;IAE/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAO5C;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/D;;OAEG;IACH,cAAc,IAAI,gBAAgB,EAAE;IAIpC;;OAEG;IACH,kBAAkB,IAAI,GAAG,GAAG,SAAS;IAIrC;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;CAG3C;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,oBAAoB,CAgGnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,EAAE,EACN,eAAe,CAAC,EAAE,oBAAoB,EACtC,cAAc,CAAC,EAAE,mBAAmB,EACpC,QAAQ,CAAC,EAAE,2BAA2B,GACvC,WAAW,CAIb;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,EAAE,GAAG,oBAAoB,CAEvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,CAElE;AAMD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,kBAAkB,CAIxF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAOjH"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAyB,MAAM,kBAAkB,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAE7F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,2BAA2B,EAAE,cAAc,EAAwC,aAAa,EAAqE,MAAM,kBAAkB,CAAC;AAGvO;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACrD,IAAI,EAAE,SAAS,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,EAAE,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IACzD,oCAAoC;IACpC,EAAE,EAAE,EAAE,CAAC;IACP,yBAAyB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,MAAM,EAAE,UAAU,CAAC;IACnB,oDAAoD;IACpD,WAAW,EAAE,gBAAgB,CAAC;IAC9B,yCAAyC;IACzC,eAAe,EAAE,oBAAoB,CAAC;IACtC,uDAAuD;IACvD,KAAK,EAAE,aAAa,CAAC;CACxB;AAMD;;GAEG;AACH,qBAAa,uBAAwB,YAAW,2BAA2B;IACvE,gEAAgE;IAChE,OAAO,CAAC,WAAW,CAAuC;IAC1D,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,gBAAgB,CAAC,CAAM;IAE/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAO5C;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/D;;OAEG;IACH,cAAc,IAAI,gBAAgB,EAAE;IAIpC;;OAEG;IACH,kBAAkB,IAAI,GAAG,GAAG,SAAS;IAIrC;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;CAG3C;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,oBAAoB,CA4GnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,EAAE,EACN,eAAe,CAAC,EAAE,oBAAoB,EACtC,cAAc,CAAC,EAAE,mBAAmB,EACpC,QAAQ,CAAC,EAAE,2BAA2B,GACvC,WAAW,CAIb;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,EAAE,GAAG,oBAAoB,CAEvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,CAElE;AAMD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,kBAAkB,CAIxF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAOjH"}
package/dist/index.d.ts CHANGED
@@ -8,11 +8,11 @@
8
8
  * The package implements the abstract interfaces from @rebasepro/server
9
9
  * (DataRepository, RealtimeProvider, CollectionRegistryInterface, etc.)
10
10
  */
11
- export * from "./connection";
12
- export * from "./factory";
13
- export * from "./db/MongoDataService";
14
- export * from "./db/MongoConditionBuilder";
15
- export * from "./services/MongoRealtimeService";
16
- export * from "./services/MongoDriver";
17
- export * from "./MongoBootstrapper";
11
+ export * from "./connection.js";
12
+ export * from "./factory.js";
13
+ export * from "./db/MongoDataService.js";
14
+ export * from "./db/MongoConditionBuilder.js";
15
+ export * from "./services/MongoRealtimeService.js";
16
+ export * from "./services/MongoDriver.js";
17
+ export * from "./MongoBootstrapper.js";
18
18
  //# sourceMappingURL=index.d.ts.map
package/dist/index.es.js CHANGED
@@ -953,21 +953,14 @@ var MongoHistoryService = class {
953
953
  }
954
954
  async pruneHistory(id, tableName) {
955
955
  const collection = this.db.collection("__rebase_history");
956
- const count = await collection.countDocuments({
956
+ const surplus = await collection.find({
957
957
  entity_id: id,
958
958
  table_name: tableName
959
- });
960
- if (count > this.retention.maxEntries) {
961
- const toDelete = count - this.retention.maxEntries;
962
- const oldestEntries = await collection.find({
963
- entity_id: id,
964
- table_name: tableName
965
- }).sort({ updated_at: 1 }).limit(toDelete).toArray();
966
- if (oldestEntries.length > 0) {
967
- const idsToDelete = oldestEntries.map((entry) => entry._id);
968
- await collection.deleteMany({ _id: { $in: idsToDelete } });
969
- }
970
- }
959
+ }).sort({
960
+ updated_at: -1,
961
+ _id: -1
962
+ }).skip(this.retention.maxEntries).toArray();
963
+ if (surplus.length > 0) await collection.deleteMany({ _id: { $in: surplus.map((entry) => entry._id) } });
971
964
  const cutoffDate = /* @__PURE__ */ new Date();
972
965
  cutoffDate.setDate(cutoffDate.getDate() - this.retention.ttlDays);
973
966
  await collection.deleteMany({
@@ -1892,6 +1885,98 @@ function rowToEntityForCheck(row, path) {
1892
1885
  };
1893
1886
  }
1894
1887
  //#endregion
1888
+ //#region src/schema/plan-schema-change.ts
1889
+ var bySlug = (collections) => {
1890
+ const map = /* @__PURE__ */ new Map();
1891
+ for (const collection of collections) if (collection.slug) map.set(collection.slug, collection);
1892
+ return map;
1893
+ };
1894
+ var propertiesOf = (collection) => collection.properties ?? {};
1895
+ /**
1896
+ * What changed, in the terms a document database makes true.
1897
+ *
1898
+ * Exported because it is the interesting half and worth testing without a
1899
+ * driver: the shape of the answer is the product, and the rest is plumbing.
1900
+ */
1901
+ function classifyMongoChanges(before, after) {
1902
+ const previous = bySlug(before);
1903
+ const next = bySlug(after);
1904
+ const changes = [];
1905
+ for (const [slug, collection] of next) {
1906
+ if (!previous.has(slug)) {
1907
+ changes.push({
1908
+ kind: "add-collection",
1909
+ verdict: "safe",
1910
+ collection: slug,
1911
+ detail: `New collection "${slug}". MongoDB creates it on the first write; nothing is created now.`
1912
+ });
1913
+ continue;
1914
+ }
1915
+ const oldProps = propertiesOf(previous.get(slug));
1916
+ const newProps = propertiesOf(collection);
1917
+ for (const name of Object.keys(newProps)) {
1918
+ if (name in oldProps) continue;
1919
+ changes.push({
1920
+ kind: "add-property",
1921
+ verdict: "safe",
1922
+ collection: slug,
1923
+ property: name,
1924
+ detail: `New property "${name}". Existing documents do not have it and are not rewritten; reads return it as absent until something writes it.`
1925
+ });
1926
+ }
1927
+ for (const name of Object.keys(oldProps)) {
1928
+ if (name in newProps) continue;
1929
+ changes.push({
1930
+ kind: "remove-property",
1931
+ verdict: "safe",
1932
+ collection: slug,
1933
+ property: name,
1934
+ detail: `"${name}" is no longer served. Documents that have it keep it — MongoDB stores no schema, so nothing is removed from the data.`
1935
+ });
1936
+ }
1937
+ }
1938
+ for (const [slug] of previous) {
1939
+ if (next.has(slug)) continue;
1940
+ changes.push({
1941
+ kind: "remove-collection",
1942
+ verdict: "safe",
1943
+ collection: slug,
1944
+ detail: `Collection "${slug}" is no longer served. The MongoDB collection and every document in it are left exactly as they are.`
1945
+ });
1946
+ }
1947
+ return changes;
1948
+ }
1949
+ /** A commit message that says what changed rather than that something did. */
1950
+ function commitMessage(changes) {
1951
+ if (changes.length === 0) return "chore(schema): no change";
1952
+ const collections = [...new Set(changes.map((c) => c.collection))].sort();
1953
+ const added = changes.filter((c) => c.kind === "add-collection");
1954
+ const properties = changes.filter((c) => c.kind === "add-property");
1955
+ return `feat(schema): ${added.length === 1 && changes.length === 1 ? `add the ${added[0].collection} collection` : properties.length === 1 && changes.length === 1 ? `add ${properties[0].property} to ${properties[0].collection}` : collections.length === 1 ? `${changes.length} change(s) to ${collections[0]}` : `${changes.length} change(s) across ${collections.length} collections`}\n\n${changes.map((c) => `- ${c.detail}`).join("\n")}\n`;
1956
+ }
1957
+ /**
1958
+ * The plan: a commit, and nothing to run.
1959
+ *
1960
+ * `files` is empty here and filled by the caller with the rewritten collection
1961
+ * source. Postgres adds generated artifacts — a Drizzle schema, declarative
1962
+ * DDL — because a stale one breaks the next deploy. MongoDB generates none, so
1963
+ * the collection file is the whole of the change.
1964
+ */
1965
+ async function planMongoSchemaChange(before, after) {
1966
+ const changes = classifyMongoChanges(before, after);
1967
+ return {
1968
+ files: [],
1969
+ statements: [],
1970
+ classified: {
1971
+ changes,
1972
+ verdict: "safe",
1973
+ applicable: true
1974
+ },
1975
+ message: commitMessage(changes),
1976
+ withheldConstraints: []
1977
+ };
1978
+ }
1979
+ //#endregion
1895
1980
  //#region src/factory.ts
1896
1981
  /**
1897
1982
  * Simple in-memory collection registry for MongoDB.
@@ -1987,6 +2072,7 @@ function createMongoBackend(config) {
1987
2072
  realtimeProvider: realtimeService,
1988
2073
  collectionRegistry,
1989
2074
  admin: {
2075
+ planSchemaChange: async (before, after) => planMongoSchemaChange(before, after),
1990
2076
  async executeAggregate(pipeline) {
1991
2077
  const firstStage = pipeline[0];
1992
2078
  const collName = typeof firstStage.$from === "string" ? firstStage.$from : "__admin__";