@atscript/db-mongo 0.1.155 → 0.1.157
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.cjs +52 -5
- package/dist/index.d.cts +5 -3
- package/dist/index.d.mts +5 -3
- package/dist/index.mjs +52 -5
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1770,6 +1770,27 @@ async function dropColumnsImpl(host, columns) {
|
|
|
1770
1770
|
await host.collection.updateMany({}, { $unset: unsetSpec }, host._getSessionOpts());
|
|
1771
1771
|
}
|
|
1772
1772
|
/**
|
|
1773
|
+
* Drops the managed indexes over any of `columns` (or a path under one).
|
|
1774
|
+
* Schema sync calls it before {@link dropColumnsImpl}: a unique index on a
|
|
1775
|
+
* required field indexes a `$unset` document as `null`, so the second one
|
|
1776
|
+
* collides (E11000) — e.g. the old key field's `__pk` index when a `@meta.id`
|
|
1777
|
+
* move removes that field. `syncIndexesImpl` then builds what the model wants.
|
|
1778
|
+
*/
|
|
1779
|
+
async function dropIndexesForColumnsImpl(host, columns) {
|
|
1780
|
+
const dropped = new Set(columns);
|
|
1781
|
+
let existing;
|
|
1782
|
+
try {
|
|
1783
|
+
existing = await host.collection.listIndexes().toArray();
|
|
1784
|
+
} catch (error) {
|
|
1785
|
+
if (error.code === 26) return;
|
|
1786
|
+
throw error;
|
|
1787
|
+
}
|
|
1788
|
+
for (const remote of existing) if (remote.name.startsWith("atscript__") && coversAny(remote.key, remote.weights, dropped)) {
|
|
1789
|
+
host._log("dropIndex", remote.name);
|
|
1790
|
+
await host.collection.dropIndex(remote.name);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
/**
|
|
1773
1794
|
* The segments of a field's physical document path with `$[]` after every
|
|
1774
1795
|
* segment whose logical prefix is an array in the flatMap — Mongo's
|
|
1775
1796
|
* all-positional operator walks every element. `physicalPath` defaults to
|
|
@@ -1803,7 +1824,23 @@ function resolveSyncDefault(field) {
|
|
|
1803
1824
|
if (!field.defaultValue) return;
|
|
1804
1825
|
if (field.defaultValue.kind === "value") return field.designType === "string" ? field.defaultValue.value : JSON.parse(field.defaultValue.value);
|
|
1805
1826
|
}
|
|
1806
|
-
|
|
1827
|
+
/**
|
|
1828
|
+
* Whether an index's fields include one of `paths` or a path under one —
|
|
1829
|
+
* a text index lists its fields in `weights` (its key is `_fts` / `_ftsx`).
|
|
1830
|
+
*/
|
|
1831
|
+
function coversAny(key, weights, paths) {
|
|
1832
|
+
return [...Object.keys(key), ...Object.keys(weights ?? {})].some((f) => paths.has(f) || hasAncestorIn(f, paths));
|
|
1833
|
+
}
|
|
1834
|
+
/** The `__pk` unique index of non-`_id` `@meta.id` fields. */
|
|
1835
|
+
const PK_INDEX = mongoIndexKey("unique", "__pk");
|
|
1836
|
+
/**
|
|
1837
|
+
* Reconciles the managed indexes with the model. `opts` (schema sync, safe
|
|
1838
|
+
* mode) names the indexes that stay as they are — neither dropped, replaced
|
|
1839
|
+
* nor created — because the change they depend on was skipped: the `__pk`
|
|
1840
|
+
* index of a skipped key rebuild, the indexes over a column whose type change
|
|
1841
|
+
* is pending (its present-only filter is typed).
|
|
1842
|
+
*/
|
|
1843
|
+
async function syncIndexesImpl(host, opts) {
|
|
1807
1844
|
await host.ensureCollectionExists();
|
|
1808
1845
|
const allIndexes = /* @__PURE__ */ new Map();
|
|
1809
1846
|
for (const [key, index] of host._table.indexes.entries()) {
|
|
@@ -1844,6 +1881,12 @@ async function syncIndexesImpl(host) {
|
|
|
1844
1881
|
} else allIndexes.set(key, index);
|
|
1845
1882
|
const existingIndexes = await host.collection.listIndexes().toArray();
|
|
1846
1883
|
const indexesToCreate = new Map(allIndexes);
|
|
1884
|
+
const keepColumns = new Set(opts?.keepColumns ?? []);
|
|
1885
|
+
const isKept = (name, key, weights) => opts?.keepPrimaryKey === true && name === PK_INDEX || coversAny(key, weights, keepColumns);
|
|
1886
|
+
const kept = /* @__PURE__ */ new Set();
|
|
1887
|
+
for (const index of allIndexes.values()) if (isPlainIndex(index) && isKept(index.key, index.fields, index.weights)) kept.add(index.key);
|
|
1888
|
+
for (const remote of existingIndexes) if (isKept(remote.name, remote.key, remote.weights)) kept.add(remote.name);
|
|
1889
|
+
for (const name of kept) indexesToCreate.delete(name);
|
|
1847
1890
|
const { attempt, throwIfAny } = (0, _atscript_db.createFailureCollector)("index sync");
|
|
1848
1891
|
let defaultCollation;
|
|
1849
1892
|
const collectionDefaultCollation = async () => {
|
|
@@ -1851,7 +1894,7 @@ async function syncIndexesImpl(host) {
|
|
|
1851
1894
|
return defaultCollation ?? void 0;
|
|
1852
1895
|
};
|
|
1853
1896
|
for (const remote of existingIndexes) {
|
|
1854
|
-
if (!remote.name.startsWith("atscript__")) continue;
|
|
1897
|
+
if (!remote.name.startsWith("atscript__") || kept.has(remote.name)) continue;
|
|
1855
1898
|
if (indexesToCreate.has(remote.name)) {
|
|
1856
1899
|
const local = indexesToCreate.get(remote.name);
|
|
1857
1900
|
if (isPlainIndex(local)) {
|
|
@@ -3168,11 +3211,12 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
3168
3211
|
* No physical primary key on MongoDB (`_id` is fixed): a `@meta.id` move is
|
|
3169
3212
|
* an index change that `syncIndexes` reconciles. Like on the other adapters,
|
|
3170
3213
|
* schema sync refuses it on a populated collection whose documents do not
|
|
3171
|
-
* satisfy the new key.
|
|
3214
|
+
* satisfy the new key. An old key field removed in the same sync loses its
|
|
3215
|
+
* `__pk` index first (`dropIndexesForColumns`).
|
|
3172
3216
|
*/
|
|
3173
3217
|
async rebuildPrimaryKey(_change) {}
|
|
3174
|
-
async syncIndexes() {
|
|
3175
|
-
return syncIndexesImpl(this);
|
|
3218
|
+
async syncIndexes(opts) {
|
|
3219
|
+
return syncIndexesImpl(this, opts);
|
|
3176
3220
|
}
|
|
3177
3221
|
async syncColumns(diff) {
|
|
3178
3222
|
return syncColumnsImpl(this, diff);
|
|
@@ -3180,6 +3224,9 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
3180
3224
|
async dropColumns(columns) {
|
|
3181
3225
|
return dropColumnsImpl(this, columns);
|
|
3182
3226
|
}
|
|
3227
|
+
async dropIndexesForColumns(columns) {
|
|
3228
|
+
return dropIndexesForColumnsImpl(this, columns);
|
|
3229
|
+
}
|
|
3183
3230
|
async renameTable(oldName) {
|
|
3184
3231
|
return renameTableImpl(this, oldName);
|
|
3185
3232
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as buildMongoFilter, c as mongoFilterStages, i as TMongoFilterPlan, l as planStages, n as TMongoFieldCollation, o as buildMongoQuery, r as TMongoFilterOptions, s as collationOfAdapter, t as REL_FILTER_TEMP_PREFIX } from "./mongo-filter-CGd9ryOD.cjs";
|
|
2
|
-
import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbCollation, TDbDeleteResult, TDbFieldMeta, TDbForeignKey, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbRelation, TDbUpdateOptions, TDbUpdateResult, TExistingTableOption, TFieldOps, TMetadataOverrides, TPrimaryKeyChange, TSearchIndexInfo, TSyncColumnResult, TTableResolver, TViewCapability, TableMetadata, WithRelation, getKeyProps } from "@atscript/db";
|
|
2
|
+
import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbCollation, TDbDeleteResult, TDbFieldMeta, TDbForeignKey, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbRelation, TDbUpdateOptions, TDbUpdateResult, TExistingTableOption, TFieldOps, TMetadataOverrides, TPrimaryKeyChange, TSearchIndexInfo, TSyncColumnResult, TSyncIndexesOptions, TTableResolver, TViewCapability, TableMetadata, WithRelation, getKeyProps } from "@atscript/db";
|
|
3
3
|
import { AggregateOptions, AggregationCursor, ClientSession, Collection, Db, Document, Filter, MongoClient, ObjectId, UpdateFilter, UpdateOptions } from "mongodb";
|
|
4
4
|
import { TAtscriptAnnotatedType, TMetadataMap, TValidatorOptions, TValidatorPlugin, Validator } from "@atscript/typescript/utils";
|
|
5
5
|
import { AggregateFn, BucketUnit } from "@uniqu/core";
|
|
@@ -592,12 +592,14 @@ declare class MongoAdapter extends BaseDbAdapter {
|
|
|
592
592
|
* No physical primary key on MongoDB (`_id` is fixed): a `@meta.id` move is
|
|
593
593
|
* an index change that `syncIndexes` reconciles. Like on the other adapters,
|
|
594
594
|
* schema sync refuses it on a populated collection whose documents do not
|
|
595
|
-
* satisfy the new key.
|
|
595
|
+
* satisfy the new key. An old key field removed in the same sync loses its
|
|
596
|
+
* `__pk` index first (`dropIndexesForColumns`).
|
|
596
597
|
*/
|
|
597
598
|
rebuildPrimaryKey(_change: TPrimaryKeyChange): Promise<void>;
|
|
598
|
-
syncIndexes(): Promise<void>;
|
|
599
|
+
syncIndexes(opts?: TSyncIndexesOptions): Promise<void>;
|
|
599
600
|
syncColumns(diff: TColumnDiff): Promise<TSyncColumnResult>;
|
|
600
601
|
dropColumns(columns: string[]): Promise<void>;
|
|
602
|
+
dropIndexesForColumns(columns: string[]): Promise<void>;
|
|
601
603
|
renameTable(oldName: string): Promise<void>;
|
|
602
604
|
recreateTable(): Promise<void>;
|
|
603
605
|
dropTable(): Promise<void>;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as buildMongoFilter, c as mongoFilterStages, i as TMongoFilterPlan, l as planStages, n as TMongoFieldCollation, o as buildMongoQuery, r as TMongoFilterOptions, s as collationOfAdapter, t as REL_FILTER_TEMP_PREFIX } from "./mongo-filter-CGd9ryOD.mjs";
|
|
2
|
-
import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbCollation, TDbDeleteResult, TDbFieldMeta, TDbForeignKey, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbRelation, TDbUpdateOptions, TDbUpdateResult, TExistingTableOption, TFieldOps, TMetadataOverrides, TPrimaryKeyChange, TSearchIndexInfo, TSyncColumnResult, TTableResolver, TViewCapability, TableMetadata, WithRelation, getKeyProps } from "@atscript/db";
|
|
2
|
+
import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbCollation, TDbDeleteResult, TDbFieldMeta, TDbForeignKey, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbRelation, TDbUpdateOptions, TDbUpdateResult, TExistingTableOption, TFieldOps, TMetadataOverrides, TPrimaryKeyChange, TSearchIndexInfo, TSyncColumnResult, TSyncIndexesOptions, TTableResolver, TViewCapability, TableMetadata, WithRelation, getKeyProps } from "@atscript/db";
|
|
3
3
|
import { AggregateOptions, AggregationCursor, ClientSession, Collection, Db, Document, Filter, MongoClient, ObjectId, UpdateFilter, UpdateOptions } from "mongodb";
|
|
4
4
|
import { AggregateFn, BucketUnit } from "@uniqu/core";
|
|
5
5
|
import { TAtscriptAnnotatedType, TMetadataMap, TValidatorOptions, TValidatorPlugin, Validator } from "@atscript/typescript/utils";
|
|
@@ -592,12 +592,14 @@ declare class MongoAdapter extends BaseDbAdapter {
|
|
|
592
592
|
* No physical primary key on MongoDB (`_id` is fixed): a `@meta.id` move is
|
|
593
593
|
* an index change that `syncIndexes` reconciles. Like on the other adapters,
|
|
594
594
|
* schema sync refuses it on a populated collection whose documents do not
|
|
595
|
-
* satisfy the new key.
|
|
595
|
+
* satisfy the new key. An old key field removed in the same sync loses its
|
|
596
|
+
* `__pk` index first (`dropIndexesForColumns`).
|
|
596
597
|
*/
|
|
597
598
|
rebuildPrimaryKey(_change: TPrimaryKeyChange): Promise<void>;
|
|
598
|
-
syncIndexes(): Promise<void>;
|
|
599
|
+
syncIndexes(opts?: TSyncIndexesOptions): Promise<void>;
|
|
599
600
|
syncColumns(diff: TColumnDiff): Promise<TSyncColumnResult>;
|
|
600
601
|
dropColumns(columns: string[]): Promise<void>;
|
|
602
|
+
dropIndexesForColumns(columns: string[]): Promise<void>;
|
|
601
603
|
renameTable(oldName: string): Promise<void>;
|
|
602
604
|
recreateTable(): Promise<void>;
|
|
603
605
|
dropTable(): Promise<void>;
|
package/dist/index.mjs
CHANGED
|
@@ -1769,6 +1769,27 @@ async function dropColumnsImpl(host, columns) {
|
|
|
1769
1769
|
await host.collection.updateMany({}, { $unset: unsetSpec }, host._getSessionOpts());
|
|
1770
1770
|
}
|
|
1771
1771
|
/**
|
|
1772
|
+
* Drops the managed indexes over any of `columns` (or a path under one).
|
|
1773
|
+
* Schema sync calls it before {@link dropColumnsImpl}: a unique index on a
|
|
1774
|
+
* required field indexes a `$unset` document as `null`, so the second one
|
|
1775
|
+
* collides (E11000) — e.g. the old key field's `__pk` index when a `@meta.id`
|
|
1776
|
+
* move removes that field. `syncIndexesImpl` then builds what the model wants.
|
|
1777
|
+
*/
|
|
1778
|
+
async function dropIndexesForColumnsImpl(host, columns) {
|
|
1779
|
+
const dropped = new Set(columns);
|
|
1780
|
+
let existing;
|
|
1781
|
+
try {
|
|
1782
|
+
existing = await host.collection.listIndexes().toArray();
|
|
1783
|
+
} catch (error) {
|
|
1784
|
+
if (error.code === 26) return;
|
|
1785
|
+
throw error;
|
|
1786
|
+
}
|
|
1787
|
+
for (const remote of existing) if (remote.name.startsWith("atscript__") && coversAny(remote.key, remote.weights, dropped)) {
|
|
1788
|
+
host._log("dropIndex", remote.name);
|
|
1789
|
+
await host.collection.dropIndex(remote.name);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1772
1793
|
* The segments of a field's physical document path with `$[]` after every
|
|
1773
1794
|
* segment whose logical prefix is an array in the flatMap — Mongo's
|
|
1774
1795
|
* all-positional operator walks every element. `physicalPath` defaults to
|
|
@@ -1802,7 +1823,23 @@ function resolveSyncDefault(field) {
|
|
|
1802
1823
|
if (!field.defaultValue) return;
|
|
1803
1824
|
if (field.defaultValue.kind === "value") return field.designType === "string" ? field.defaultValue.value : JSON.parse(field.defaultValue.value);
|
|
1804
1825
|
}
|
|
1805
|
-
|
|
1826
|
+
/**
|
|
1827
|
+
* Whether an index's fields include one of `paths` or a path under one —
|
|
1828
|
+
* a text index lists its fields in `weights` (its key is `_fts` / `_ftsx`).
|
|
1829
|
+
*/
|
|
1830
|
+
function coversAny(key, weights, paths) {
|
|
1831
|
+
return [...Object.keys(key), ...Object.keys(weights ?? {})].some((f) => paths.has(f) || hasAncestorIn(f, paths));
|
|
1832
|
+
}
|
|
1833
|
+
/** The `__pk` unique index of non-`_id` `@meta.id` fields. */
|
|
1834
|
+
const PK_INDEX = mongoIndexKey("unique", "__pk");
|
|
1835
|
+
/**
|
|
1836
|
+
* Reconciles the managed indexes with the model. `opts` (schema sync, safe
|
|
1837
|
+
* mode) names the indexes that stay as they are — neither dropped, replaced
|
|
1838
|
+
* nor created — because the change they depend on was skipped: the `__pk`
|
|
1839
|
+
* index of a skipped key rebuild, the indexes over a column whose type change
|
|
1840
|
+
* is pending (its present-only filter is typed).
|
|
1841
|
+
*/
|
|
1842
|
+
async function syncIndexesImpl(host, opts) {
|
|
1806
1843
|
await host.ensureCollectionExists();
|
|
1807
1844
|
const allIndexes = /* @__PURE__ */ new Map();
|
|
1808
1845
|
for (const [key, index] of host._table.indexes.entries()) {
|
|
@@ -1843,6 +1880,12 @@ async function syncIndexesImpl(host) {
|
|
|
1843
1880
|
} else allIndexes.set(key, index);
|
|
1844
1881
|
const existingIndexes = await host.collection.listIndexes().toArray();
|
|
1845
1882
|
const indexesToCreate = new Map(allIndexes);
|
|
1883
|
+
const keepColumns = new Set(opts?.keepColumns ?? []);
|
|
1884
|
+
const isKept = (name, key, weights) => opts?.keepPrimaryKey === true && name === PK_INDEX || coversAny(key, weights, keepColumns);
|
|
1885
|
+
const kept = /* @__PURE__ */ new Set();
|
|
1886
|
+
for (const index of allIndexes.values()) if (isPlainIndex(index) && isKept(index.key, index.fields, index.weights)) kept.add(index.key);
|
|
1887
|
+
for (const remote of existingIndexes) if (isKept(remote.name, remote.key, remote.weights)) kept.add(remote.name);
|
|
1888
|
+
for (const name of kept) indexesToCreate.delete(name);
|
|
1846
1889
|
const { attempt, throwIfAny } = createFailureCollector("index sync");
|
|
1847
1890
|
let defaultCollation;
|
|
1848
1891
|
const collectionDefaultCollation = async () => {
|
|
@@ -1850,7 +1893,7 @@ async function syncIndexesImpl(host) {
|
|
|
1850
1893
|
return defaultCollation ?? void 0;
|
|
1851
1894
|
};
|
|
1852
1895
|
for (const remote of existingIndexes) {
|
|
1853
|
-
if (!remote.name.startsWith("atscript__")) continue;
|
|
1896
|
+
if (!remote.name.startsWith("atscript__") || kept.has(remote.name)) continue;
|
|
1854
1897
|
if (indexesToCreate.has(remote.name)) {
|
|
1855
1898
|
const local = indexesToCreate.get(remote.name);
|
|
1856
1899
|
if (isPlainIndex(local)) {
|
|
@@ -3167,11 +3210,12 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
|
|
|
3167
3210
|
* No physical primary key on MongoDB (`_id` is fixed): a `@meta.id` move is
|
|
3168
3211
|
* an index change that `syncIndexes` reconciles. Like on the other adapters,
|
|
3169
3212
|
* schema sync refuses it on a populated collection whose documents do not
|
|
3170
|
-
* satisfy the new key.
|
|
3213
|
+
* satisfy the new key. An old key field removed in the same sync loses its
|
|
3214
|
+
* `__pk` index first (`dropIndexesForColumns`).
|
|
3171
3215
|
*/
|
|
3172
3216
|
async rebuildPrimaryKey(_change) {}
|
|
3173
|
-
async syncIndexes() {
|
|
3174
|
-
return syncIndexesImpl(this);
|
|
3217
|
+
async syncIndexes(opts) {
|
|
3218
|
+
return syncIndexesImpl(this, opts);
|
|
3175
3219
|
}
|
|
3176
3220
|
async syncColumns(diff) {
|
|
3177
3221
|
return syncColumnsImpl(this, diff);
|
|
@@ -3179,6 +3223,9 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
|
|
|
3179
3223
|
async dropColumns(columns) {
|
|
3180
3224
|
return dropColumnsImpl(this, columns);
|
|
3181
3225
|
}
|
|
3226
|
+
async dropIndexesForColumns(columns) {
|
|
3227
|
+
return dropIndexesForColumnsImpl(this, columns);
|
|
3228
|
+
}
|
|
3182
3229
|
async renameTable(oldName) {
|
|
3183
3230
|
return renameTableImpl(this, oldName);
|
|
3184
3231
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db-mongo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.157",
|
|
4
4
|
"description": "Mongodb plugin for atscript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@atscript/core": "^0.1.
|
|
50
|
-
"@atscript/typescript": "^0.1.
|
|
49
|
+
"@atscript/core": "^0.1.106",
|
|
50
|
+
"@atscript/typescript": "^0.1.106",
|
|
51
51
|
"@uniqu/core": "^0.1.15",
|
|
52
52
|
"mongodb": "^6.17.0",
|
|
53
53
|
"mongodb-memory-server-core": "^10.0.0",
|
|
54
|
-
"unplugin-atscript": "^0.1.
|
|
54
|
+
"unplugin-atscript": "^0.1.106"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@atscript/core": "^0.1.
|
|
58
|
-
"@atscript/typescript": "^0.1.
|
|
57
|
+
"@atscript/core": "^0.1.106",
|
|
58
|
+
"@atscript/typescript": "^0.1.106",
|
|
59
59
|
"@uniqu/core": "^0.1.15",
|
|
60
60
|
"mongodb": "^6.17.0",
|
|
61
|
-
"@atscript/db": "^0.1.
|
|
61
|
+
"@atscript/db": "^0.1.157"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"postinstall": "asc -f dts",
|