@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.
- package/dist/MongoBootstrapper.d.ts +3 -3
- package/dist/factory.d.ts +4 -4
- package/dist/factory.d.ts.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.es.js +99 -13
- package/dist/index.es.js.map +1 -1
- package/dist/schema/plan-schema-change.d.ts +49 -0
- package/dist/schema/plan-schema-change.d.ts.map +1 -0
- package/dist/services/MongoDriver.d.ts +3 -3
- package/dist/services/MongoHistoryService.d.ts.map +1 -1
- package/dist/services/MongoRealtimeService.d.ts +1 -1
- package/dist/websocket.d.ts +2 -2
- package/package.json +6 -6
- package/src/factory.ts +15 -2
- package/src/schema/plan-schema-change.ts +159 -0
- package/src/services/MongoHistoryService.ts +28 -13
|
@@ -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.
|
package/dist/factory.d.ts.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
|
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
|
|
956
|
+
const surplus = await collection.find({
|
|
957
957
|
entity_id: id,
|
|
958
958
|
table_name: tableName
|
|
959
|
-
})
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
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__";
|