@owlmeans/mongo-resource 0.1.18-rc.20 → 0.1.18-rc.22

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/README.md CHANGED
@@ -1,27 +1,46 @@
1
1
  # @owlmeans/mongo-resource
2
2
 
3
- MongoDB-backed `Resource<T>` implementation — the primary database resource for OwlMeans server apps.
4
-
5
- ## Overview
6
-
7
- - `makeMongoResource<R, T>(alias, dbAlias?, serviceAlias?, collectionName?)` — factory for MongoDB resources
8
- - `MongoResource<T>` — extends `Resource<T>` with MongoDB collection, indexing, field encryption, code migrations and ObjectId references
9
- - Supports CRUD, criteria queries, sorting and paging, AJV schema validation ($jsonSchema collection validators), and field-level locking (encryption)
10
- - Declared references convert between the string ids records carry and the `ObjectId`s the collection stores — the same way `_id` already does
11
- - Code migrations run automatically at resource initialization, tracked in a per-database `_owlmeans_migrations` ledger
12
- - Used for all persistent data models in server applications
3
+ MongoDB-backed `Resource<T>` for server apps. The AJV schema becomes the collection validator, and
4
+ the package also handles indexes, code migrations and the conversion between string ids and
5
+ `ObjectId`. Use it for documents whose shape varies per record or per tenant and that are read
6
+ whole by id: per-tenant form submissions, generated content documents, compacted agent
7
+ conversations. Postgres, not Mongo, is the default for records you filter, join, sum or report
8
+ across (see [`@owlmeans/postgres-resource`](../postgres-resource)). Expiring or coordinating data
9
+ (sessions, locks, counters, pub/sub) goes in [`@owlmeans/redis-resource`](../redis-resource).
10
+ Client-side records go in [`@owlmeans/state`](../state).
13
11
 
14
12
  ## Installation
15
13
 
16
14
  ```bash
17
- bun add @owlmeans/mongo-resource@^0.1.18-rc.11
15
+ bun add @owlmeans/mongo-resource@^0.1.18-rc.21
18
16
  ```
19
17
 
18
+ `mongodb` and `ajv` are peer dependencies. The connection service comes from
19
+ [`@owlmeans/mongo`](../mongo) (`appendMongo`).
20
+
21
+ ## Concepts
22
+
23
+ - **Resource maker**: a `ResourceMaker<R, T>` function that calls `makeMongoResource`, assigns
24
+ `schema` and declares indexes, references and migrations. The server context factory registers
25
+ its result once with `context.registerResource(makeXResource())`.
26
+ - **Validator**: the resource's AJV schema compiled into a `$jsonSchema` collection validator. It
27
+ is reapplied, and indexes are reconciled, on every boot.
28
+ - **Reference**: a field declared with `reference(field, targetAlias?)` that stores another
29
+ record's id. Records and criteria carry strings, the collection stores `ObjectId`s, and the
30
+ resource converts between them the same way it does for `_id`.
31
+ - **Migration**: a code body registered with `migration(name, apply, stage?)`. It runs once per
32
+ database at `Pre` or `Post` stage around structure reconciliation, and is recorded in the
33
+ `_owlmeans_migrations` ledger.
34
+ - **Declaration**: the module-scope, per-alias store that holds references and migrations. A maker
35
+ called twice for the same alias extends it; the second call does not replace it.
36
+ - **Paged by default**: `list(where)` returns at most `DEFAULT_PAGE_SIZE` (100) documents.
37
+ `{ size: 0 }` explicitly asks for all of them.
38
+
20
39
  ## Usage
21
40
 
22
- Define a resource:
41
+ ### Define and register a resource
23
42
 
24
- ```typescript
43
+ ```ts
25
44
  import { makeMongoResource } from '@owlmeans/mongo-resource'
26
45
  import type { MongoResource } from '@owlmeans/mongo-resource'
27
46
  import type { ResourceMaker } from '@owlmeans/resource'
@@ -32,70 +51,142 @@ export const makeProjectResource: ResourceMaker<ProjectRecord, ProjectResource>
32
51
  const resource = makeMongoResource<ProjectRecord, ProjectResource>(RES_PROJECT, dbAlias, serviceAlias)
33
52
  resource.schema = ProjectSchema
34
53
  resource.index('entity', { entityId: 1 })
35
- resource.index('alias', { alias: 1 })
54
+ resource.index('alias', { entityId: 1, alias: 1 }, { unique: true })
55
+
36
56
  return resource
37
57
  }
38
- ```
39
58
 
40
- Register in context:
41
-
42
- ```typescript
59
+ // in the server context factory, next to appendMongo(context)
43
60
  context.registerResource(makeProjectResource())
44
61
  ```
45
62
 
46
- Use in a handler:
63
+ ### Read and write from a handler
47
64
 
48
- ```typescript
65
+ ```ts
49
66
  const projects = context.resource<ProjectResource>(RES_PROJECT)
50
- const record = await projects.create({ entityId, alias, title })
51
- const one = await projects.load({ entityId, alias })
52
- const page = await projects.list({ entityId }, { page: 0, size: 20, sort: ['createdAt'] })
53
- const open = await projects.count({ status: ['draft', 'active'] })
67
+
68
+ const created = await projects.create({ entityId, alias, title, status: 'draft' })
69
+ const one = await projects.load({ entityId, alias }) // null when absent
70
+ const newest = await projects.get({ entityId }, { sort: [{ field: 'createdAt', order: 'desc' }] })
71
+ const page = await projects.list(
72
+ { entityId, status: ['draft', 'active'] }, // an array means "any of these"
73
+ { page: 0, size: 20, sort: [{ field: 'createdAt', order: 'desc' }] }
74
+ )
75
+ const open = await projects.count({ entityId, status: { $ne: 'archived' } })
76
+
77
+ await projects.update({ ...created, title: 'Renamed' }) // replaces the whole record
78
+ await projects.purge({ entityId, status: 'archived' }) // refuses empty criteria
54
79
  ```
55
80
 
81
+ `entityId` here is the organization's stable record id, taken from `requireEntityKey(req)` in the
82
+ handler, never from the token. Only `entitySlug` travels on the wire.
83
+
84
+ ### References, compound indexes and a domain method
85
+
86
+ A revisioned design document per story, modelled on a real application resource. `current` is a
87
+ domain method the app adds to its own resource interface:
88
+
89
+ ```ts
90
+ export interface DesignResource extends MongoResource<DesignRecord> {
91
+ current: (projectId: string, code: string) => Promise<DesignRecord | null>
92
+ }
93
+
94
+ export const makeDesignResource: ResourceMaker<DesignRecord, DesignResource> = (dbAlias, serviceAlias) => {
95
+ const resource = makeMongoResource<DesignRecord, DesignResource>(RES_DESIGN, dbAlias, serviceAlias)
96
+
97
+ resource.current = async (projectId, code) => {
98
+ const { items } = await resource.list(
99
+ { projectId, code }, { size: 1, sort: [{ field: 'revision', order: 'desc' }] }
100
+ )
101
+
102
+ return items[0] ?? null
103
+ }
104
+
105
+ resource.schema = DesignSchema
106
+ resource.reference('projectId', RES_PROJECT) // stored as ObjectId, indexed ref_projectId
107
+ resource.reference('storyId', RES_STORY)
108
+ resource.index('current', { projectId: 1, code: 1, revision: -1 })
109
+ resource.index('story', { storyId: 1, revision: -1 }, { sparse: true })
110
+
111
+ return resource
112
+ }
113
+ ```
114
+
115
+ `code` is a business key and stays a plain string. Only fields assigned from another record's
116
+ `.id` are references.
117
+
118
+ ### A migration
119
+
120
+ ```ts
121
+ import { MigrationStage } from '@owlmeans/resource'
122
+ import type { MongoTx } from '@owlmeans/mongo-resource'
123
+
124
+ // Module scope, so the checksum fingerprints this body and nothing else.
125
+ const backfillStatus = async (tx: MongoTx) => {
126
+ await tx.collection.updateMany({ status: { $exists: false } }, { $set: { status: 'draft' } })
127
+ }
128
+
129
+ resource.migration('0001-backfill-status', backfillStatus, MigrationStage.Post)
130
+ ```
131
+
132
+ The body receives a `MongoTx` (`db`, `collection`, `use(alias)`, `ref(alias)`) and must be
133
+ idempotent: without transactions an interrupted body can run again.
134
+
135
+ ### Raw driver access with converted references
136
+
137
+ ```ts
138
+ import { marshalReference } from '@owlmeans/mongo-resource'
139
+
140
+ await projects.collection.updateOne(
141
+ { _id: marshalReference('id', projectId) as never, jobSequence },
142
+ { $inc: { jobSequence: 1 }, $set: { updatedAt: new Date() } }
143
+ )
144
+ ```
145
+
146
+ `resource.collection.*` bypasses the conversion layer. Marshal ids yourself, or stay on the
147
+ resource API.
148
+
56
149
  ## API
57
150
 
58
151
  ### `makeMongoResource<R, T>(alias, dbAlias?, serviceAlias?, collectionName?): T`
59
152
 
60
- Creates a MongoDB resource. `dbAlias` defaults to `DEFAULT_DB_ALIAS` (`'mongo'`).
61
- `collectionName` overrides the physical collection name (otherwise `resourcePrefix + alias`).
62
- `migration()` and `reference()` are kept in module-scope declarations keyed by alias, so a
63
- maker that runs more than once for the same alias re-declares the same entries and loses
64
- nothing.
153
+ Creates a MongoDB resource. `dbAlias` and `serviceAlias` default to `DEFAULT_DB_ALIAS` (`'mongo'`).
154
+ `collectionName` overrides the physical collection name (otherwise `resourcePrefix + alias`, limited
155
+ to `[a-zA-Z0-9_-]`). `migration()` and `reference()` are kept in module-scope declarations keyed by
156
+ alias, so a maker that runs more than once for the same alias re-declares the same entries and
157
+ loses nothing.
65
158
 
66
159
  ### `MongoResource<T>`
67
160
 
68
161
  Extends `Resource<T>` with the shared `MigratableResource<MongoTx, MongoResource<T>>` and
69
162
  `LockableResource<T>` capabilities, plus:
70
- - `collection: Collection` — MongoDB collection
163
+ - `collection: Collection`, the MongoDB collection
71
164
  - `db(): Promise<Db>` / `client(): Promise<MongoClient>`
72
- - `index(name, spec, options?): this` — define a collection index
73
- - `reference(field, targetAlias?): this` / `references()` — declare that a field stores another record's id (see below)
74
- - `migration(name, apply, stage?)` / `migrations()` — register a code migration (see below)
75
- - `lock(record, fields?)` / `unlock(record, fields?)` — encrypt/decrypt secure fields
76
- - `getDefaults(): Partial<T>` — default values derived from schema
165
+ - `index(name, spec, options?): this`, which defines a collection index
166
+ - `reference(field, targetAlias?): this` / `references()`, which declare that a field stores another record's id (see below)
167
+ - `migration(name, apply, stage?)` / `migrations()`, which register a code migration (see below)
168
+ - `lock(record, fields?)` / `unlock(record, fields?)`, which encrypt/decrypt `secure: true` schema fields
169
+ - `getDefaults(): Partial<T>`, the default values derived from the schema
170
+ - `dbAlias` / `serviceAlias`, the aliases the resource was registered against
77
171
 
78
172
  ### Criteria, sorting and paging
79
173
 
80
174
  `Criteria<T>` is the portable query shape from [`@owlmeans/resource`](../resource): a bare value
81
175
  is equality, a bare array is "any of these", `null` asks for the absence of a value and
82
176
  `undefined` is skipped so an untouched filter never empties a list. Every operator in the shared
83
- vocabulary — `$eq $ne $gt $gte $lt $lte $in $nin $exists $null $like $ilike $regex $startsWith
84
- $endsWith $between $contains $contained $overlaps`, plus `$and`/`$or`/`$not` — is translated into
85
- the mongo expression that answers the same question, so one criteria object means the same thing
86
- here as it does against Postgres or an in-memory store. `$exists` and `$null` both ask whether the
87
- field *has a value*, not whether the key is present. An operator outside the vocabulary raises
88
- `UnsupportedArgumentError`.
89
-
90
- Paging is per call: `list(where, { page, size, sort })`. Mongo pages by default —
91
- `DEFAULT_PAGE_SIZE` records when no `size` is given — because an unbounded read of a collection is
92
- not something a caller should get by omission. `list(where, { size: 0 })` asks for the whole
93
- result set explicitly. `ListResult.total` is always filled; `page` and `size` come back only when
94
- a limit was applied. `sort` takes field names (ascending) or `{ field, order: 'desc' }`, and `id`
95
- addresses `_id`.
96
-
97
- `criteriaToFilter(criteria, refs)` and `sortToMongo(sort)` are exported for code driving
98
- `resource.collection` directly.
177
+ vocabulary is translated into the Mongo expression that answers the same question, so one criteria
178
+ object means the same thing here as it does against Postgres or an in-memory store. The vocabulary
179
+ is `$eq $ne $gt $gte $lt $lte $in $nin $exists $null $like $ilike $regex $startsWith $endsWith
180
+ $between $contains $contained $overlaps`, plus `$and`/`$or`/`$not`. `$exists` and `$null` both ask
181
+ whether the field *has a value*, not whether the key is present. An operator outside the
182
+ vocabulary raises `UnsupportedArgumentError`.
183
+
184
+ Paging is per call: `list(where, { page, size, sort })`. Mongo pages by default and returns
185
+ `DEFAULT_PAGE_SIZE` records when no `size` is given, because a caller should not get an unbounded
186
+ read of a collection by omission. `list(where, { size: 0 })` asks for the whole result set
187
+ explicitly, and a `page` without a `size` raises `UnsupportedArgumentError('page-without-size')`.
188
+ `ListResult.total` is always filled; `page` and `size` come back only when a limit was applied.
189
+ `sort` takes field names (ascending) or `{ field, order: 'desc' }`, and `id` addresses `_id`.
99
190
 
100
191
  ### ObjectId references
101
192
 
@@ -103,62 +194,97 @@ addresses `_id`.
103
194
  The resource then treats the field exactly like `_id`:
104
195
 
105
196
  - Records and criteria carry **strings**; the collection stores **`ObjectId`s**. Conversion is
106
- automatic on every read, write and lookup — including `$in`-style operator objects,
197
+ automatic on every read, write and lookup, including `$in`-style operator objects,
107
198
  `$and`/`$or`/`$nor` branches and arrays of ids. `id` criteria are mapped onto `_id`.
108
- - Writes are strict (a non-24-hex value throws `MisshapedRecord`); reads and criteria are
109
- tolerant (a non-id value simply matches nothing).
110
- - The field gets a mongo-level index (`ref_<field>`) automatically, unless an index with the
199
+ - Writes are strict: a non-24-hex value throws `MisshapedRecord`. Reads and criteria are tolerant:
200
+ a non-id value simply matches nothing.
201
+ - The field gets a Mongo-level index (`ref_<field>`) automatically, unless an index with the
111
202
  identical key pattern is already declared, and the collection validator declares it
112
203
  `objectId`.
113
- - Declaring a reference registers the system migration `$ref:<field>@1` (pre stage) that
114
- converts pre-existing string ids in place — idempotent and interrupt-safe. On every boot
115
- the collection is additionally probed for convertible strings and repaired if the ledger
116
- and the data disagree (the double check). Conversion bypasses document validation, which
117
- requires the `bypassDocumentValidation` privilege (`dbOwner`/`root` hold it).
118
- - Only declare fields whose values really are another record's `id`. Business keys, composite
119
- keys, external provider ids and slugs must stay strings — converting them corrupts data.
120
- - Raw `resource.collection.*` access bypasses the conversion: marshal filter values with
121
- `marshalReference(field, value)` and convert read-back ids to strings yourself.
204
+ - Declaring a reference registers the system migration `$ref:<field>@1` (pre stage), which
205
+ converts pre-existing string ids in place and is idempotent and interrupt-safe. On every boot
206
+ the collection is also probed for convertible strings and repaired if the ledger and the data
207
+ disagree (the double check). Conversion bypasses document validation, which requires the
208
+ `bypassDocumentValidation` privilege (`dbOwner`/`root` hold it).
122
209
 
123
210
  ### Migrations
124
211
 
125
- `migration(name, apply, stage?)` registers a code migration, applied once per database in
126
- declaration order and recorded in the `_owlmeans_migrations` collection (one ledger per
127
- database, so each database tracks its own).
212
+ `migration(name, apply, stage?)` registers a code migration. It is applied once per database, in
213
+ declaration order, and recorded in the `_owlmeans_migrations` collection. The ledger is per
214
+ database, so each database tracks its own.
128
215
 
129
216
  - `MigrationStage.Pre` runs before the validator/index update, `Post` after. On a collection
130
217
  created by this very boot, registered migrations are **baselined** (recorded, not run).
131
- - Bodies receive a `MongoTx` (`db`, `collection`, `use(alias)`, `ref(alias)`) and must be
132
- **idempotent** — multi-document transactions are unavailable on a standalone `mongod`, so
133
- the ledger claims-then-completes and an interrupted body may re-run.
134
- - The checksum fingerprints the body's source text: keep bodies at module scope; an edited
135
- applied body raises `MigrationConflict` at boot.
218
+ - A replica that loses the race to claim a migration waits for the winner (up to
219
+ `DEF_MIGRATION_WAIT`), and a failed body withdraws its claim so the next boot retries.
136
220
 
137
221
  ### `Resource<T>` methods (all implemented)
138
222
 
139
223
  `get`, `load`, `list`, `count`, `create`, `update`, `save`, `delete`, `take`, `purge`
140
224
 
141
225
  - `get`/`load` take either an id or a `Criteria<T>` with an optional `{ sort }`; `get` throws
142
- `UnknownRecordError` where `load` answers `null`. An id that is not a mongo id finds nothing
226
+ `UnknownRecordError` where `load` answers `null`. An id that is not a Mongo id finds nothing
143
227
  rather than raising a driver error.
144
- - `update` replaces the whole record addressed by its `id`; `save` creates when the record
145
- carries no id and replaces otherwise.
228
+ - `create` refuses a caller-supplied id (`RecordExists`). `update` replaces the whole record
229
+ addressed by its `id`; `save` creates when the record carries no id and replaces otherwise.
146
230
  - `delete(id)` and `take(id)` remove atomically through `findOneAndDelete` and hand the record
147
- back — `take` throws `UnknownRecordError` on absence where `delete` answers `null`.
231
+ back. `take` throws `UnknownRecordError` on absence where `delete` answers `null`.
148
232
  - `purge(where)` is the bulk delete; it refuses an empty criteria object rather than emptying
149
233
  the collection.
150
- - `ttl` is refused with `UnsupportedArgumentError` — a collection has no per-record expiry.
151
-
152
- ### Constants
153
-
154
- - `DEFAULT_DB_ALIAS` — `'mongo'`
155
- - `DEFAULT_PAGE_SIZE` — `100`
156
- - `DEF_MIGRATIONS_COLLECTION` — `'_owlmeans_migrations'`
157
-
158
- ## Related Packages
159
-
160
- - [`@owlmeans/resource`](../resource) — `Resource<T>`, `ResourceRecord`, `ResourceMaker` base
161
- - [`@owlmeans/mongo`](../mongo) — MongoDB connection service required by this package
234
+ - `ttl` is refused with `UnsupportedArgumentError`, because a collection has no per-record expiry.
235
+
236
+ ### Exports
237
+
238
+ | Symbol | Kind | Purpose |
239
+ |---|---|---|
240
+ | `makeMongoResource` | function | The resource factory |
241
+ | `MongoResource<T>` | type | The resource interface described above |
242
+ | `MongoDbService` | type | Connection service contract implemented by `@owlmeans/mongo` |
243
+ | `MongoTx` | type | Façade handed to migration bodies: `db`, `collection`, `use(alias)`, `ref(alias)` |
244
+ | `MongoReference`, `MongoRefOptions` | type | A declared reference and the `reference()` options (`resource`, `noIndex`) |
245
+ | `criteriaToFilter(criteria, refs)` | function | `Criteria<T>` to a Mongo filter, with references converted |
246
+ | `sortToMongo(sort)` | function | `Sort<T>[]` to a Mongo sort document (`id` becomes `_id`) |
247
+ | `marshalReference(field, value)` | function | String id(s) to `ObjectId` for a write; throws `MisshapedRecord` on non-ids |
248
+ | `demarshalReference(value)`, `demarshalRefs(record, refs)` | function | `ObjectId` back to strings for one value or a whole document |
249
+ | `marshalCriteria(filter, refs)`, `identityCriteria(field, id, refs)` | function | Convert a Mongo filter's id-addressed values; build a single-record lookup |
250
+ | `isObjectIdHex(value)` | function | Strict 24-hex test used by the conversion layer |
251
+ | `convertReferenceField`, `makeRefMigration`, `reconcileReferences`, `refMigrationName` | function | The system reference migration and its boot-time probe |
252
+ | `makeMongoTx`, `makeMongoMigrationStore` | function | The migration façade and the ledger implementation |
253
+ | `getDeclaration(alias)`, `resetDeclarations(alias?)`, `MongoDeclaration` | function / type | Module-scope per-alias declarations; `resetDeclarations` is the testing seam |
254
+ | `getSchemaSecureFeilds(schema)` | function | The `secure: true` properties `lock`/`unlock` use when no fields are named |
255
+ | `DEFAULT_DB_ALIAS` | const | `'mongo'` |
256
+ | `DEFAULT_PAGE_SIZE` | const | `100` |
257
+ | `DEF_MIGRATIONS_COLLECTION` | const | `'_owlmeans_migrations'` |
258
+ | `DEF_MIGRATION_WAIT`, `DEF_MIGRATION_POLL` | const | How long (60 000 ms) and how often (250 ms) a replica waits for another's migration |
259
+ | `MONGO_DUPLICATE_KEY` | const | `11000`, the driver's duplicate-key code |
260
+
261
+ ## Common pitfalls
262
+
263
+ - **Declaring a non-id field as a reference.** `entityId`/`entitySlug` (the organization entity),
264
+ composite keys such as `profileId`, provider ids (Stripe, GitHub), slugs, aliases and codes must
265
+ stay strings. Converting them corrupts the collection and breaks unique indexes.
266
+ - **Two indexes over the same keys.** Mongo refuses them. Declare the index yourself under the key
267
+ pattern a reference would use and the automatic `ref_<field>` index is skipped.
268
+ - **Non-idempotent migration bodies.** There are no multi-document transactions on a standalone
269
+ `mongod`, so an interrupted body re-runs.
270
+ - **Editing an applied migration**, or defining its body inside a loop or closure. The checksum
271
+ fingerprints source text, so the boot fails with `MigrationConflict`.
272
+ - **A `Pre` body that `$unset`s a field under a unique index.** Indexes reconcile *after* `Pre`, so
273
+ the old index is still enforcing and the second document fails with E11000. Drop the stale index
274
+ in the body first.
275
+ - **Expecting `update` to merge.** It replaces the whole document. Pass every field that must survive.
276
+ - **Reading "everything" with `list(where)`.** It stops at 100. Ask with `{ size: 0 }`, or page.
277
+ - **Raw `resource.collection` calls with string ids.** They match nothing against `ObjectId`
278
+ fields. Use `marshalReference`.
279
+ - **Passing `{ ttl }`.** It is refused. Expiring records belong in Redis.
280
+
281
+ ## Related packages
282
+
283
+ - [`@owlmeans/mongo`](../mongo): the MongoDB connection service this package resolves through
284
+ - [`@owlmeans/resource`](../resource): `Resource<T>`, criteria, `ResourceMaker`, the migration framework, errors
285
+ - [`@owlmeans/postgres-resource`](../postgres-resource): the relational counterpart and the default choice
286
+ - [`@owlmeans/redis-resource`](../redis-resource): expiring, cached and pub/sub data
287
+ - [`@owlmeans/server-context`](../server-context): the server context resources register on
162
288
 
163
289
  <!-- owlmeans:agent-guidance:start -->
164
290
  ## Agent guidance
@@ -168,7 +294,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
168
294
  your project's skill store (`.agents/skills/`):
169
295
 
170
296
  ```sh
171
- npx @owlmeans/agent-skills@^0.1.18-rc.20
297
+ npx @owlmeans/agent-skills@^0.1.18-rc.22
172
298
  ```
173
299
 
174
300
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/mongo-resource",
4
- "version": "0.1.18-rc.20",
5
- "generatedAt": "2026-09-12T14:21:25.463Z",
4
+ "version": "0.1.18-rc.22",
5
+ "generatedAt": "2026-09-15T12:38:15.178Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/mongo-resource
9
9
 
10
10
  **Layer:** Infra
11
- **Install:** `"@owlmeans/mongo-resource": "^0.1.18-rc.20"` in `dependencies` (peers `mongodb`, `ajv`)
11
+ **Install:** `"@owlmeans/mongo-resource": "^0.1.18-rc.22"` in `dependencies` (peers `mongodb`, `ajv`)
12
12
 
13
13
  The Mongo counterpart of [[postgres-resource]]. A collection has no structure of its own, so
14
14
  here the resource layer owns the *validator* (`$jsonSchema` from the AJV schema), the indexes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/mongo-resource",
3
- "version": "0.1.18-rc.20",
3
+ "version": "0.1.18-rc.22",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -26,13 +26,13 @@
26
26
  "mongodb": "*"
27
27
  },
28
28
  "dependencies": {
29
- "@owlmeans/context": "^0.1.18-rc.16",
30
- "@owlmeans/resource": "^0.1.18-rc.17",
31
- "@owlmeans/server-context": "^0.1.18-rc.20"
29
+ "@owlmeans/context": "^0.1.18-rc.18",
30
+ "@owlmeans/resource": "^0.1.18-rc.19",
31
+ "@owlmeans/server-context": "^0.1.18-rc.22"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@owlmeans/dep-config": "workspace:*",
35
- "@owlmeans/test-integration": "^0.1.18-rc.16",
35
+ "@owlmeans/test-integration": "^0.1.18-rc.18",
36
36
  "@types/bun": "^1.4.0",
37
37
  "@types/node": "^26.1.0",
38
38
  "mongodb": "^7.5.0",