@nxgt/mongo-kit 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Steve Tsala
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,273 @@
1
+ # @nxgt/mongo-kit
2
+
3
+ An application's MongoDB in one object: a configuration checked once, the
4
+ clients it needs opened from it, and every collection of
5
+ [`@nxgt/mongo`](https://www.npmjs.com/package/@nxgt/mongo) typed on the
6
+ database it lives in.
7
+
8
+ ```ts
9
+ import { createKit, defineConfig } from '@nxgt/mongo-kit';
10
+ import * as collections from './models'; // every `defineCollection` of the app
11
+
12
+ export const kit = await createKit(
13
+ defineConfig({ uri: process.env.MONGO_URI!, collections }),
14
+ );
15
+
16
+ const user = await kit.db.users.create({ email: 'ada@example.com' });
17
+ const posts = await kit.db.posts.findMany({ filter: { authorId: user._id } });
18
+ await kit.db.command({ ping: 1 }); // the driver's Db, untouched
19
+ ```
20
+
21
+ `kit.db` is the driver's `Db` with the collections on it: `db.users` is the
22
+ typed collection `getCollection(db, users)` gives, and everything a `Db`
23
+ answers to is still there. Nothing else has to be wired: no `getCollection`
24
+ at each call site, no client to pass around, no session to thread by hand.
25
+
26
+ > **0.x, on `@nxgt/mongo`.** The API is still settling.
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ bun add @nxgt/mongo-kit @nxgt/mongo mongodb zod
32
+ ```
33
+
34
+ - `@nxgt/mongo`: required peer. The collections, their options and their
35
+ behaviour are its; this package wires them.
36
+ - `mongodb` `>=7.0.0 <8`: required peer, as `@nxgt/mongo` needs it. `zod` is
37
+ `@nxgt/mongo`'s.
38
+ - `typescript` 6: required peer, the version every `@nxgt` package pins.
39
+ - Tested against MongoDB 8.2. A **replica set** only for transactions, which
40
+ is MongoDB's own rule.
41
+
42
+ ## The collections
43
+
44
+ They come from a module object — one import, and every type follows:
45
+
46
+ ```ts
47
+ // src/models/index.ts
48
+ export * from './users.model';
49
+ export * from './posts.model';
50
+
51
+ // src/db.ts
52
+ import * as collections from './models';
53
+ ```
54
+
55
+ Each export that is a `defineCollection` becomes a key on the scope, under
56
+ the name it is exported by; anything else in the module — a function, a
57
+ constant, a type — is left where it is. The key is the name the application
58
+ reads (`db.users`), and the collection's own `name` is the one on the server,
59
+ so `export const users = defineCollection({ name: 'app_users', … })` is
60
+ `db.users` here and `app_users` there. Two exports on one server collection
61
+ are refused: two keys writing to the same place is a mistake, not a feature.
62
+
63
+ For a **script** — a sync or a migration run from the repository — the files
64
+ can be read from disk instead:
65
+
66
+ ```ts
67
+ import { syncCollections } from '@nxgt/mongo';
68
+ import { discoverCollections } from '@nxgt/mongo-kit';
69
+
70
+ const definitions = await discoverCollections({ glob: 'src/**/*.model.ts' });
71
+ await syncCollections(db, definitions); // `db` from connectMongo, say
72
+ ```
73
+
74
+ It gives `@nxgt/mongo`'s `AnyCollectionDefinition[]`, **with no types**: a
75
+ glob is read at run time, so a bundler cannot follow it and the compiler sees
76
+ nothing. It **runs under Bun** — the glob is `Bun.Glob` — and it imports each
77
+ file it finds, so their top level runs. It is for scripts, never for the
78
+ wiring of an application.
79
+
80
+ ## Several databases
81
+
82
+ They name themselves, and `kit.databases` reads them:
83
+
84
+ ```ts
85
+ export const kit = await createKit(
86
+ defineConfig({
87
+ databases: {
88
+ main: { uri: process.env.MONGO_URI!, collections },
89
+ analytics: { uri: process.env.ANALYTICS_URI!, collections: events },
90
+ },
91
+ }),
92
+ );
93
+
94
+ await kit.databases.main.users.create({ email: 'ada@example.com' });
95
+ await kit.databases.analytics.events.create({ kind: 'signup' });
96
+ ```
97
+
98
+ `kit.db` is then `never`: with two databases there is no “the” database, and
99
+ the name is what says which — and reading it anyway, from JavaScript or
100
+ across an `any`, throws. A single database is named `default`, so
101
+ `kit.databases.default` and `kit.clients.default` are the long way of writing
102
+ the same thing, and `sync()` reports under that key.
103
+
104
+ Two databases on one URI share one client, which is what `connectMongo`
105
+ already does; their `clientOptions` must then be identical, since the second
106
+ hold on a client opened with other options is refused.
107
+
108
+ ## The actor and the session
109
+
110
+ ```ts
111
+ await kit.as(userId).db.posts.create({ title: 'a' }); // stamps createdBy
112
+
113
+ await kit.as(userId).transaction(async (tx) => {
114
+ const team = await tx.db.teams.create({ name: 'Core' });
115
+ await tx.db.users.update(userId, { teamId: team._id });
116
+ });
117
+ ```
118
+
119
+ `as` and `withSession` give back **another kit** over the same clients: the
120
+ one they came from is unchanged, so a request's kit never leaks into the
121
+ next. The collections are built on the first read and kept, so a request
122
+ pays for the collections it touches and no others.
123
+
124
+ `transaction` runs the body with a kit whose collections are all in the
125
+ session — nothing has to be passed. **The driver retries the body from the
126
+ start** on a transient error, so it must be safe to run twice: keep side
127
+ effects that are not MongoDB's out of it. A transaction inside a transaction
128
+ **joins** the outer one, and takes no `{ on }`, since the session already
129
+ decided; MongoDB has no savepoints, so an inner failure takes the whole
130
+ transaction with it.
131
+
132
+ With several clients, `{ on: 'main' }` says whose, since a transaction lives
133
+ on one client — and inside that body only the databases on that client can be
134
+ used: an operation on another one carries a session its client does not own,
135
+ and the driver refuses it.
136
+
137
+ The actor's type is the one the collections agree on: a kit whose collections
138
+ stamp an `ObjectId` takes an `ObjectId`, and one whose collections stamp
139
+ nothing has no `as` to call.
140
+
141
+ ## Sync
142
+
143
+ ```ts
144
+ const reports = await kit.sync(); // { main: [ … ], analytics: [ … ] }
145
+ await kit.sync({ dryRun: true }); // what it would change
146
+ ```
147
+
148
+ The first database that throws stops the rest, which is what `dryRun` is for:
149
+ it reports everything at once. It syncs exactly the collections the kit
150
+ wires, database by database —
151
+ `@nxgt/mongo`'s `syncAll` cannot, since its registry knows no database. It is
152
+ a **deployment step**: `collMod` needs the `dbAdmin` role, and an index build
153
+ runs outside any transaction. For tests and development, `autoSync: true` in
154
+ the config syncs each collection before its first operation instead.
155
+
156
+ ## Closing
157
+
158
+ ```ts
159
+ await kit.close(); // or `await using kit = await createKit(…)`
160
+ ```
161
+
162
+ It gives back the clients it opened, and leaves alone a `client` the config
163
+ gave it: what it did not open is not its to close. Only the kit `createKit`
164
+ returned can be closed — one from `as`, `withSession` or a transaction shares
165
+ those clients and refuses.
166
+
167
+ ## API
168
+
169
+ ### `defineConfig(config)`
170
+
171
+ Checks the configuration and freezes it. It connects to nothing and reads no
172
+ environment variable: the application writes `uri: process.env.MONGO_URI!`,
173
+ and what is wrong throws here, where the application starts.
174
+
175
+ | Key | Default | |
176
+ | --- | --- | --- |
177
+ | `uri` | — | One of `uri` and `client`, never both. |
178
+ | `client` | — | A client the application opened. Never closed by the kit. |
179
+ | `clientOptions` | `{}` | Passed to the driver with `uri`. Refused with `client`. |
180
+ | `database` | the URI's, else `test` | The database's name. |
181
+ | `collections` | — | `import * as collections from './models'`. |
182
+ | `options` | `{}` | `@nxgt/mongo`'s collection options, for every collection. |
183
+ | `optionsFor` | `{}` | The same, per key, merged over `options`. |
184
+ | `autoSync` | `false` | Sync each collection before its first operation. |
185
+
186
+ `db`, `session`, `actor` and `autoSync` are not collection options here: the
187
+ kit decides them, and one of them under `options` does not compile, while one
188
+ under `optionsFor` is refused by `defineConfig` — the types cannot see that
189
+ deep. Several databases go under `databases: { main: …, … }`, each one taking
190
+ the same keys; a lone database is named `default`.
191
+
192
+ ### `createKit(config)`
193
+
194
+ Opens what the configuration describes, and gives a `MongoKit`:
195
+
196
+ | Member | |
197
+ | --- | --- |
198
+ | `db` | The only database's scope; `never` with several, and it throws if read anyway. |
199
+ | `databases` | Every scope, under its name — `default` when the config named none. |
200
+ | `clients` | The `MongoClient` of each database, under the same names. |
201
+ | `actor`, `session` | What this kit stamps and runs in, if anything. |
202
+ | `as(actor)` | The same kit, stamping that actor. |
203
+ | `withSession(session)` | The same kit, in that session; `undefined` takes it away. |
204
+ | `transaction(fn, options?)` | `fn` with a kit in a transaction. May run twice. |
205
+ | `sync(options?)` | `SyncReport[]` per database, under its name. |
206
+ | `close()` | Gives back what it opened. Idempotent. |
207
+
208
+ `KitOf<typeof config>` is that kit's type, for an application that declares
209
+ it — a service holding the kit, say — rather than reading it off `await
210
+ createKit(…)`.
211
+
212
+ ### `discoverCollections({ glob, cwd?, export? })`
213
+
214
+ The definitions of the files a glob matches, read at run time and untyped.
215
+ `cwd` is where the glob starts, `process.cwd()` by default. `export` reads
216
+ one export by name in each file, and throws for a matched file that has no
217
+ definition under it; without `export`, every export that is a definition is
218
+ taken. Two files defining the same server collection are refused. It needs
219
+ the Bun runtime, and it is for scripts.
220
+
221
+ ## What does not compile
222
+
223
+ Each is a `@ts-expect-error` case in this package's type tests.
224
+
225
+ - A collection wired under a name the driver's `Db` already has
226
+ (`command`, `watch`, `collection`, …): it would be unreachable.
227
+ - `db.usrs`, or a field no schema has in a `create`.
228
+ - `kit.db` when the kit holds several databases, `kit.databases.nowhere`,
229
+ or `{ on: 'nowhere' }`.
230
+ - `optionsFor` under a key no collection is wired under.
231
+ - `session`, `db`, `actor` or `autoSync` under `options`. Under
232
+ `optionsFor`, the same four are refused by `defineConfig` instead.
233
+ - `as` with an actor of the wrong type, and `as` at all when the
234
+ collections stamp none or disagree.
235
+
236
+ ## Traps
237
+
238
+ - **A key the driver's `Db` has is refused twice**: by the types where the
239
+ config is written, and by `createKit` against the object itself — which is
240
+ what catches a member a later driver release adds.
241
+ - **The scope is a `Db` underneath.** `Object.keys(kit.db)` lists the
242
+ collections, not the driver's members; a driver method read off it is
243
+ bound, so `const { command } = kit.db` works.
244
+ - **`createKit` connects.** `defineConfig` does not, so a wrong URI throws
245
+ where the kit is created, and a database that fails gives back every
246
+ connection opened before it.
247
+ - **A client the config gave is never closed**, including by `await using`.
248
+ Close it where it was opened.
249
+ - **`autoSync` is for tests and development.** In production `sync()` is a
250
+ deployment step: it needs `dbAdmin`, and an index build is not in a
251
+ transaction.
252
+ - **A kit from `as` or `withSession` cannot be closed**, and `close()` on it
253
+ throws: the clients are the root kit's.
254
+ - **`discoverCollections` runs under Bun**, has no types, and does not
255
+ survive bundling. It is for scripts run from the repository; a Node script
256
+ calling it gets `Bun is not defined`.
257
+ - **Two collections that stamp actors of different types** leave `as`
258
+ uncallable: one call could not stamp both.
259
+ - **`{ on }` is required at run time, not by the types**, and cannot be: two
260
+ databases on one URI share a client and need none, so what decides is the
261
+ number of *clients*. Without it, a kit holding two throws.
262
+ - **A transaction body may run twice.** The driver retries it from the start
263
+ on a transient error, so it must hold nothing that MongoDB would not roll
264
+ back.
265
+ - **A transaction reaches one client's databases.** With `{ on: 'main' }`,
266
+ an operation on a database of another client carries a session that client
267
+ does not own, and the driver refuses it.
268
+ - **`kit.db` throws on a kit with several databases**, where its type is
269
+ already `never`: the message names the databases to read instead.
270
+
271
+ ## License
272
+
273
+ MIT
@@ -0,0 +1,9 @@
1
+ import type { AnyCollectionDefinition } from '@nxgt/mongo';
2
+ import type { DatabaseConfig } from './types';
3
+ /** A definition, told by its shape: `instanceof` has no class to ask. */
4
+ export declare function isDefinition(value: unknown): value is AnyCollectionDefinition;
5
+ /** The definitions of a module object, under the keys they are exported by. */
6
+ export declare function definitionsOf(collections: object): [string, AnyCollectionDefinition][];
7
+ /** Everything one database's config must answer before anything connects. */
8
+ export declare function checkDatabase(name: string, config: DatabaseConfig<object>): [string, AnyCollectionDefinition][];
9
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/config/checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB,CAU7E;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAC5B,WAAW,EAAE,MAAM,GACjB,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAAE,CAKrC;AA6BD,6EAA6E;AAC7E,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,GAC5B,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAAE,CA8DrC"}
@@ -0,0 +1,30 @@
1
+ import type { Checked, KitConfig, KitConfigInput } from './types';
2
+ /**
3
+ * The configuration of an application's MongoDB, checked once and frozen.
4
+ *
5
+ * ```ts
6
+ * import * as collections from './models';
7
+ *
8
+ * export const config = defineConfig({
9
+ * uri: process.env.MONGO_URI!,
10
+ * collections,
11
+ * });
12
+ * ```
13
+ *
14
+ * Several databases name themselves:
15
+ *
16
+ * ```ts
17
+ * defineConfig({
18
+ * databases: {
19
+ * main: { uri: process.env.MONGO_URI!, collections },
20
+ * analytics: { uri: process.env.ANALYTICS_URI!, collections: events },
21
+ * },
22
+ * });
23
+ * ```
24
+ *
25
+ * It connects to nothing and reads no environment variable: what is wrong
26
+ * with the configuration throws here, where the application starts, and the
27
+ * variables are the application's to read.
28
+ */
29
+ export declare function defineConfig<const C extends KitConfigInput>(config: C & Checked<C>): KitConfig<C>;
30
+ //# sourceMappingURL=define-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-config.d.ts","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,OAAO,EAEP,SAAS,EACT,cAAc,EACd,MAAM,SAAS,CAAC;AAuBjB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,cAAc,EAC1D,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACpB,SAAS,CAAC,CAAC,CAAC,CAQd"}
@@ -0,0 +1,124 @@
1
+ import type { AnyCollectionDefinition, CollectionOptions } from '@nxgt/mongo';
2
+ import type { Db, MongoClient, MongoClientOptions } from 'mongodb';
3
+ /**
4
+ * The collections of a module, as `import * as collections` gives them: its
5
+ * other exports — types are gone already, and a function or a constant is no
6
+ * definition — are left out of the scope rather than refused.
7
+ */
8
+ export type CollectionsOf<C> = {
9
+ [K in keyof C as C[K] extends AnyCollectionDefinition ? K : never]: C[K];
10
+ };
11
+ /**
12
+ * A name the driver's `Db` already uses. The scope carries the collections
13
+ * over a `Db`, so a collection under one of these names would be unreachable
14
+ * — and `db.watch` would answer something other than what a caller expects.
15
+ *
16
+ * Read from the driver's own type, never from a list of ours: a member the
17
+ * driver adds is covered the day the pin moves. At run time the same question
18
+ * is asked of the object itself, with `in`.
19
+ */
20
+ export type ReservedName = keyof Db;
21
+ /** The keys of `C` that a `Db` already answers to. */
22
+ export type Collides<C> = Extract<keyof CollectionsOf<C>, ReservedName>;
23
+ /**
24
+ * Makes a colliding key unassignable, and says why where the developer is
25
+ * looking: under that key, the value would have to be a string no definition
26
+ * is.
27
+ */
28
+ export type NoCollision<C> = [Collides<C>] extends [never] ? unknown : {
29
+ [K in Collides<C>]: `"${K & string}" is a member of the driver's Db: wire this collection under another key`;
30
+ };
31
+ /**
32
+ * Makes options written for a key no collection is wired under unassignable,
33
+ * and says so under that key — the same shape as `NoCollision`.
34
+ */
35
+ export type Unwired<Cols, OF> = [
36
+ Exclude<keyof OF, keyof CollectionsOf<Cols>>
37
+ ] extends [never] ? unknown : {
38
+ [K in Exclude<keyof OF, keyof CollectionsOf<Cols>>]: `"${K & string}" is not wired by this database: there are no options for it`;
39
+ };
40
+ /** The options of one collection, minus what the kit decides itself. */
41
+ export type KitCollectionOptions<Def> = Omit<CollectionOptions<Def>, 'db' | 'session' | 'actor' | 'autoSync'>;
42
+ /** One database: where it is, and what it holds. */
43
+ export interface DatabaseConfig<C> {
44
+ /**
45
+ * Where to connect. One of `uri` and `client`, never both. Databases on
46
+ * one URI share a client, which the kit closes with its last holder.
47
+ */
48
+ uri?: string;
49
+ /**
50
+ * A client the application opened. The kit uses it and **never closes
51
+ * it**: what it did not open is not its to close.
52
+ */
53
+ client?: MongoClient;
54
+ /** Passed to the driver with `uri`. Refused with `client`, which has its own. */
55
+ clientOptions?: MongoClientOptions;
56
+ /** The database's name. Default: the one the URI names, or `test`. */
57
+ database?: string;
58
+ /** `import * as collections from './models'`, passed as it is. */
59
+ collections: C;
60
+ /** For every collection of this database. */
61
+ options?: KitCollectionOptions<AnyCollectionDefinition>;
62
+ /** For one collection, merged over `options`. */
63
+ optionsFor?: {
64
+ [K in keyof CollectionsOf<C>]?: KitCollectionOptions<CollectionsOf<C>[K]>;
65
+ };
66
+ /**
67
+ * Sync each collection before its first operation, once per database:
68
+ * `@nxgt/mongo`'s `autoSync`. For tests and development, never for
69
+ * production, where `sync()` is a deployment step.
70
+ */
71
+ autoSync?: boolean;
72
+ }
73
+ /** One database, or several under their names. */
74
+ export type KitConfigInput = DatabaseConfig<object> | {
75
+ databases: Record<string, DatabaseConfig<object>>;
76
+ };
77
+ /**
78
+ * The config with every key it has to refuse — one the driver's `Db` already
79
+ * answers to, or options for a collection that is not wired — turned into the
80
+ * message above. `defineConfig` takes its argument as `C & Checked<C>`, and a
81
+ * constraint written that way is what makes the refusal land on the key the
82
+ * application wrote, rather than on the whole object.
83
+ */
84
+ export type Checked<C> = C extends {
85
+ databases: infer D;
86
+ } ? {
87
+ databases: {
88
+ [N in keyof D]: CheckedDatabase<D[N]>;
89
+ };
90
+ } : CheckedDatabase<C>;
91
+ /** One database's collections, and the options written for them. */
92
+ type CheckedDatabase<D> = D extends {
93
+ collections: infer Cols;
94
+ } ? {
95
+ collections: Cols & NoCollision<Cols>;
96
+ } & (D extends {
97
+ optionsFor: infer OF;
98
+ } ? {
99
+ optionsFor: OF & Unwired<Cols, OF>;
100
+ } : unknown) : D;
101
+ /** The databases of a config, whichever of the two shapes it was written in. */
102
+ export type DatabasesOf<C> = C extends {
103
+ databases: infer D;
104
+ } ? D : {
105
+ default: C;
106
+ };
107
+ /** The name of every database. */
108
+ export type DbName<C> = keyof DatabasesOf<C> & string;
109
+ /** The collections of one database, as they were passed. */
110
+ export type CollectionsIn<C, N extends DbName<C>> = DatabasesOf<C>[N] extends {
111
+ collections: infer Cols;
112
+ } ? Cols : never;
113
+ /**
114
+ * What `defineConfig` gives back: the databases under their names, checked
115
+ * and frozen, carrying the shape it was written in — which is what decides
116
+ * whether the kit has a `db` of its own.
117
+ */
118
+ export interface KitConfig<C> {
119
+ readonly databases: {
120
+ readonly [N in DbName<C>]: DatabaseConfig<CollectionsIn<C, N>>;
121
+ };
122
+ }
123
+ export {};
124
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { AnyCollectionDefinition } from '@nxgt/mongo';
2
+ /** What to scan, and what to read in each file it finds. */
3
+ export interface DiscoverOptions {
4
+ /** A glob, relative to `cwd`: `'src/models/*.model.ts'`. */
5
+ glob: string;
6
+ /** Where the glob starts. Default: the process's working directory. */
7
+ cwd?: string;
8
+ /**
9
+ * The export to read in each file. Default: every export that is a
10
+ * definition, which is what `import * as collections` gives.
11
+ */
12
+ export?: string;
13
+ }
14
+ /**
15
+ * The definitions of the files a glob matches, read at run time.
16
+ *
17
+ * For scripts — a sync or a migration run from the repository — and for
18
+ * nothing else: a glob is read from the file system, so it finds nothing
19
+ * once the application is bundled, and it produces **no types**. An
20
+ * application wires its collections with `import * as collections from
21
+ * './models'`, which a bundler follows and the compiler sees.
22
+ *
23
+ * ```ts
24
+ * import { connectMongo, syncCollections } from '@nxgt/mongo';
25
+ * import { discoverCollections } from '@nxgt/mongo-kit';
26
+ *
27
+ * const mongo = await connectMongo(process.env.MONGO_URI!);
28
+ * const definitions = await discoverCollections({ glob: 'src/**\/*.model.ts' });
29
+ * await syncCollections(mongo.db, definitions);
30
+ * await mongo.close();
31
+ * ```
32
+ *
33
+ * The files are imported, so their top level runs, and the glob is
34
+ * `Bun.Glob`: this one function needs the Bun runtime.
35
+ */
36
+ export declare function discoverCollections(options: DiscoverOptions): Promise<AnyCollectionDefinition[]>;
37
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG3D,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC/B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAiCpC"}
@@ -0,0 +1,6 @@
1
+ export { defineConfig } from './config/define-config';
2
+ export type { CollectionsIn, CollectionsOf, DatabaseConfig, DbName, KitCollectionOptions, KitConfig, KitConfigInput, NoCollision, ReservedName, Unwired, } from './config/types';
3
+ export { type DiscoverOptions, discoverCollections } from './discover';
4
+ export { createKit } from './kit/create-kit';
5
+ export type { DbScope, KitActor, KitOf, KitTransactionOptions, MongoKit, SoleScope, } from './kit/types';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,MAAM,EACN,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,WAAW,EACX,YAAY,EACZ,OAAO,GACP,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EACX,OAAO,EACP,QAAQ,EACR,KAAK,EACL,qBAAqB,EACrB,QAAQ,EACR,SAAS,GACT,MAAM,aAAa,CAAC"}