@atscript/db-mongo 0.1.140 → 0.1.142

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 CHANGED
@@ -1033,7 +1033,10 @@ function joinedAs(table) {
1033
1033
  * pipeline paths (SQL null semantics — `queryNodeToExpr`).
1034
1034
  *
1035
1035
  * All field paths are PHYSICAL document paths (`@db.column` renames), joined
1036
- * tables live under `__joined_<table>`. A column whose source may be missing
1036
+ * tables live under `__joined_<scope>` — the physical collection, or the
1037
+ * `@db.alias` type name for an aliased join (`__joined_Manager`), whose
1038
+ * `$lookup.from` stays the physical collection (since 0.1.141).
1039
+ * The entry collection and a `$lookup.from` may be views. A column whose source may be missing
1037
1040
  * (`nullable` mapping) reads as null; every other column is a plain path, so
1038
1041
  * a `$match` / `$sort` on the view can still push down to an index.
1039
1042
  * @since 0.1.136
@@ -1052,10 +1055,10 @@ function buildViewPipeline(view) {
1052
1055
  for (const join of plan.joins) {
1053
1056
  pipeline.push(buildLookup(view, join, prefixes));
1054
1057
  pipeline.push({ $unwind: {
1055
- path: `$${joinedAs(join.targetTable)}`,
1058
+ path: `$${joinedAs(join.scope)}`,
1056
1059
  preserveNullAndEmptyArrays: join.kind === "left"
1057
1060
  } });
1058
- prefixes.set(join.targetTable, `${joinedAs(join.targetTable)}.`);
1061
+ prefixes.set(join.scope, `${joinedAs(join.scope)}.`);
1059
1062
  }
1060
1063
  if (plan.filter) pipeline.push({ $match: viewMatch(plan.filter, pathOf) });
1061
1064
  /** A column's source field as an aggregation operand. */
@@ -1099,7 +1102,8 @@ function buildViewPipeline(view) {
1099
1102
  * `$match: { $expr }`, SQL null semantics).
1100
1103
  */
1101
1104
  function buildLookup(view, join, outer) {
1102
- const as = joinedAs(join.targetTable);
1105
+ const scope = join.scope;
1106
+ const as = joinedAs(scope);
1103
1107
  const simple = simpleJoinFields(view, join, outer);
1104
1108
  if (simple) return { $lookup: {
1105
1109
  from: join.targetTable,
@@ -1110,9 +1114,9 @@ function buildLookup(view, join, outer) {
1110
1114
  const varByPath = /* @__PURE__ */ new Map();
1111
1115
  const pathOf = (ref) => {
1112
1116
  const { table, source } = view.resolveRefSource(ref);
1113
- if (table === join.targetTable) return `$${source.column}`;
1117
+ if (table === scope) return `$${source.column}`;
1114
1118
  const prefix = outer.get(table);
1115
- if (prefix === void 0) throw new Error(`View "${view.tableName}": the join on "${join.targetTable}" references "${table}", which is not joined before it`);
1119
+ if (prefix === void 0) throw new Error(`View "${view.tableName}": the join on "${scope}" references "${table}", which is not joined before it`);
1116
1120
  const outerPath = prefix + source.column;
1117
1121
  let varName = varByPath.get(outerPath);
1118
1122
  if (!varName) {
@@ -1141,14 +1145,15 @@ function simpleJoinFields(view, join, outer) {
1141
1145
  if ("$or" in node || "$not" in node || "$and" in node) return void 0;
1142
1146
  const comp = node;
1143
1147
  if (comp.op !== "$eq" || !(0, _atscript_db.isFieldRef)(comp.right)) return void 0;
1148
+ const scope = join.scope;
1144
1149
  const left = view.resolveRefSource(comp.left);
1145
1150
  const right = view.resolveRefSource(comp.right);
1146
1151
  let target;
1147
1152
  let local;
1148
- if (left.table === join.targetTable && right.table !== join.targetTable) {
1153
+ if (left.table === scope && right.table !== scope) {
1149
1154
  target = left;
1150
1155
  local = right;
1151
- } else if (right.table === join.targetTable && left.table !== join.targetTable) {
1156
+ } else if (right.table === scope && left.table !== scope) {
1152
1157
  target = right;
1153
1158
  local = left;
1154
1159
  } else return;
@@ -1895,7 +1900,7 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
1895
1900
  }
1896
1901
  async nativePatch(filter, patch, ops, expectedVersion) {
1897
1902
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "nativePatch");
1898
- const versionColumn = this._table.versionColumn;
1903
+ const versionColumn = this._table.versionColumnPhysical;
1899
1904
  const effectiveOps = versionColumn !== void 0 ? {
1900
1905
  ...ops,
1901
1906
  inc: {
@@ -1905,14 +1910,10 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
1905
1910
  } : ops;
1906
1911
  const { updateFilter, updateOptions } = new CollectionPatcher(this.getPatcherContext(), patch, effectiveOps).preparePatch();
1907
1912
  this._log("updateOne (patch)", mongoFilter, updateFilter);
1908
- const result = await this.collection.updateOne(mongoFilter, updateFilter, {
1913
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, updateFilter, {
1909
1914
  ...updateOptions,
1910
1915
  ...this._getSessionOpts()
1911
- });
1912
- return {
1913
- matchedCount: result.matchedCount,
1914
- modifiedCount: result.modifiedCount
1915
- };
1916
+ }));
1916
1917
  }
1917
1918
  onBeforeFlatten(_type) {
1918
1919
  const typeMeta = _type.metadata;
@@ -2144,7 +2145,7 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2144
2145
  * rather than silently dropping the CAS predicate.
2145
2146
  */
2146
2147
  _buildCasFilter(filter, expectedVersion, op) {
2147
- const versionColumn = this._table.versionColumn;
2148
+ const versionColumn = this._table.versionColumnPhysical;
2148
2149
  if (expectedVersion !== void 0 && versionColumn === void 0) throw new Error(`${op}: expectedVersion requires versionColumn`);
2149
2150
  const mongoFilter = require_mongo_accumulator.buildMongoFilter(filter);
2150
2151
  if (expectedVersion !== void 0 && versionColumn !== void 0) mongoFilter[versionColumn] = expectedVersion;
@@ -2152,7 +2153,9 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2152
2153
  }
2153
2154
  /**
2154
2155
  * Wraps an async operation to catch MongoDB duplicate key errors
2155
- * (code 11000) and rethrow as structured `DbError`.
2156
+ * (code 11000) and rethrow as structured `DbError` — every write path
2157
+ * (insert, replace, update, patch, their `*Many` variants) goes through it,
2158
+ * so a unique-index violation is a `CONFLICT` whichever statement hit it.
2156
2159
  */
2157
2160
  async _wrapDuplicateKeyError(fn) {
2158
2161
  try {
@@ -2165,8 +2168,16 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2165
2168
  throw error;
2166
2169
  }
2167
2170
  }
2171
+ /** An update-shaped write under {@link _wrapDuplicateKeyError}, reduced to `TDbUpdateResult`. */
2172
+ async _wrapUpdate(fn) {
2173
+ const { matchedCount, modifiedCount } = await this._wrapDuplicateKeyError(fn);
2174
+ return {
2175
+ matchedCount,
2176
+ modifiedCount
2177
+ };
2178
+ }
2168
2179
  async insertOne(data) {
2169
- const versionColumn = this._table.versionColumn;
2180
+ const versionColumn = this._table.versionColumnPhysical;
2170
2181
  if (versionColumn !== void 0 && !(versionColumn in data)) data[versionColumn] = 0;
2171
2182
  if (this._incrementFields.size > 0) {
2172
2183
  const fields = this._fieldsNeedingIncrement(data);
@@ -2180,7 +2191,7 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2180
2191
  return { insertedId: objectIdFromStorage(this._resolveInsertedId(data, result.insertedId)) };
2181
2192
  }
2182
2193
  async insertMany(data) {
2183
- const versionColumn = this._table.versionColumn;
2194
+ const versionColumn = this._table.versionColumnPhysical;
2184
2195
  if (versionColumn !== void 0) {
2185
2196
  for (const item of data) if (!(versionColumn in item)) item[versionColumn] = 0;
2186
2197
  }
@@ -2226,30 +2237,22 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2226
2237
  }
2227
2238
  async updateOne(filter, data, ops, expectedVersion) {
2228
2239
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "updateOne");
2229
- const updateDoc = buildMongoUpdateDoc(data, ops, this._table.versionColumn);
2240
+ const updateDoc = buildMongoUpdateDoc(data, ops, this._table.versionColumnPhysical);
2230
2241
  this._log("updateOne", mongoFilter, updateDoc);
2231
- const result = await this.collection.updateOne(mongoFilter, updateDoc, this._getSessionOpts());
2232
- return {
2233
- matchedCount: result.matchedCount,
2234
- modifiedCount: result.modifiedCount
2235
- };
2242
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, updateDoc, this._getSessionOpts()));
2236
2243
  }
2237
2244
  async replaceOne(filter, data, expectedVersion) {
2238
2245
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "replaceOne");
2239
- const versionColumn = this._table.versionColumn;
2246
+ const versionColumn = this._table.versionColumnPhysical;
2240
2247
  this._log("replaceOne", mongoFilter, data);
2241
- let result;
2242
2248
  if (versionColumn !== void 0) {
2243
2249
  const pipeline = [{ $replaceWith: {
2244
2250
  ...data,
2245
2251
  [versionColumn]: { $add: [`$${versionColumn}`, 1] }
2246
2252
  } }];
2247
- result = await this._wrapDuplicateKeyError(() => this.collection.updateOne(mongoFilter, pipeline, this._getSessionOpts()));
2248
- } else result = await this._wrapDuplicateKeyError(() => this.collection.replaceOne(mongoFilter, data, this._getSessionOpts()));
2249
- return {
2250
- matchedCount: result.matchedCount,
2251
- modifiedCount: result.modifiedCount
2252
- };
2253
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, pipeline, this._getSessionOpts()));
2254
+ }
2255
+ return this._wrapUpdate(() => this.collection.replaceOne(mongoFilter, data, this._getSessionOpts()));
2253
2256
  }
2254
2257
  async deleteOne(filter) {
2255
2258
  const mongoFilter = require_mongo_accumulator.buildMongoFilter(filter);
@@ -2257,25 +2260,17 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2257
2260
  return { deletedCount: (await this.collection.deleteOne(mongoFilter, this._getSessionOpts())).deletedCount };
2258
2261
  }
2259
2262
  async updateMany(filter, data, ops) {
2260
- const versionColumn = this._table.versionColumn;
2263
+ const versionColumn = this._table.versionColumnPhysical;
2261
2264
  const mongoFilter = require_mongo_accumulator.buildMongoFilter(filter);
2262
2265
  const updateDoc = buildMongoUpdateDoc(data, ops, versionColumn);
2263
2266
  this._log("updateMany", mongoFilter, updateDoc);
2264
- const result = await this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts());
2265
- return {
2266
- matchedCount: result.matchedCount,
2267
- modifiedCount: result.modifiedCount
2268
- };
2267
+ return this._wrapUpdate(() => this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts()));
2269
2268
  }
2270
2269
  async replaceMany(filter, data) {
2271
2270
  const mongoFilter = require_mongo_accumulator.buildMongoFilter(filter);
2272
- const updateDoc = buildMongoUpdateDoc(data, void 0, this._table.versionColumn);
2271
+ const updateDoc = buildMongoUpdateDoc(data, void 0, this._table.versionColumnPhysical);
2273
2272
  this._log("replaceMany", mongoFilter, updateDoc);
2274
- const result = await this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts());
2275
- return {
2276
- matchedCount: result.matchedCount,
2277
- modifiedCount: result.modifiedCount
2278
- };
2273
+ return this._wrapUpdate(() => this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts()));
2279
2274
  }
2280
2275
  async deleteMany(filter) {
2281
2276
  const mongoFilter = require_mongo_accumulator.buildMongoFilter(filter);
package/dist/index.d.cts CHANGED
@@ -390,9 +390,13 @@ declare class MongoAdapter extends BaseDbAdapter {
390
390
  private _buildCasFilter;
391
391
  /**
392
392
  * Wraps an async operation to catch MongoDB duplicate key errors
393
- * (code 11000) and rethrow as structured `DbError`.
393
+ * (code 11000) and rethrow as structured `DbError` — every write path
394
+ * (insert, replace, update, patch, their `*Many` variants) goes through it,
395
+ * so a unique-index violation is a `CONFLICT` whichever statement hit it.
394
396
  */
395
397
  private _wrapDuplicateKeyError;
398
+ /** An update-shaped write under {@link _wrapDuplicateKeyError}, reduced to `TDbUpdateResult`. */
399
+ private _wrapUpdate;
396
400
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
397
401
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
398
402
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
package/dist/index.d.mts CHANGED
@@ -390,9 +390,13 @@ declare class MongoAdapter extends BaseDbAdapter {
390
390
  private _buildCasFilter;
391
391
  /**
392
392
  * Wraps an async operation to catch MongoDB duplicate key errors
393
- * (code 11000) and rethrow as structured `DbError`.
393
+ * (code 11000) and rethrow as structured `DbError` — every write path
394
+ * (insert, replace, update, patch, their `*Many` variants) goes through it,
395
+ * so a unique-index violation is a `CONFLICT` whichever statement hit it.
394
396
  */
395
397
  private _wrapDuplicateKeyError;
398
+ /** An update-shaped write under {@link _wrapDuplicateKeyError}, reduced to `TDbUpdateResult`. */
399
+ private _wrapUpdate;
396
400
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
397
401
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
398
402
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
package/dist/index.mjs CHANGED
@@ -1032,7 +1032,10 @@ function joinedAs(table) {
1032
1032
  * pipeline paths (SQL null semantics — `queryNodeToExpr`).
1033
1033
  *
1034
1034
  * All field paths are PHYSICAL document paths (`@db.column` renames), joined
1035
- * tables live under `__joined_<table>`. A column whose source may be missing
1035
+ * tables live under `__joined_<scope>` — the physical collection, or the
1036
+ * `@db.alias` type name for an aliased join (`__joined_Manager`), whose
1037
+ * `$lookup.from` stays the physical collection (since 0.1.141).
1038
+ * The entry collection and a `$lookup.from` may be views. A column whose source may be missing
1036
1039
  * (`nullable` mapping) reads as null; every other column is a plain path, so
1037
1040
  * a `$match` / `$sort` on the view can still push down to an index.
1038
1041
  * @since 0.1.136
@@ -1051,10 +1054,10 @@ function buildViewPipeline(view) {
1051
1054
  for (const join of plan.joins) {
1052
1055
  pipeline.push(buildLookup(view, join, prefixes));
1053
1056
  pipeline.push({ $unwind: {
1054
- path: `$${joinedAs(join.targetTable)}`,
1057
+ path: `$${joinedAs(join.scope)}`,
1055
1058
  preserveNullAndEmptyArrays: join.kind === "left"
1056
1059
  } });
1057
- prefixes.set(join.targetTable, `${joinedAs(join.targetTable)}.`);
1060
+ prefixes.set(join.scope, `${joinedAs(join.scope)}.`);
1058
1061
  }
1059
1062
  if (plan.filter) pipeline.push({ $match: viewMatch(plan.filter, pathOf) });
1060
1063
  /** A column's source field as an aggregation operand. */
@@ -1098,7 +1101,8 @@ function buildViewPipeline(view) {
1098
1101
  * `$match: { $expr }`, SQL null semantics).
1099
1102
  */
1100
1103
  function buildLookup(view, join, outer) {
1101
- const as = joinedAs(join.targetTable);
1104
+ const scope = join.scope;
1105
+ const as = joinedAs(scope);
1102
1106
  const simple = simpleJoinFields(view, join, outer);
1103
1107
  if (simple) return { $lookup: {
1104
1108
  from: join.targetTable,
@@ -1109,9 +1113,9 @@ function buildLookup(view, join, outer) {
1109
1113
  const varByPath = /* @__PURE__ */ new Map();
1110
1114
  const pathOf = (ref) => {
1111
1115
  const { table, source } = view.resolveRefSource(ref);
1112
- if (table === join.targetTable) return `$${source.column}`;
1116
+ if (table === scope) return `$${source.column}`;
1113
1117
  const prefix = outer.get(table);
1114
- if (prefix === void 0) throw new Error(`View "${view.tableName}": the join on "${join.targetTable}" references "${table}", which is not joined before it`);
1118
+ if (prefix === void 0) throw new Error(`View "${view.tableName}": the join on "${scope}" references "${table}", which is not joined before it`);
1115
1119
  const outerPath = prefix + source.column;
1116
1120
  let varName = varByPath.get(outerPath);
1117
1121
  if (!varName) {
@@ -1140,14 +1144,15 @@ function simpleJoinFields(view, join, outer) {
1140
1144
  if ("$or" in node || "$not" in node || "$and" in node) return void 0;
1141
1145
  const comp = node;
1142
1146
  if (comp.op !== "$eq" || !isFieldRef(comp.right)) return void 0;
1147
+ const scope = join.scope;
1143
1148
  const left = view.resolveRefSource(comp.left);
1144
1149
  const right = view.resolveRefSource(comp.right);
1145
1150
  let target;
1146
1151
  let local;
1147
- if (left.table === join.targetTable && right.table !== join.targetTable) {
1152
+ if (left.table === scope && right.table !== scope) {
1148
1153
  target = left;
1149
1154
  local = right;
1150
- } else if (right.table === join.targetTable && left.table !== join.targetTable) {
1155
+ } else if (right.table === scope && left.table !== scope) {
1151
1156
  target = right;
1152
1157
  local = left;
1153
1158
  } else return;
@@ -1894,7 +1899,7 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
1894
1899
  }
1895
1900
  async nativePatch(filter, patch, ops, expectedVersion) {
1896
1901
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "nativePatch");
1897
- const versionColumn = this._table.versionColumn;
1902
+ const versionColumn = this._table.versionColumnPhysical;
1898
1903
  const effectiveOps = versionColumn !== void 0 ? {
1899
1904
  ...ops,
1900
1905
  inc: {
@@ -1904,14 +1909,10 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
1904
1909
  } : ops;
1905
1910
  const { updateFilter, updateOptions } = new CollectionPatcher(this.getPatcherContext(), patch, effectiveOps).preparePatch();
1906
1911
  this._log("updateOne (patch)", mongoFilter, updateFilter);
1907
- const result = await this.collection.updateOne(mongoFilter, updateFilter, {
1912
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, updateFilter, {
1908
1913
  ...updateOptions,
1909
1914
  ...this._getSessionOpts()
1910
- });
1911
- return {
1912
- matchedCount: result.matchedCount,
1913
- modifiedCount: result.modifiedCount
1914
- };
1915
+ }));
1915
1916
  }
1916
1917
  onBeforeFlatten(_type) {
1917
1918
  const typeMeta = _type.metadata;
@@ -2143,7 +2144,7 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2143
2144
  * rather than silently dropping the CAS predicate.
2144
2145
  */
2145
2146
  _buildCasFilter(filter, expectedVersion, op) {
2146
- const versionColumn = this._table.versionColumn;
2147
+ const versionColumn = this._table.versionColumnPhysical;
2147
2148
  if (expectedVersion !== void 0 && versionColumn === void 0) throw new Error(`${op}: expectedVersion requires versionColumn`);
2148
2149
  const mongoFilter = buildMongoFilter(filter);
2149
2150
  if (expectedVersion !== void 0 && versionColumn !== void 0) mongoFilter[versionColumn] = expectedVersion;
@@ -2151,7 +2152,9 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2151
2152
  }
2152
2153
  /**
2153
2154
  * Wraps an async operation to catch MongoDB duplicate key errors
2154
- * (code 11000) and rethrow as structured `DbError`.
2155
+ * (code 11000) and rethrow as structured `DbError` — every write path
2156
+ * (insert, replace, update, patch, their `*Many` variants) goes through it,
2157
+ * so a unique-index violation is a `CONFLICT` whichever statement hit it.
2155
2158
  */
2156
2159
  async _wrapDuplicateKeyError(fn) {
2157
2160
  try {
@@ -2164,8 +2167,16 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2164
2167
  throw error;
2165
2168
  }
2166
2169
  }
2170
+ /** An update-shaped write under {@link _wrapDuplicateKeyError}, reduced to `TDbUpdateResult`. */
2171
+ async _wrapUpdate(fn) {
2172
+ const { matchedCount, modifiedCount } = await this._wrapDuplicateKeyError(fn);
2173
+ return {
2174
+ matchedCount,
2175
+ modifiedCount
2176
+ };
2177
+ }
2167
2178
  async insertOne(data) {
2168
- const versionColumn = this._table.versionColumn;
2179
+ const versionColumn = this._table.versionColumnPhysical;
2169
2180
  if (versionColumn !== void 0 && !(versionColumn in data)) data[versionColumn] = 0;
2170
2181
  if (this._incrementFields.size > 0) {
2171
2182
  const fields = this._fieldsNeedingIncrement(data);
@@ -2179,7 +2190,7 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2179
2190
  return { insertedId: objectIdFromStorage(this._resolveInsertedId(data, result.insertedId)) };
2180
2191
  }
2181
2192
  async insertMany(data) {
2182
- const versionColumn = this._table.versionColumn;
2193
+ const versionColumn = this._table.versionColumnPhysical;
2183
2194
  if (versionColumn !== void 0) {
2184
2195
  for (const item of data) if (!(versionColumn in item)) item[versionColumn] = 0;
2185
2196
  }
@@ -2225,30 +2236,22 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2225
2236
  }
2226
2237
  async updateOne(filter, data, ops, expectedVersion) {
2227
2238
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "updateOne");
2228
- const updateDoc = buildMongoUpdateDoc(data, ops, this._table.versionColumn);
2239
+ const updateDoc = buildMongoUpdateDoc(data, ops, this._table.versionColumnPhysical);
2229
2240
  this._log("updateOne", mongoFilter, updateDoc);
2230
- const result = await this.collection.updateOne(mongoFilter, updateDoc, this._getSessionOpts());
2231
- return {
2232
- matchedCount: result.matchedCount,
2233
- modifiedCount: result.modifiedCount
2234
- };
2241
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, updateDoc, this._getSessionOpts()));
2235
2242
  }
2236
2243
  async replaceOne(filter, data, expectedVersion) {
2237
2244
  const mongoFilter = this._buildCasFilter(filter, expectedVersion, "replaceOne");
2238
- const versionColumn = this._table.versionColumn;
2245
+ const versionColumn = this._table.versionColumnPhysical;
2239
2246
  this._log("replaceOne", mongoFilter, data);
2240
- let result;
2241
2247
  if (versionColumn !== void 0) {
2242
2248
  const pipeline = [{ $replaceWith: {
2243
2249
  ...data,
2244
2250
  [versionColumn]: { $add: [`$${versionColumn}`, 1] }
2245
2251
  } }];
2246
- result = await this._wrapDuplicateKeyError(() => this.collection.updateOne(mongoFilter, pipeline, this._getSessionOpts()));
2247
- } else result = await this._wrapDuplicateKeyError(() => this.collection.replaceOne(mongoFilter, data, this._getSessionOpts()));
2248
- return {
2249
- matchedCount: result.matchedCount,
2250
- modifiedCount: result.modifiedCount
2251
- };
2252
+ return this._wrapUpdate(() => this.collection.updateOne(mongoFilter, pipeline, this._getSessionOpts()));
2253
+ }
2254
+ return this._wrapUpdate(() => this.collection.replaceOne(mongoFilter, data, this._getSessionOpts()));
2252
2255
  }
2253
2256
  async deleteOne(filter) {
2254
2257
  const mongoFilter = buildMongoFilter(filter);
@@ -2256,25 +2259,17 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2256
2259
  return { deletedCount: (await this.collection.deleteOne(mongoFilter, this._getSessionOpts())).deletedCount };
2257
2260
  }
2258
2261
  async updateMany(filter, data, ops) {
2259
- const versionColumn = this._table.versionColumn;
2262
+ const versionColumn = this._table.versionColumnPhysical;
2260
2263
  const mongoFilter = buildMongoFilter(filter);
2261
2264
  const updateDoc = buildMongoUpdateDoc(data, ops, versionColumn);
2262
2265
  this._log("updateMany", mongoFilter, updateDoc);
2263
- const result = await this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts());
2264
- return {
2265
- matchedCount: result.matchedCount,
2266
- modifiedCount: result.modifiedCount
2267
- };
2266
+ return this._wrapUpdate(() => this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts()));
2268
2267
  }
2269
2268
  async replaceMany(filter, data) {
2270
2269
  const mongoFilter = buildMongoFilter(filter);
2271
- const updateDoc = buildMongoUpdateDoc(data, void 0, this._table.versionColumn);
2270
+ const updateDoc = buildMongoUpdateDoc(data, void 0, this._table.versionColumnPhysical);
2272
2271
  this._log("replaceMany", mongoFilter, updateDoc);
2273
- const result = await this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts());
2274
- return {
2275
- matchedCount: result.matchedCount,
2276
- modifiedCount: result.modifiedCount
2277
- };
2272
+ return this._wrapUpdate(() => this.collection.updateMany(mongoFilter, updateDoc, this._getSessionOpts()));
2278
2273
  }
2279
2274
  async deleteMany(filter) {
2280
2275
  const mongoFilter = buildMongoFilter(filter);
package/dist/plugin.cjs CHANGED
@@ -52,6 +52,7 @@ const annotations = {
52
52
  collection: new _atscript_core.AnnotationSpec({
53
53
  description: "Marks an interface as a **MongoDB collection**.\n\n- Use together with `@db.table \"name\"` which provides the collection name.\n- Automatically injects a **non-optional** `_id` field if not explicitly defined.\n- `_id` must be of type **`string`**, **`number`**, or **`mongo.objectId`**.\n\n**Example:**\n```atscript\n@db.table \"users\"\n@db.mongo.collection\nexport interface User {\n _id: mongo.objectId\n email: string.email\n}\n```\n",
54
54
  nodeType: ["interface"],
55
+ passedWhenReferred: false,
55
56
  validate(token, args, doc) {
56
57
  const parent = token.parentNode;
57
58
  const struc = parent?.getDefinition();
@@ -91,6 +92,7 @@ const annotations = {
91
92
  capped: new _atscript_core.AnnotationSpec({
92
93
  description: "Creates a **capped collection** with a fixed maximum size.\n\n- Capped collections have fixed size and maintain insertion order.\n- Ideal for logs, event streams, and cache-like data.\n- Changing the cap size requires dropping and recreating the collection — use `@db.sync.method \"drop\"` to allow this.\n\n**Example:**\n```atscript\n@db.table \"logs\"\n@db.mongo.collection\n@db.mongo.capped 10485760, 10000\n@db.sync.method \"drop\"\nexport interface LogEntry {\n message: string\n timestamp: number\n}\n```\n",
93
94
  nodeType: ["interface"],
95
+ passedWhenReferred: false,
94
96
  multiple: false,
95
97
  argument: [{
96
98
  optional: false,
@@ -108,6 +110,7 @@ const annotations = {
108
110
  dynamic: new _atscript_core.AnnotationSpec({
109
111
  description: "Creates a **dynamic MongoDB Search Index** that applies to the entire collection.\n\n- **Indexes all text fields automatically** (no need to specify fields).\n- Supports **language analyzers** for text tokenization.\n- Enables **fuzzy search** (typo tolerance) if needed.\n\n**Example:**\n```atscript\n@db.mongo.search.dynamic \"lucene.english\", 1\nexport interface MongoCollection {}\n```\n",
110
112
  nodeType: ["interface"],
113
+ passedWhenReferred: false,
111
114
  multiple: false,
112
115
  argument: [{
113
116
  optional: true,
@@ -125,6 +128,7 @@ const annotations = {
125
128
  static: new _atscript_core.AnnotationSpec({
126
129
  description: "Defines a **MongoDB Atlas Search Index** for the collection. The props can refer to this index using `@db.mongo.search.text` annotation.\n\n- **Creates a named search index** for full-text search.\n- **Specify analyzers and fuzzy search** behavior at the index level.\n- **Fields must explicitly use `@db.mongo.search.text`** to be included in this search index.\n\n**Example:**\n```atscript\n@db.mongo.search.static \"lucene.english\", 1, \"mySearchIndex\"\nexport interface MongoCollection {}\n```\n",
127
130
  nodeType: ["interface"],
131
+ passedWhenReferred: false,
128
132
  multiple: true,
129
133
  argument: [
130
134
  {
package/dist/plugin.mjs CHANGED
@@ -48,6 +48,7 @@ const annotations = {
48
48
  collection: new AnnotationSpec({
49
49
  description: "Marks an interface as a **MongoDB collection**.\n\n- Use together with `@db.table \"name\"` which provides the collection name.\n- Automatically injects a **non-optional** `_id` field if not explicitly defined.\n- `_id` must be of type **`string`**, **`number`**, or **`mongo.objectId`**.\n\n**Example:**\n```atscript\n@db.table \"users\"\n@db.mongo.collection\nexport interface User {\n _id: mongo.objectId\n email: string.email\n}\n```\n",
50
50
  nodeType: ["interface"],
51
+ passedWhenReferred: false,
51
52
  validate(token, args, doc) {
52
53
  const parent = token.parentNode;
53
54
  const struc = parent?.getDefinition();
@@ -87,6 +88,7 @@ const annotations = {
87
88
  capped: new AnnotationSpec({
88
89
  description: "Creates a **capped collection** with a fixed maximum size.\n\n- Capped collections have fixed size and maintain insertion order.\n- Ideal for logs, event streams, and cache-like data.\n- Changing the cap size requires dropping and recreating the collection — use `@db.sync.method \"drop\"` to allow this.\n\n**Example:**\n```atscript\n@db.table \"logs\"\n@db.mongo.collection\n@db.mongo.capped 10485760, 10000\n@db.sync.method \"drop\"\nexport interface LogEntry {\n message: string\n timestamp: number\n}\n```\n",
89
90
  nodeType: ["interface"],
91
+ passedWhenReferred: false,
90
92
  multiple: false,
91
93
  argument: [{
92
94
  optional: false,
@@ -104,6 +106,7 @@ const annotations = {
104
106
  dynamic: new AnnotationSpec({
105
107
  description: "Creates a **dynamic MongoDB Search Index** that applies to the entire collection.\n\n- **Indexes all text fields automatically** (no need to specify fields).\n- Supports **language analyzers** for text tokenization.\n- Enables **fuzzy search** (typo tolerance) if needed.\n\n**Example:**\n```atscript\n@db.mongo.search.dynamic \"lucene.english\", 1\nexport interface MongoCollection {}\n```\n",
106
108
  nodeType: ["interface"],
109
+ passedWhenReferred: false,
107
110
  multiple: false,
108
111
  argument: [{
109
112
  optional: true,
@@ -121,6 +124,7 @@ const annotations = {
121
124
  static: new AnnotationSpec({
122
125
  description: "Defines a **MongoDB Atlas Search Index** for the collection. The props can refer to this index using `@db.mongo.search.text` annotation.\n\n- **Creates a named search index** for full-text search.\n- **Specify analyzers and fuzzy search** behavior at the index level.\n- **Fields must explicitly use `@db.mongo.search.text`** to be included in this search index.\n\n**Example:**\n```atscript\n@db.mongo.search.static \"lucene.english\", 1, \"mySearchIndex\"\nexport interface MongoCollection {}\n```\n",
123
126
  nodeType: ["interface"],
127
+ passedWhenReferred: false,
124
128
  multiple: true,
125
129
  argument: [
126
130
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-mongo",
3
- "version": "0.1.140",
3
+ "version": "0.1.142",
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.92",
50
- "@atscript/typescript": "^0.1.92",
49
+ "@atscript/core": "^0.1.95",
50
+ "@atscript/typescript": "^0.1.95",
51
51
  "@uniqu/core": "^0.1.11",
52
52
  "mongodb": "^6.17.0",
53
53
  "mongodb-memory-server-core": "^10.0.0",
54
- "unplugin-atscript": "^0.1.92"
54
+ "unplugin-atscript": "^0.1.95"
55
55
  },
56
56
  "peerDependencies": {
57
- "@atscript/core": "^0.1.92",
58
- "@atscript/typescript": "^0.1.92",
57
+ "@atscript/core": "^0.1.95",
58
+ "@atscript/typescript": "^0.1.95",
59
59
  "@uniqu/core": "^0.1.11",
60
60
  "mongodb": "^6.17.0",
61
- "@atscript/db": "^0.1.140"
61
+ "@atscript/db": "^0.1.142"
62
62
  },
63
63
  "scripts": {
64
64
  "postinstall": "asc -f dts",