@atscript/db-mongo 0.1.121 → 0.1.122

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
@@ -1548,6 +1548,24 @@ const validateMongoIdPlugin = (ctx, def, value) => {
1548
1548
  };
1549
1549
  //#endregion
1550
1550
  //#region src/lib/mongo-adapter.ts
1551
+ /** Mirrors the `mongo.objectId` primitive's pattern — only definite hex ids convert. */
1552
+ const OBJECT_ID_HEX = /^[a-fA-F0-9]{24}$/;
1553
+ /** True for `mongo.objectId`-typed fields and arrays of them (tag-based, same as `prepareId`). */
1554
+ function isObjectIdColumn(fieldType) {
1555
+ const t = fieldType.type;
1556
+ if (t.kind === "array") return !!t.of && isObjectIdColumn(t.of);
1557
+ return t.tags?.has("objectId") === true && t.tags?.has("mongo") === true;
1558
+ }
1559
+ function objectIdToStorage(value) {
1560
+ if (typeof value === "string" && OBJECT_ID_HEX.test(value)) return new mongodb.ObjectId(value);
1561
+ if (Array.isArray(value)) return value.map(objectIdToStorage);
1562
+ return value;
1563
+ }
1564
+ function objectIdFromStorage(value) {
1565
+ if (value instanceof mongodb.ObjectId) return value.toHexString();
1566
+ if (Array.isArray(value)) return value.map(objectIdFromStorage);
1567
+ return value;
1568
+ }
1551
1569
  var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
1552
1570
  db;
1553
1571
  client;
@@ -1711,10 +1729,17 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
1711
1729
  * write `[lng, lat]` → `{ type: 'Point', coordinates: [lng, lat] }`,
1712
1730
  * unwrap back to the tuple on read. Non-tuple values (e.g. `$geoWithin`
1713
1731
  * operator objects flowing through filter translation) pass through.
1732
+ *
1733
+ * Converts `mongo.objectId` values between wire hex strings and native
1734
+ * ObjectId storage. Filters, writes, and reads all flow through these
1735
+ * formatters, so id envelopes (`@DbActionID` row loading), FK filters
1736
+ * (`{ leadId: '<hex>' }`), and inserted documents match natively stored
1737
+ * ObjectIds — and reads return the hex strings the declared type promises.
1738
+ * Top-level fields only: nested values skip the write/read formatter passes,
1739
+ * so a nested formatter would coerce filters against un-coerced storage.
1714
1740
  */
1715
1741
  formatValue(field) {
1716
- if (!field.isGeoPoint) return;
1717
- return {
1742
+ if (field.isGeoPoint) return {
1718
1743
  toStorage: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number" ? {
1719
1744
  type: "Point",
1720
1745
  coordinates: value
@@ -1724,6 +1749,10 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
1724
1749
  return v && typeof v === "object" && v.type === "Point" && Array.isArray(v.coordinates) ? v.coordinates : value;
1725
1750
  }
1726
1751
  };
1752
+ if (!field.path.includes(".") && isObjectIdColumn(field.type)) return {
1753
+ toStorage: objectIdToStorage,
1754
+ fromStorage: objectIdFromStorage
1755
+ };
1727
1756
  }
1728
1757
  getAdapterTableName(_type) {}
1729
1758
  supportsNativeRelations() {
@@ -2020,7 +2049,7 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2020
2049
  }
2021
2050
  this._log("insertOne", data);
2022
2051
  const result = await this._wrapDuplicateKeyError(() => this.collection.insertOne(data, this._getSessionOpts()));
2023
- return { insertedId: this._resolveInsertedId(data, result.insertedId) };
2052
+ return { insertedId: objectIdFromStorage(this._resolveInsertedId(data, result.insertedId)) };
2024
2053
  }
2025
2054
  async insertMany(data) {
2026
2055
  const versionColumn = this._table.versionColumn;
@@ -2036,7 +2065,7 @@ var MongoAdapter = class MongoAdapter extends _atscript_db.BaseDbAdapter {
2036
2065
  const result = await this._wrapDuplicateKeyError(() => this.collection.insertMany(data, this._getSessionOpts()));
2037
2066
  return {
2038
2067
  insertedCount: result.insertedCount,
2039
- insertedIds: data.map((item, i) => this._resolveInsertedId(item, result.insertedIds[i]))
2068
+ insertedIds: data.map((item, i) => objectIdFromStorage(this._resolveInsertedId(item, result.insertedIds[i])))
2040
2069
  };
2041
2070
  }
2042
2071
  async findOne(query) {
package/dist/index.d.cts CHANGED
@@ -315,6 +315,14 @@ declare class MongoAdapter extends BaseDbAdapter {
315
315
  * write `[lng, lat]` → `{ type: 'Point', coordinates: [lng, lat] }`,
316
316
  * unwrap back to the tuple on read. Non-tuple values (e.g. `$geoWithin`
317
317
  * operator objects flowing through filter translation) pass through.
318
+ *
319
+ * Converts `mongo.objectId` values between wire hex strings and native
320
+ * ObjectId storage. Filters, writes, and reads all flow through these
321
+ * formatters, so id envelopes (`@DbActionID` row loading), FK filters
322
+ * (`{ leadId: '<hex>' }`), and inserted documents match natively stored
323
+ * ObjectIds — and reads return the hex strings the declared type promises.
324
+ * Top-level fields only: nested values skip the write/read formatter passes,
325
+ * so a nested formatter would coerce filters against un-coerced storage.
318
326
  */
319
327
  formatValue(field: TDbFieldMeta): {
320
328
  toStorage: (value: unknown) => unknown;
package/dist/index.d.mts CHANGED
@@ -315,6 +315,14 @@ declare class MongoAdapter extends BaseDbAdapter {
315
315
  * write `[lng, lat]` → `{ type: 'Point', coordinates: [lng, lat] }`,
316
316
  * unwrap back to the tuple on read. Non-tuple values (e.g. `$geoWithin`
317
317
  * operator objects flowing through filter translation) pass through.
318
+ *
319
+ * Converts `mongo.objectId` values between wire hex strings and native
320
+ * ObjectId storage. Filters, writes, and reads all flow through these
321
+ * formatters, so id envelopes (`@DbActionID` row loading), FK filters
322
+ * (`{ leadId: '<hex>' }`), and inserted documents match natively stored
323
+ * ObjectIds — and reads return the hex strings the declared type promises.
324
+ * Top-level fields only: nested values skip the write/read formatter passes,
325
+ * so a nested formatter would coerce filters against un-coerced storage.
318
326
  */
319
327
  formatValue(field: TDbFieldMeta): {
320
328
  toStorage: (value: unknown) => unknown;
package/dist/index.mjs CHANGED
@@ -1547,6 +1547,24 @@ const validateMongoIdPlugin = (ctx, def, value) => {
1547
1547
  };
1548
1548
  //#endregion
1549
1549
  //#region src/lib/mongo-adapter.ts
1550
+ /** Mirrors the `mongo.objectId` primitive's pattern — only definite hex ids convert. */
1551
+ const OBJECT_ID_HEX = /^[a-fA-F0-9]{24}$/;
1552
+ /** True for `mongo.objectId`-typed fields and arrays of them (tag-based, same as `prepareId`). */
1553
+ function isObjectIdColumn(fieldType) {
1554
+ const t = fieldType.type;
1555
+ if (t.kind === "array") return !!t.of && isObjectIdColumn(t.of);
1556
+ return t.tags?.has("objectId") === true && t.tags?.has("mongo") === true;
1557
+ }
1558
+ function objectIdToStorage(value) {
1559
+ if (typeof value === "string" && OBJECT_ID_HEX.test(value)) return new ObjectId(value);
1560
+ if (Array.isArray(value)) return value.map(objectIdToStorage);
1561
+ return value;
1562
+ }
1563
+ function objectIdFromStorage(value) {
1564
+ if (value instanceof ObjectId) return value.toHexString();
1565
+ if (Array.isArray(value)) return value.map(objectIdFromStorage);
1566
+ return value;
1567
+ }
1550
1568
  var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
1551
1569
  db;
1552
1570
  client;
@@ -1710,10 +1728,17 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
1710
1728
  * write `[lng, lat]` → `{ type: 'Point', coordinates: [lng, lat] }`,
1711
1729
  * unwrap back to the tuple on read. Non-tuple values (e.g. `$geoWithin`
1712
1730
  * operator objects flowing through filter translation) pass through.
1731
+ *
1732
+ * Converts `mongo.objectId` values between wire hex strings and native
1733
+ * ObjectId storage. Filters, writes, and reads all flow through these
1734
+ * formatters, so id envelopes (`@DbActionID` row loading), FK filters
1735
+ * (`{ leadId: '<hex>' }`), and inserted documents match natively stored
1736
+ * ObjectIds — and reads return the hex strings the declared type promises.
1737
+ * Top-level fields only: nested values skip the write/read formatter passes,
1738
+ * so a nested formatter would coerce filters against un-coerced storage.
1713
1739
  */
1714
1740
  formatValue(field) {
1715
- if (!field.isGeoPoint) return;
1716
- return {
1741
+ if (field.isGeoPoint) return {
1717
1742
  toStorage: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number" ? {
1718
1743
  type: "Point",
1719
1744
  coordinates: value
@@ -1723,6 +1748,10 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
1723
1748
  return v && typeof v === "object" && v.type === "Point" && Array.isArray(v.coordinates) ? v.coordinates : value;
1724
1749
  }
1725
1750
  };
1751
+ if (!field.path.includes(".") && isObjectIdColumn(field.type)) return {
1752
+ toStorage: objectIdToStorage,
1753
+ fromStorage: objectIdFromStorage
1754
+ };
1726
1755
  }
1727
1756
  getAdapterTableName(_type) {}
1728
1757
  supportsNativeRelations() {
@@ -2019,7 +2048,7 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2019
2048
  }
2020
2049
  this._log("insertOne", data);
2021
2050
  const result = await this._wrapDuplicateKeyError(() => this.collection.insertOne(data, this._getSessionOpts()));
2022
- return { insertedId: this._resolveInsertedId(data, result.insertedId) };
2051
+ return { insertedId: objectIdFromStorage(this._resolveInsertedId(data, result.insertedId)) };
2023
2052
  }
2024
2053
  async insertMany(data) {
2025
2054
  const versionColumn = this._table.versionColumn;
@@ -2035,7 +2064,7 @@ var MongoAdapter = class MongoAdapter extends BaseDbAdapter {
2035
2064
  const result = await this._wrapDuplicateKeyError(() => this.collection.insertMany(data, this._getSessionOpts()));
2036
2065
  return {
2037
2066
  insertedCount: result.insertedCount,
2038
- insertedIds: data.map((item, i) => this._resolveInsertedId(item, result.insertedIds[i]))
2067
+ insertedIds: data.map((item, i) => objectIdFromStorage(this._resolveInsertedId(item, result.insertedIds[i])))
2039
2068
  };
2040
2069
  }
2041
2070
  async findOne(query) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-mongo",
3
- "version": "0.1.121",
3
+ "version": "0.1.122",
4
4
  "description": "Mongodb plugin for atscript.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -56,7 +56,7 @@
56
56
  "@atscript/core": "^0.1.85",
57
57
  "@atscript/typescript": "^0.1.85",
58
58
  "mongodb": "^6.17.0",
59
- "@atscript/db": "^0.1.121"
59
+ "@atscript/db": "^0.1.122"
60
60
  },
61
61
  "scripts": {
62
62
  "postinstall": "asc -f dts",