@twasik4/pocket-service 1.0.3 → 1.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.
@@ -1,285 +0,0 @@
1
- import { Collection, Db, Document, MongoClient } from "mongodb";
2
- import { CollectionWrapper, SchemaParser } from "./collection";
3
-
4
- type AnyMongoMethod = (...args: any[]) => any;
5
-
6
- export type MongoCollectionMethods = Record<string, AnyMongoMethod>;
7
-
8
- export type MongoIndexSpec = {
9
- /**
10
- * Index key specification. Example: { userId: 1 } for ascending, { userId: -1 } for descending
11
- */
12
- key: Record<string, 1 | -1>;
13
- /**
14
- * Optional name for the index. If not provided, MongoDB will auto-generate.
15
- */
16
- name?: string;
17
- /**
18
- * Whether the index should enforce uniqueness.
19
- */
20
- unique?: boolean;
21
- /**
22
- * Whether the index should be sparse (only index documents with the indexed field).
23
- */
24
- sparse?: boolean;
25
- /**
26
- * Whether to build the index in the background without blocking other operations.
27
- */
28
- background?: boolean;
29
- /**
30
- * The time-to-live (TTL) for documents in the collection, in seconds. Only applicable for TTL indexes.
31
- */
32
- expireAfterSeconds?: number;
33
- };
34
-
35
- export type MongoCollectionMethodContext<TDocument extends Document> = {
36
- /**
37
- * The MongoDB client instance
38
- */
39
- client: MongoClient;
40
- /**
41
- * The MongoDB database instance
42
- */
43
- db: Db;
44
- /**
45
- * The MongoDB collection instance
46
- */
47
- collection: Collection<TDocument>;
48
- /**
49
- * The base collection wrapper instance
50
- */
51
- base: CollectionWrapper<TDocument>;
52
- };
53
-
54
- export type MongoCollectionDefinition<
55
- TDocument extends Document = Document,
56
- TMethods extends MongoCollectionMethods = {},
57
- > = {
58
- name?: string;
59
- /**
60
- * Whether to automatically track revisions of documents in this collection. If enabled, every update will insert a copy of the updated document into a separate revision collection, allowing you to keep a history of changes. The revision collection will have the same name as the main collection with `_revisions` appended to it (e.g. `users` -> `users_revisions`).
61
- */
62
- trackRevisions: boolean;
63
- schema: SchemaParser<TDocument>;
64
- /**
65
- * Custom methods to add to the collection wrapper. These methods receive a context object with the MongoDB client, database, collection, and base wrapper instance, allowing you to build complex queries and operations while still benefiting from the schema validation and soft delete functionality provided by the base wrapper.
66
- * @param ctx
67
- * @returns
68
- */
69
- methods?: (ctx: MongoCollectionMethodContext<TDocument>) => TMethods;
70
- /**
71
- * Optional array of index specifications to create on this collection. Indexes are created idempotently on service startup, so duplicate indexes are safely ignored.
72
- */
73
- indexes?: MongoIndexSpec[];
74
- };
75
-
76
- export type MongoCollectionsConfig = Record<
77
- string,
78
- MongoCollectionDefinition<any, MongoCollectionMethods>
79
- >;
80
-
81
- type InferDocument<TDefinition> = TDefinition extends {
82
- schema: SchemaParser<infer TDocument>;
83
- }
84
- ? TDocument
85
- : Document;
86
-
87
- type NormalizeDocument<TDocument> = TDocument extends Document
88
- ? TDocument
89
- : Document;
90
-
91
- type InferMethods<TDefinition> = TDefinition extends {
92
- methods: (...args: any[]) => infer TMethods;
93
- }
94
- ? TMethods
95
- : TDefinition extends {
96
- methods?: (...args: any[]) => infer TMethods;
97
- }
98
- ? TMethods extends undefined
99
- ? {}
100
- : TMethods
101
- : {};
102
-
103
- export type MongoBoundCollection<
104
- TDocument extends Document,
105
- TMethods extends MongoCollectionMethods = {},
106
- > = CollectionWrapper<TDocument> & TMethods;
107
-
108
- export type InferMongoCollections<TCollections extends MongoCollectionsConfig> =
109
- {
110
- [K in keyof TCollections]: MongoBoundCollection<
111
- NormalizeDocument<InferDocument<TCollections[K]>>,
112
- InferMethods<TCollections[K]>
113
- >;
114
- };
115
-
116
- export type MongoDatabase<TCollections extends MongoCollectionsConfig> = {
117
- client: MongoClient;
118
- db: Db;
119
- collections: InferMongoCollections<TCollections>;
120
- disconnect: () => Promise<void>;
121
- connect: () => Promise<MongoClient>;
122
- } & InferMongoCollections<TCollections>;
123
-
124
- type SchemaOutput<TSchema> = TSchema extends {
125
- parse: (input: unknown) => infer TOutput;
126
- }
127
- ? NormalizeDocument<TOutput>
128
- : Document;
129
-
130
- /**
131
- * Define a MongoDB collection with an associated Zod schema for validation and optional custom methods. The returned collection definition can then be used to create a MongoDatabase instance, which will automatically wrap the collection with the provided schema validation and methods.
132
- * @param config The configuration object for the MongoDB collection, including the schema and optional custom methods.
133
- */
134
- export function defineMongoCollection<
135
- TSchema extends SchemaParser<any>,
136
- >(config: {
137
- /**
138
- * Optional name for the collection. If not provided, the key used in the collections config will be used as the collection name. This allows you to have more control over the actual collection names in the database, while still using descriptive keys in your code.
139
- */
140
- name?: string;
141
- /**
142
- * Zod schema for validating documents in the collection. The schema will be used to parse and validate documents returned from the database, ensuring that they conform to the expected structure and types. If a document does not match the schema, an error will be thrown.
143
- */
144
- schema: TSchema;
145
- methods?: undefined;
146
- /**
147
- * Optional array of index specifications to create on this collection.
148
- */
149
- indexes?: MongoIndexSpec[];
150
- }): MongoCollectionDefinition<SchemaOutput<TSchema>, {}>;
151
-
152
- /**
153
- * Define a MongoDB collection with an associated Zod schema for validation and optional custom methods. The returned collection definition can then be used to create a MongoDatabase instance, which will automatically wrap the collection with the provided schema validation and methods.
154
- * @param config The configuration object for the MongoDB collection, including the schema and optional custom methods.
155
- */
156
- export function defineMongoCollection<
157
- TSchema extends SchemaParser<any>,
158
- TMethods extends MongoCollectionMethods,
159
- >(config: {
160
- /**
161
- * Optional name for the collection. If not provided, the key used in the collections config will be used as the collection name. This allows you to have more control over the actual collection names in the database, while still using descriptive keys in your code.
162
- */
163
- name?: string;
164
- /**
165
- * Zod schema for validating documents in the collection. The schema will be used to parse and validate documents returned from the database, ensuring that they conform to the expected structure and types. If a document does not match the schema, an error will be thrown.
166
- */
167
- schema: TSchema;
168
- /**
169
- * Optional custom methods for the collection. These methods will be added to the collection instance and can be used to implement custom queries or operations.
170
- * @param ctx The context object containing the MongoDB client, database, collection, and base collection wrapper.
171
- * @returns An object containing the custom methods to be added to the collection instance.
172
- */
173
- methods: (
174
- ctx: MongoCollectionMethodContext<SchemaOutput<TSchema>>,
175
- ) => TMethods;
176
- /**
177
- * Optional array of index specifications to create on this collection.
178
- */
179
- indexes?: MongoIndexSpec[];
180
- }): MongoCollectionDefinition<SchemaOutput<TSchema>, TMethods>;
181
-
182
- /**
183
- * Define a MongoDB collection with an associated Zod schema for validation and optional custom methods. The returned collection definition can then be used to create a MongoDatabase instance, which will automatically wrap the collection with the provided schema validation and methods.
184
- * @param config The configuration object for the MongoDB collection, including the schema and optional custom methods.
185
- */
186
- export function defineMongoCollection<
187
- TSchema extends SchemaParser<any>,
188
- TMethods extends MongoCollectionMethods = {},
189
- >(config: {
190
- /**
191
- * Optional name for the collection. If not provided, the key used in the collections config will be used as the collection name. This allows you to have more control over the actual collection names in the database, while still using descriptive keys in your code.
192
- */
193
- name?: string;
194
- /**
195
- * Zod schema for validating documents in the collection. The schema will be used to parse and validate documents returned from the database, ensuring that they conform to the expected structure and types. If a document does not match the schema, an error will be thrown.
196
- */
197
- schema: TSchema;
198
- /**
199
- * Optional custom methods for the collection. These methods will be added to the collection instance and can be used to implement custom queries or operations.
200
- * @param ctx The context object containing the MongoDB client, database, collection, and base collection wrapper.
201
- * @returns An object containing the custom methods to be added to the collection instance.
202
- */
203
- methods?: (
204
- ctx: MongoCollectionMethodContext<SchemaOutput<TSchema>>,
205
- ) => TMethods;
206
- /**
207
- * Optional array of index specifications to create on this collection.
208
- */
209
- indexes?: MongoIndexSpec[];
210
- }): MongoCollectionDefinition<SchemaOutput<TSchema>, TMethods> {
211
- return {
212
- name: config.name,
213
- schema: config.schema,
214
- /**
215
- * Optional custom methods for the collection. These methods will be added to the collection instance and can be used to implement custom queries or operations.
216
- * @param ctx The context object containing the MongoDB client, database, collection, and base collection wrapper.
217
- * @returns An object containing the custom methods to be added to the collection instance.
218
- */
219
- methods: config.methods,
220
- indexes: config.indexes,
221
- /**
222
- * Whether to automatically track revisions of documents in this collection. If enabled, every update will insert a copy of the updated document into a separate revision collection, allowing you to keep a history of changes. The revision collection will have the same name as the main collection with `_revisions` appended to it (e.g. `users` -> `users_revisions`).
223
- */
224
- trackRevisions: false,
225
- } as MongoCollectionDefinition<SchemaOutput<TSchema>, TMethods>;
226
- }
227
-
228
- export function createMongo<TCollections extends MongoCollectionsConfig>(
229
- dbName: string,
230
- config: TCollections,
231
- options: { uri?: string } = {},
232
- ): MongoDatabase<TCollections> {
233
- const client = new MongoClient(
234
- options.uri || process.env.MONGO_URI || "mongodb://mongo:27017",
235
- );
236
- const db = client.db(dbName);
237
-
238
- const wrapped = {} as InferMongoCollections<TCollections>;
239
-
240
- for (const key in config) {
241
- const def = config[key];
242
- const collectionName = def.name || key;
243
- const collection = db.collection(collectionName);
244
- const revisionCollection = def.trackRevisions
245
- ? db.collection(`${collectionName}_revisions`)
246
- : undefined;
247
- const base = new CollectionWrapper(
248
- collection as Collection<any>,
249
- def.schema,
250
- revisionCollection,
251
- );
252
- const methods =
253
- def.methods?.({
254
- client,
255
- db,
256
- collection: collection as Collection<any>,
257
- base,
258
- }) || {};
259
-
260
- if (def.indexes && def.indexes.length > 0) {
261
- for (const indexSpec of def.indexes) {
262
- const { key, ...options } = indexSpec;
263
- collection.createIndex(key, options).catch((err) => {
264
- console.error(
265
- `Failed to create index on ${collectionName}: ${err.message}`,
266
- );
267
- });
268
- }
269
- }
270
-
271
- wrapped[key] = Object.assign(
272
- base,
273
- methods,
274
- ) as InferMongoCollections<TCollections>[typeof key];
275
- }
276
-
277
- return {
278
- client,
279
- db,
280
- collections: wrapped,
281
- ...wrapped,
282
- disconnect: async () => client.close(),
283
- connect: async () => client.connect(),
284
- } as MongoDatabase<TCollections>;
285
- }