@furystack/mongodb-store 11.0.0 → 11.0.2
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/CHANGELOG.md +28 -0
- package/esm/define-mongodb-store.d.ts +1 -7
- package/esm/define-mongodb-store.d.ts.map +1 -1
- package/esm/define-mongodb-store.js.map +1 -1
- package/esm/mongo-client-factory.d.ts.map +1 -1
- package/esm/mongo-client-factory.js.map +1 -1
- package/esm/mongodb-store.d.ts +13 -1
- package/esm/mongodb-store.d.ts.map +1 -1
- package/esm/mongodb-store.js +15 -2
- package/esm/mongodb-store.js.map +1 -1
- package/package.json +8 -8
- package/src/define-mongodb-store.ts +2 -8
- package/src/mongo-client-factory.ts +2 -0
- package/src/mongodb-store.ts +18 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [11.0.2] - 2026-06-05
|
|
4
|
+
|
|
5
|
+
### 👷 CI
|
|
6
|
+
|
|
7
|
+
- Raised the minimum supported Node.js to `>=24.0.0` (Node 24 LTS) in `engines`, dropping Node 22.
|
|
8
|
+
|
|
9
|
+
### ⬆️ Dependencies
|
|
10
|
+
|
|
11
|
+
- Bumped dev `vitest` to `^4.1.8`. No source changes — dev-tooling bump only.
|
|
12
|
+
|
|
13
|
+
## [11.0.1] - 2026-05-21
|
|
14
|
+
|
|
15
|
+
### ♻️ Refactoring
|
|
16
|
+
|
|
17
|
+
### `update` throws `NotFoundError` for missing entities
|
|
18
|
+
|
|
19
|
+
`MongodbStore.update` now throws `NotFoundError` from `@furystack/core` (instead of a plain `Error`) when no document matches the given id. Callers can branch on `instanceof NotFoundError` without parsing messages. The message was tightened from `... cannot update!` to `... cannot update` — substring matches that look for `cannot update` keep working.
|
|
20
|
+
|
|
21
|
+
### ⬆️ Dependencies
|
|
22
|
+
|
|
23
|
+
- Bump `mongodb` to `7.2.0`.
|
|
24
|
+
- Bump dev `vitest` to `^4.1.5`.
|
|
25
|
+
- Bumped `@types/node` to `^25.9.1` and `vitest` to `^4.1.7`. No source changes — dev-tooling bump only.
|
|
26
|
+
|
|
27
|
+
### 📚 Documentation
|
|
28
|
+
|
|
29
|
+
- Rewrote JSDoc on `MongodbStore`, `defineMongodbStore`, and `MongoClientFactory` to follow the new value-test guidance: dropped restate-the-type narration, called out the lazy-init contract, the `_id`/`ObjectId` coercion behavior, and the fact that the store has no `[Symbol.asyncDispose]` because client lifetime belongs to the factory.
|
|
30
|
+
|
|
3
31
|
## [11.0.0] - 2026-04-25
|
|
4
32
|
|
|
5
33
|
### 💥 Breaking Changes
|
|
@@ -4,19 +4,13 @@ import type { MongoClientOptions } from 'mongodb';
|
|
|
4
4
|
* Options accepted by {@link defineMongoDbStore}.
|
|
5
5
|
*/
|
|
6
6
|
export type DefineMongoDbStoreOptions<T extends object, TPrimaryKey extends keyof T> = {
|
|
7
|
-
/** Human-readable token name used for debug/readability. */
|
|
8
7
|
name: string;
|
|
9
|
-
/** Entity model constructor. */
|
|
10
8
|
model: Constructable<T>;
|
|
11
|
-
/** Primary key field name. */
|
|
12
9
|
primaryKey: TPrimaryKey;
|
|
13
|
-
/** MongoDB deployment URL (e.g. `mongodb://localhost:27017`). */
|
|
10
|
+
/** MongoDB deployment URL (e.g. `mongodb://localhost:27017`) — also acts as the pool key. */
|
|
14
11
|
url: string;
|
|
15
|
-
/** MongoDB database name. */
|
|
16
12
|
db: string;
|
|
17
|
-
/** MongoDB collection name. */
|
|
18
13
|
collection: string;
|
|
19
|
-
/** Optional {@link MongoClientOptions}. */
|
|
20
14
|
options?: MongoClientOptions;
|
|
21
15
|
};
|
|
22
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-mongodb-store.d.ts","sourceRoot":"","sources":["../src/define-mongodb-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEhE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"define-mongodb-store.d.ts","sourceRoot":"","sources":["../src/define-mongodb-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEhE,OAAO,KAAK,EAAe,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAI9D;;GAEG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,CAAC,IAAI;IACrF,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IACvB,UAAU,EAAE,WAAW,CAAA;IACvB,6FAA6F;IAC7F,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,WAAW,SAAS,MAAM,CAAC,EACpF,SAAS,yBAAyB,CAAC,CAAC,EAAE,WAAW,CAAC,KACjD,UAAU,CAAC,CAAC,EAAE,WAAW,CAexB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-mongodb-store.js","sourceRoot":"","sources":["../src/define-mongodb-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"define-mongodb-store.js","sourceRoot":"","sources":["../src/define-mongodb-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAgBjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAkD,EACtB,EAAE,CAC9B,WAAW,CAAiB;IAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAC1C,OAAO,IAAI,YAAY,CAAiB;YACtC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC;SACtE,CAAC,CAAA;IACJ,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-client-factory.d.ts","sourceRoot":"","sources":["../src/mongo-client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"mongo-client-factory.d.ts","sourceRoot":"","sources":["../src/mongo-client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIrC;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAAA;CACrE;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,EAAE,WAAW,CAqBpE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-client-factory.js","sourceRoot":"","sources":["../src/mongo-client-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"mongo-client-factory.js","sourceRoot":"","sources":["../src/mongo-client-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAgBrC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2C,aAAa,CAAC;IACtF,IAAI,EAAE,6CAA6C;IACnD,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;QACzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAA;QAClD,SAAS,CAAC,KAAK,IAAI,EAAE;YACnB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACtE,WAAW,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC,CAAC,CAAA;QACF,OAAO;YACL,YAAY,CAAC,GAAW,EAAE,OAA4B;gBACpD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACrC,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAA;gBACjB,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;gBAC5C,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;gBAC5B,OAAO,MAAM,CAAA;YACf,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
|
package/esm/mongodb-store.d.ts
CHANGED
|
@@ -2,7 +2,19 @@ import type { Constructable, CreateResult, FilterType, FindOptions, PartialResul
|
|
|
2
2
|
import { EventHub } from '@furystack/utils';
|
|
3
3
|
import type { Collection, MongoClient } from 'mongodb';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* {@link PhysicalStore} backed by a MongoDB collection.
|
|
6
|
+
*
|
|
7
|
+
* The collection handle is resolved lazily on the first call via
|
|
8
|
+
* {@link getCollection}; if the primary key is not `_id` a unique index is
|
|
9
|
+
* created on it during init. Init failure clears the cached promise so the
|
|
10
|
+
* next call retries.
|
|
11
|
+
*
|
|
12
|
+
* When `primaryKey` is `_id`, string keys are transparently coerced to
|
|
13
|
+
* `ObjectId` for filters and back to hex strings on results so callers can
|
|
14
|
+
* stay in plain string-key territory.
|
|
15
|
+
*
|
|
16
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
17
|
+
* {@link MongoClientFactory}, which closes pooled clients on injector teardown.
|
|
6
18
|
*/
|
|
7
19
|
export declare class MongodbStore<T extends object, TPrimaryKey extends keyof T, TWriteableData = WithOptionalId<T, TPrimaryKey>> extends EventHub<{
|
|
8
20
|
onEntityAdded: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb-store.d.ts","sourceRoot":"","sources":["../src/mongodb-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"mongodb-store.d.ts","sourceRoot":"","sources":["../src/mongodb-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAU,WAAW,EAAkC,MAAM,SAAS,CAAA;AAS9F;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAY,CACvB,CAAC,SAAS,MAAM,EAChB,WAAW,SAAS,MAAM,CAAC,EAC3B,cAAc,GAAG,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC,CAE/C,SAAQ,QAAQ,CAAC;IACf,aAAa,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;IAC5B,eAAe,EAAE;QAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC3D,eAAe,EAAE;QAAE,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;CACzC,CACD,YAAW,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,cAAc,CAAC;IA+EtD,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7E1B,SAAgB,UAAU,EAAE,WAAW,CAAA;IACvC,SAAgB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IACvC,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,UAAU,CAAC,CAAe;IAElC,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,WAAW;IA0BN,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAUtC,oBAAoB;gBAgBf,OAAO,EAAE;QACxB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;QACvB,UAAU,EAAE,WAAW,CAAA;QACvB,EAAE,EAAE,MAAM,CAAA;QACV,UAAU,EAAE,MAAM,CAAA;QAClB,WAAW,EAAE,MAAM,WAAW,CAAA;KAC/B;IAOU,GAAG,CAAC,GAAG,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAmB3D,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3D,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAK9C,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAC9C,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAe5C,OAAO,CAAC,aAAa;IAOR,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAOzE,MAAM,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAKnE"}
|
package/esm/mongodb-store.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NotFoundError } from '@furystack/core';
|
|
1
2
|
import { EventHub } from '@furystack/utils';
|
|
2
3
|
import { ObjectId } from 'mongodb';
|
|
3
4
|
// Improved type safety for hasObjectId
|
|
@@ -5,7 +6,19 @@ const hasObjectId = (value) => {
|
|
|
5
6
|
return value && typeof value === 'object' && value._id instanceof ObjectId;
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
+
* {@link PhysicalStore} backed by a MongoDB collection.
|
|
10
|
+
*
|
|
11
|
+
* The collection handle is resolved lazily on the first call via
|
|
12
|
+
* {@link getCollection}; if the primary key is not `_id` a unique index is
|
|
13
|
+
* created on it during init. Init failure clears the cached promise so the
|
|
14
|
+
* next call retries.
|
|
15
|
+
*
|
|
16
|
+
* When `primaryKey` is `_id`, string keys are transparently coerced to
|
|
17
|
+
* `ObjectId` for filters and back to hex strings on results so callers can
|
|
18
|
+
* stay in plain string-key territory.
|
|
19
|
+
*
|
|
20
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
21
|
+
* {@link MongoClientFactory}, which closes pooled clients on injector teardown.
|
|
9
22
|
*/
|
|
10
23
|
export class MongodbStore extends EventHub {
|
|
11
24
|
options;
|
|
@@ -107,7 +120,7 @@ export class MongodbStore extends EventHub {
|
|
|
107
120
|
const collection = await this.getCollection();
|
|
108
121
|
const updateResult = await collection.updateOne(this.createIdFilter(id), { $set: data });
|
|
109
122
|
if (updateResult.matchedCount < 1) {
|
|
110
|
-
throw
|
|
123
|
+
throw new NotFoundError(`Entity not found with id '${String(id)}', cannot update`);
|
|
111
124
|
}
|
|
112
125
|
this.emit('onEntityUpdated', { id, change: data });
|
|
113
126
|
}
|
package/esm/mongodb-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb-store.js","sourceRoot":"","sources":["../src/mongodb-store.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"mongodb-store.js","sourceRoot":"","sources":["../src/mongodb-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furystack/mongodb-store",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.2",
|
|
4
4
|
"description": "MongoDB Store implementation for FuryStack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/furystack/furystack",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@furystack/core": "^17.
|
|
42
|
-
"@furystack/inject": "^13.0.
|
|
43
|
-
"@furystack/utils": "^9.0.
|
|
44
|
-
"mongodb": "7.
|
|
41
|
+
"@furystack/core": "^17.1.1",
|
|
42
|
+
"@furystack/inject": "^13.0.2",
|
|
43
|
+
"@furystack/utils": "^9.0.2",
|
|
44
|
+
"mongodb": "7.2.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^25.
|
|
47
|
+
"@types/node": "^25.9.1",
|
|
48
48
|
"typescript": "^6.0.3",
|
|
49
|
-
"vitest": "^4.1.
|
|
49
|
+
"vitest": "^4.1.8"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
|
-
"node": ">=
|
|
52
|
+
"node": ">=24.0.0"
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false
|
|
55
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Constructable, StoreToken } from '@furystack/core'
|
|
2
2
|
import { defineStore } from '@furystack/core'
|
|
3
|
-
import type { MongoClientOptions } from 'mongodb'
|
|
3
|
+
import type { MongoClient, MongoClientOptions } from 'mongodb'
|
|
4
4
|
import { MongoClientFactory } from './mongo-client-factory.js'
|
|
5
5
|
import { MongodbStore } from './mongodb-store.js'
|
|
6
6
|
|
|
@@ -8,19 +8,13 @@ import { MongodbStore } from './mongodb-store.js'
|
|
|
8
8
|
* Options accepted by {@link defineMongoDbStore}.
|
|
9
9
|
*/
|
|
10
10
|
export type DefineMongoDbStoreOptions<T extends object, TPrimaryKey extends keyof T> = {
|
|
11
|
-
/** Human-readable token name used for debug/readability. */
|
|
12
11
|
name: string
|
|
13
|
-
/** Entity model constructor. */
|
|
14
12
|
model: Constructable<T>
|
|
15
|
-
/** Primary key field name. */
|
|
16
13
|
primaryKey: TPrimaryKey
|
|
17
|
-
/** MongoDB deployment URL (e.g. `mongodb://localhost:27017`). */
|
|
14
|
+
/** MongoDB deployment URL (e.g. `mongodb://localhost:27017`) — also acts as the pool key. */
|
|
18
15
|
url: string
|
|
19
|
-
/** MongoDB database name. */
|
|
20
16
|
db: string
|
|
21
|
-
/** MongoDB collection name. */
|
|
22
17
|
collection: string
|
|
23
|
-
/** Optional {@link MongoClientOptions}. */
|
|
24
18
|
options?: MongoClientOptions
|
|
25
19
|
}
|
|
26
20
|
|
|
@@ -3,6 +3,8 @@ import { defineService } from '@furystack/inject'
|
|
|
3
3
|
import type { MongoClientOptions } from 'mongodb'
|
|
4
4
|
import { MongoClient } from 'mongodb'
|
|
5
5
|
|
|
6
|
+
import type { defineMongoDbStore } from './define-mongodb-store.js'
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Pools {@link MongoClient} instances by URL so every store that targets the
|
|
8
10
|
* same MongoDB deployment shares a single connection.
|
package/src/mongodb-store.ts
CHANGED
|
@@ -7,9 +7,11 @@ import type {
|
|
|
7
7
|
PhysicalStore,
|
|
8
8
|
WithOptionalId,
|
|
9
9
|
} from '@furystack/core'
|
|
10
|
+
import { NotFoundError } from '@furystack/core'
|
|
10
11
|
import { EventHub } from '@furystack/utils'
|
|
11
|
-
import type { Collection, Filter, MongoClient, OptionalUnlessRequiredId, Sort
|
|
12
|
+
import type { Collection, Filter, MongoClient, OptionalUnlessRequiredId, Sort } from 'mongodb'
|
|
12
13
|
import { ObjectId } from 'mongodb'
|
|
14
|
+
import type { MongoClientFactory } from './mongo-client-factory.js'
|
|
13
15
|
|
|
14
16
|
// Improved type safety for hasObjectId
|
|
15
17
|
const hasObjectId = <T extends { _id?: unknown }>(value: T): value is T & { _id: ObjectId } => {
|
|
@@ -17,7 +19,19 @@ const hasObjectId = <T extends { _id?: unknown }>(value: T): value is T & { _id:
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
22
|
+
* {@link PhysicalStore} backed by a MongoDB collection.
|
|
23
|
+
*
|
|
24
|
+
* The collection handle is resolved lazily on the first call via
|
|
25
|
+
* {@link getCollection}; if the primary key is not `_id` a unique index is
|
|
26
|
+
* created on it during init. Init failure clears the cached promise so the
|
|
27
|
+
* next call retries.
|
|
28
|
+
*
|
|
29
|
+
* When `primaryKey` is `_id`, string keys are transparently coerced to
|
|
30
|
+
* `ObjectId` for filters and back to hex strings on results so callers can
|
|
31
|
+
* stay in plain string-key territory.
|
|
32
|
+
*
|
|
33
|
+
* The store has no `[Symbol.asyncDispose]` — client lifetime belongs to
|
|
34
|
+
* {@link MongoClientFactory}, which closes pooled clients on injector teardown.
|
|
21
35
|
*/
|
|
22
36
|
export class MongodbStore<
|
|
23
37
|
T extends object,
|
|
@@ -142,9 +156,9 @@ export class MongodbStore<
|
|
|
142
156
|
|
|
143
157
|
public async update(id: T[TPrimaryKey], data: Partial<T>): Promise<void> {
|
|
144
158
|
const collection = await this.getCollection()
|
|
145
|
-
const updateResult = await collection.updateOne(this.createIdFilter(id), { $set: data }
|
|
159
|
+
const updateResult = await collection.updateOne(this.createIdFilter(id), { $set: data })
|
|
146
160
|
if (updateResult.matchedCount < 1) {
|
|
147
|
-
throw
|
|
161
|
+
throw new NotFoundError(`Entity not found with id '${String(id)}', cannot update`)
|
|
148
162
|
}
|
|
149
163
|
this.emit('onEntityUpdated', { id, change: data })
|
|
150
164
|
}
|