@opra/mongodb 0.31.12 → 0.32.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,6 +1,5 @@
1
1
  import { ObjectId } from 'mongodb';
2
2
  import { ResourceNotFoundError } from '@opra/common';
3
- import * as OpraCommon from '@opra/common';
4
3
  import { MongoAdapter } from './mongo-adapter.js';
5
4
  import { MongoService } from './mongo-service.js';
6
5
  /**
@@ -10,74 +9,89 @@ import { MongoService } from './mongo-service.js';
10
9
  export class MongoSingletonService extends MongoService {
11
10
  constructor(dataType, options) {
12
11
  super(dataType, options);
12
+ this.collectionKey = options?.collectionKey || '_id';
13
13
  this._id = options?._id || new ObjectId('655608925cad472b75fc6485');
14
14
  }
15
- get resource() {
16
- const resource = this.context.request.resource;
17
- if (resource instanceof OpraCommon.Singleton)
18
- return resource;
19
- throw new TypeError(`"${resource}" resource is not a Singleton`);
15
+ /**
16
+ * Fetches the Document. Throws error undefined if not found.
17
+ *
18
+ * @param options
19
+ */
20
+ async assert(options) {
21
+ const out = await this.get(options);
22
+ if (!out)
23
+ throw new ResourceNotFoundError(this.resourceName || this.getCollectionName());
24
+ return out;
20
25
  }
26
+ /**
27
+ * Inserts the document into MongoDB
28
+ *
29
+ * @param doc
30
+ * @param options
31
+ */
21
32
  async create(doc, options) {
22
- const r = await this._rawInsertOne({ ...doc, _id: this._id }, options);
23
- if (r.insertedId) {
24
- const out = await this.get(options);
25
- if (out)
26
- return out;
27
- }
33
+ const r = await this.__insertOne({ ...doc, _id: this._id }, options);
34
+ if (r.insertedId)
35
+ return doc;
28
36
  /* istanbul ignore next */
29
37
  throw new Error('Unknown error while creating document');
30
38
  }
39
+ /**
40
+ * Delete the document from a collection
41
+ *
42
+ * @param options
43
+ */
31
44
  async delete(options) {
32
- const filter = { _id: this._id };
33
- const optionsFilter = MongoAdapter.prepareFilter(options?.filter);
34
- if (optionsFilter)
35
- filter.$and = [...(Array.isArray(optionsFilter) ? optionsFilter : [optionsFilter])];
36
- const r = await this._rawDeleteOne(filter, options);
45
+ const filter = MongoAdapter.prepareFilter([{ _id: this._id }, options?.filter]);
46
+ const r = await this.__deleteOne(filter, options);
37
47
  return r.deletedCount;
38
48
  }
39
- async get(options) {
40
- const out = await this.find(options);
41
- if (!out)
42
- throw new ResourceNotFoundError(this.resource.name);
43
- return out;
49
+ /**
50
+ * Checks if the document exists.
51
+ * Returns true if document exists, false otherwise
52
+ *
53
+ */
54
+ async exists() {
55
+ return !!(await this.get({ pick: ['_id'] }));
44
56
  }
45
- async find(options) {
46
- const filter = { _id: this._id };
47
- const optionsFilter = MongoAdapter.prepareFilter(options?.filter);
48
- if (optionsFilter)
49
- filter.$and = [...(Array.isArray(optionsFilter) ? optionsFilter : [optionsFilter])];
57
+ /**
58
+ * Fetches the document
59
+ *
60
+ * @param options
61
+ */
62
+ async get(options) {
63
+ const filter = MongoAdapter.prepareFilter([{ _id: this._id }, options?.filter]);
50
64
  const mongoOptions = {
51
65
  ...options,
52
- projection: MongoAdapter.prepareProjection(this.resource.type, options),
66
+ projection: MongoAdapter.prepareProjection(this.getDataType(), options),
53
67
  sort: undefined,
54
68
  skip: undefined,
55
69
  limit: undefined
56
70
  };
57
- const out = await this._rawFindOne(filter, mongoOptions);
58
- if (out) {
59
- if (this.transformData)
60
- return this.transformData(out);
61
- return out;
62
- }
71
+ return await this.__findOne(filter, mongoOptions);
63
72
  }
73
+ /**
74
+ * Updates a single document.
75
+ * Returns updated document
76
+ *
77
+ * @param doc
78
+ * @param options
79
+ */
64
80
  async update(doc, options) {
65
- // Prevent upsert with different _id field
66
- if (options?.upsert)
67
- doc._id = this._id;
68
- else
69
- delete doc._id;
81
+ // Prevent updating _id field
82
+ delete doc._id;
83
+ const filter = MongoAdapter.prepareFilter([
84
+ { _id: this._id },
85
+ options?.filter
86
+ ]);
70
87
  const patch = MongoAdapter.preparePatch(doc);
71
88
  const mongoOptions = {
72
89
  ...options,
73
- upsert: undefined
90
+ includeResultMetadata: false,
91
+ upsert: undefined,
92
+ projection: MongoAdapter.prepareProjection(this.getDataType(), options),
74
93
  };
75
- const filter = { _id: this._id };
76
- const optionsFilter = MongoAdapter.prepareFilter(options?.filter);
77
- if (optionsFilter)
78
- filter.$and = [...(Array.isArray(optionsFilter) ? optionsFilter : [optionsFilter])];
79
- const r = await this._rawUpdateOne(filter, patch, mongoOptions);
80
- if (r.matchedCount)
81
- return await this.get(options);
94
+ const out = await this.__findOneAndUpdate(filter, patch, mongoOptions);
95
+ return out || undefined;
82
96
  }
83
97
  }
package/esm/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/mongodb",
3
- "version": "0.31.12",
3
+ "version": "0.32.0",
4
4
  "description": "Opra MongoDB adapter package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -29,11 +29,11 @@
29
29
  "@types/lodash.isnil": "^4.0.9",
30
30
  "@types/lodash.omitby": "^4.6.9",
31
31
  "mongodb": "^6.3.0",
32
- "ts-gems": "^2.5.0"
32
+ "ts-gems": "^2.7.1"
33
33
  },
34
34
  "peerDependencies": {
35
- "@opra/common": "^0.31.12",
36
- "@opra/core": "^0.31.12",
35
+ "@opra/common": "^0.32.0",
36
+ "@opra/core": "^0.32.0",
37
37
  "mongodb": ">=6.x.x"
38
38
  },
39
39
  "type": "module",
@@ -1,4 +1,12 @@
1
- import '@opra/core';
2
1
  import mongodb from 'mongodb';
3
2
  import { OpraFilter } from '@opra/common';
4
- export default function prepareFilter(filter: OpraFilter.Expression | mongodb.Filter<any> | string | undefined): mongodb.Filter<any> | undefined;
3
+ type FilterInput = (OpraFilter.Expression | mongodb.Filter<any> | string | undefined);
4
+ /**
5
+ * Convert filter expressions to MongoDB filter objects.
6
+ * This method also merges multiple expressions into one single filter object
7
+ * @param filters
8
+ */
9
+ export default function prepareFilter(filters: FilterInput | FilterInput[], options?: {
10
+ fieldPrefix?: string;
11
+ }): mongodb.Filter<any>;
12
+ export {};
@@ -1,9 +1,13 @@
1
1
  import mongodb from 'mongodb';
2
2
  import { ComplexType } from '@opra/common';
3
- export default function prepareProjection(dataType: ComplexType, args?: {
3
+ export default function prepareProjection(dataType: ComplexType, options?: {
4
4
  pick?: string[];
5
5
  omit?: string[];
6
6
  include?: string[];
7
7
  }): mongodb.Document | undefined;
8
- export declare function _prepareInclusionProjection(dataType: ComplexType, target: mongodb.Document, pick?: any, include?: any, omit?: any, defaultFields?: boolean): void;
9
- export declare function _prepareExclusionProjection(dataType: ComplexType, target: mongodb.Document, omit?: any, omitExclusiveFields?: boolean): void;
8
+ export declare function _prepareProjection(dataType: ComplexType, target: mongodb.Document, options: {
9
+ pickActivated: boolean;
10
+ include?: any;
11
+ pick?: any;
12
+ omit?: any;
13
+ }): void;
package/types/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './mongo-adapter.js';
2
+ export * from './mongo-array-service.js';
2
3
  export * from './mongo-collection-service.js';
3
4
  export * from './mongo-service.js';
4
5
  export * from './mongo-singleton-service.js';
6
+ export * from './types.js';
@@ -0,0 +1,193 @@
1
+ import mongodb from 'mongodb';
2
+ import { StrictOmit, Type } from 'ts-gems';
3
+ import vg from 'valgen';
4
+ import * as OpraCommon from '@opra/common';
5
+ import { ComplexType, PartialInput } from '@opra/common';
6
+ import { PartialOutput } from '@opra/core';
7
+ import { MongoCollectionService } from './mongo-collection-service.js';
8
+ import { MongoService } from './mongo-service.js';
9
+ import { AnyId } from './types.js';
10
+ /**
11
+ *
12
+ * @class MongoArrayService
13
+ */
14
+ export declare class MongoArrayService<T extends mongodb.Document> extends MongoService<T> {
15
+ protected _encoders: Record<string, vg.Validator>;
16
+ collectionKey: string;
17
+ arrayKey: string;
18
+ defaultLimit: number;
19
+ fieldName: string;
20
+ constructor(dataType: Type | string, fieldName: string, options?: MongoArrayService.Options);
21
+ getArrayDataType(): ComplexType;
22
+ /**
23
+ * Checks if array item exists. Throws error if not.
24
+ *
25
+ * @param parentId
26
+ * @param id
27
+ */
28
+ assert(parentId: AnyId, id: AnyId): Promise<void>;
29
+ /**
30
+ * Adds a single item into array field.
31
+ *
32
+ * @param parentId
33
+ * @param input
34
+ * @param options
35
+ */
36
+ create(parentId: AnyId, input: T, options?: MongoArrayService.CreateOptions): Promise<PartialOutput<T>>;
37
+ /**
38
+ * Gets the number of array items matching the filter.
39
+ * @param parentId
40
+ * @param options
41
+ */
42
+ count(parentId: AnyId, options?: MongoArrayService.CountOptions<T>): Promise<number>;
43
+ /**
44
+ * Removes one item from an array field
45
+ *
46
+ * @param parentId
47
+ * @param id
48
+ * @param options
49
+ */
50
+ delete(parentId: AnyId, id: AnyId, options?: MongoArrayService.DeleteOptions<T>): Promise<number>;
51
+ /**
52
+ * Removes multiple items from an array field
53
+ *
54
+ * @param parentId
55
+ * @param options
56
+ */
57
+ deleteMany(parentId: AnyId, options?: MongoArrayService.DeleteManyOptions<T>): Promise<number>;
58
+ /**
59
+ * Returns true if item exists, false otherwise
60
+ *
61
+ * @param parentId
62
+ * @param id
63
+ */
64
+ exists(parentId: AnyId, id: AnyId): Promise<boolean>;
65
+ /**
66
+ * Fetches the first item in an array field that matches by id.
67
+ *
68
+ * @param parentId
69
+ * @param id
70
+ * @param options
71
+ */
72
+ findById(parentId: AnyId, id: AnyId, options?: MongoArrayService.FindOneOptions): Promise<PartialOutput<T> | undefined>;
73
+ /**
74
+ * Fetches the first item in an array field that matches the filter. Returns undefined if not found.
75
+ *
76
+ * @param parentId
77
+ * @param options
78
+ */
79
+ findOne(parentId: AnyId, options?: MongoArrayService.FindOneOptions): Promise<PartialOutput<T> | undefined>;
80
+ /**
81
+ * Fetches all items in an array field that matches the filter
82
+ *
83
+ * @param parentId
84
+ * @param options
85
+ */
86
+ findMany(parentId: AnyId, options?: MongoArrayService.FindManyOptions<T>): Promise<PartialOutput<T>[] | undefined>;
87
+ /**
88
+ * Fetches the first item in an array field that matches the item id. Throws error undefined if not found.
89
+ *
90
+ * @param parentId
91
+ * @param id
92
+ * @param options
93
+ */
94
+ get(parentId: AnyId, id: AnyId, options?: MongoArrayService.FindOneOptions<T>): Promise<PartialOutput<T>>;
95
+ /**
96
+ * Update a single item in array field
97
+ *
98
+ * @param parentId
99
+ * @param id
100
+ * @param input
101
+ * @param options
102
+ */
103
+ update(parentId: AnyId, id: AnyId, input: PartialInput<T>, options?: MongoArrayService.UpdateOptions<T>): Promise<PartialOutput<T> | undefined>;
104
+ /**
105
+ * Update a single item in array field
106
+ * Returns how many master documents updated (not array items)
107
+ *
108
+ * @param parentId
109
+ * @param id
110
+ * @param doc
111
+ * @param options
112
+ */
113
+ updateOnly(parentId: AnyId, id: AnyId, doc: PartialInput<T>, options?: MongoArrayService.UpdateOptions<T>): Promise<number>;
114
+ /**
115
+ * Update multiple items in array field, returns how many master documents updated (not array items)
116
+ *
117
+ * @param parentId
118
+ * @param input
119
+ * @param options
120
+ */
121
+ updateMany(parentId: AnyId, input: PartialInput<T>, options?: MongoArrayService.UpdateManyOptions<T>): Promise<number>;
122
+ /**
123
+ * Update multiple items in array field and returns number of updated array items
124
+ *
125
+ * @param parentId
126
+ * @param doc
127
+ * @param options
128
+ */
129
+ updateManyReturnCount(parentId: AnyId, doc: PartialInput<T>, options?: MongoArrayService.UpdateManyOptions<T>): Promise<number>;
130
+ /**
131
+ * Generates Id value
132
+ *
133
+ * @protected
134
+ */
135
+ protected _generateId(): AnyId;
136
+ /**
137
+ * Generates a new Validator for encoding or returns from cache if already generated before
138
+ * @param operation
139
+ * @protected
140
+ */
141
+ protected _getEncoder(operation: 'create' | 'update'): vg.Validator;
142
+ /**
143
+ * Generates a new Valgen Validator for encode operation
144
+ *
145
+ * @param operation
146
+ * @protected
147
+ */
148
+ protected _generateEncoder(operation: 'create' | 'update'): vg.Validator;
149
+ }
150
+ /**
151
+ *
152
+ * @namespace MongoArrayService
153
+ */
154
+ export declare namespace MongoArrayService {
155
+ interface Options extends MongoCollectionService.Options {
156
+ arrayKey?: string;
157
+ }
158
+ interface CreateOptions extends mongodb.UpdateOptions {
159
+ pick?: string[];
160
+ omit?: string[];
161
+ include?: string[];
162
+ }
163
+ interface CountOptions<T> extends mongodb.AggregateOptions {
164
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
165
+ }
166
+ interface DeleteOptions<T> extends mongodb.UpdateOptions {
167
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
168
+ }
169
+ interface DeleteManyOptions<T> extends mongodb.UpdateOptions {
170
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
171
+ }
172
+ interface FindOneOptions<T = any> extends StrictOmit<FindManyOptions<T>, 'count' | 'limit'> {
173
+ }
174
+ interface FindManyOptions<T> extends mongodb.AggregateOptions {
175
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
176
+ pick?: string[];
177
+ omit?: string[];
178
+ include?: string[];
179
+ sort?: string[];
180
+ count?: boolean;
181
+ limit?: number;
182
+ skip?: number;
183
+ }
184
+ interface UpdateOptions<T> extends mongodb.UpdateOptions {
185
+ pick?: string[];
186
+ omit?: string[];
187
+ include?: string[];
188
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
189
+ }
190
+ interface UpdateManyOptions<T> extends mongodb.UpdateOptions {
191
+ filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
192
+ }
193
+ }
@@ -1,25 +1,129 @@
1
1
  import mongodb from 'mongodb';
2
2
  import { StrictOmit, Type } from 'ts-gems';
3
+ import vg from 'valgen';
3
4
  import * as OpraCommon from '@opra/common';
4
5
  import { PartialInput, PartialOutput } from '@opra/core';
5
6
  import { MongoService } from './mongo-service.js';
7
+ import { AnyId } from './types.js';
6
8
  /**
7
9
  *
8
10
  * @class MongoCollectionService
9
11
  */
10
12
  export declare class MongoCollectionService<T extends mongodb.Document> extends MongoService<T> {
11
- keyFields?: string[];
13
+ protected _encoders: Record<string, vg.Validator>;
14
+ collectionKey: string;
12
15
  defaultLimit: number;
13
16
  constructor(dataType: Type | string, options?: MongoCollectionService.Options);
14
- protected create(doc: mongodb.OptionalUnlessRequiredId<T>, options?: MongoCollectionService.CreateOptions): Promise<PartialOutput<T>>;
15
- protected count(options?: MongoCollectionService.CountOptions<T>): Promise<number>;
16
- protected delete(id: any, options?: MongoCollectionService.DeleteOptions<T>): Promise<number>;
17
- protected deleteMany(options?: MongoCollectionService.DeleteManyOptions<T>): Promise<number>;
18
- protected get(id: any, options?: MongoCollectionService.GetOptions): Promise<PartialOutput<T>>;
19
- protected findOne(id: any, options?: MongoCollectionService.GetOptions): Promise<PartialOutput<T> | undefined>;
20
- protected findMany(options?: MongoCollectionService.FindManyOptions<T>): Promise<PartialOutput<T>[]>;
21
- protected update(id: any, doc: PartialInput<T>, options?: MongoCollectionService.UpdateOptions<T>): Promise<PartialOutput<T> | undefined>;
22
- protected updateMany(doc: OpraCommon.PartialInput<T>, options?: MongoCollectionService.UpdateManyOptions<T>): Promise<number>;
17
+ /**
18
+ * Checks if document exists. Throws error if not.
19
+ *
20
+ * @param id
21
+ */
22
+ assert(id: AnyId): Promise<void>;
23
+ /**
24
+ * Inserts a single document into MongoDB
25
+ *
26
+ * @param input
27
+ * @param options
28
+ */
29
+ create(input: PartialInput<T>, options?: MongoCollectionService.CreateOptions): Promise<PartialOutput<T>>;
30
+ /**
31
+ * Gets the number of documents matching the filter.
32
+ *
33
+ * @param options
34
+ */
35
+ count(options?: MongoCollectionService.CountOptions<T>): Promise<number>;
36
+ /**
37
+ * Delete a document from a collection
38
+ *
39
+ * @param id
40
+ * @param options
41
+ */
42
+ delete(id: AnyId, options?: MongoCollectionService.DeleteOptions<T>): Promise<number>;
43
+ /**
44
+ * Delete multiple documents from a collection
45
+ *
46
+ * @param options
47
+ */
48
+ deleteMany(options?: MongoCollectionService.DeleteManyOptions<T>): Promise<number>;
49
+ /**
50
+ * Checks if document exists.
51
+ * Returns true if document exists, false otherwise
52
+ *
53
+ * @param id
54
+ */
55
+ exists(id: AnyId): Promise<boolean>;
56
+ /**
57
+ * Fetches the first document matches by id.
58
+ *
59
+ * @param id
60
+ * @param options
61
+ */
62
+ findById(id: AnyId, options?: MongoCollectionService.FindOneOptions): Promise<PartialOutput<T | undefined>>;
63
+ /**
64
+ * Fetches the first document that matches the filter.
65
+ * Returns undefined if not found.
66
+ *
67
+ * @param options
68
+ */
69
+ findOne(options?: MongoCollectionService.FindOneOptions): Promise<PartialOutput<T> | undefined>;
70
+ /**
71
+ * Fetches all document that matches the filter
72
+ *
73
+ * @param options
74
+ */
75
+ findMany(options?: MongoCollectionService.FindManyOptions<T>): Promise<PartialOutput<T>[]>;
76
+ /**
77
+ * Fetches the first Document that matches the id. Throws error undefined if not found.
78
+ *
79
+ * @param id
80
+ * @param options
81
+ */
82
+ get(id: AnyId, options?: MongoCollectionService.FindOneOptions): Promise<PartialOutput<any>>;
83
+ /**
84
+ * Updates a single document.
85
+ * Returns updated document
86
+ *
87
+ * @param id
88
+ * @param input
89
+ * @param options
90
+ */
91
+ update(id: any, input: PartialInput<T>, options?: MongoCollectionService.UpdateOptions<T>): Promise<PartialOutput<T> | undefined>;
92
+ /**
93
+ * Updates a single document
94
+ * Returns number of updated documents
95
+ *
96
+ * @param id
97
+ * @param input
98
+ * @param options
99
+ */
100
+ updateOnly(id: any, input: PartialInput<T>, options?: MongoCollectionService.UpdateOptions<T>): Promise<number>;
101
+ /**
102
+ * Update multiple documents in a collection
103
+ *
104
+ * @param input
105
+ * @param options
106
+ */
107
+ updateMany(input: OpraCommon.PartialInput<T>, options?: MongoCollectionService.UpdateManyOptions<T>): Promise<number>;
108
+ /**
109
+ * Generates Id value
110
+ *
111
+ * @protected
112
+ */
113
+ protected _generateId(): AnyId;
114
+ /**
115
+ * Generates a new Validator for encoding or returns from cache if already generated before
116
+ * @param operation
117
+ * @protected
118
+ */
119
+ protected _getEncoder(operation: 'create' | 'update'): vg.Validator;
120
+ /**
121
+ * Generates a new Valgen Validator for encode operation
122
+ *
123
+ * @param operation
124
+ * @protected
125
+ */
126
+ protected _generateEncoder(operation: 'create' | 'update'): vg.Validator;
23
127
  }
24
128
  /**
25
129
  *
@@ -27,7 +131,7 @@ export declare class MongoCollectionService<T extends mongodb.Document> extends
27
131
  */
28
132
  export declare namespace MongoCollectionService {
29
133
  interface Options extends MongoService.Options {
30
- keyField?: string | string[];
134
+ collectionKey?: string;
31
135
  defaultLimit?: number;
32
136
  }
33
137
  interface CreateOptions extends mongodb.InsertOneOptions {
@@ -44,21 +148,19 @@ export declare namespace MongoCollectionService {
44
148
  interface DeleteManyOptions<T> extends mongodb.DeleteOptions {
45
149
  filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
46
150
  }
47
- interface GetOptions<T = any> extends StrictOmit<mongodb.FindOptions, 'sort' | 'limit' | 'skip' | 'projection'> {
48
- filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
49
- pick?: string[];
50
- omit?: string[];
51
- include?: string[];
151
+ interface FindOneOptions<T = any> extends StrictOmit<FindManyOptions<T>, 'count' | 'limit'> {
52
152
  }
53
- interface FindManyOptions<T> extends StrictOmit<mongodb.FindOptions, 'sort' | 'projection'> {
153
+ interface FindManyOptions<T> extends mongodb.AggregateOptions {
54
154
  filter?: mongodb.Filter<T> | OpraCommon.OpraFilter.Ast | string;
55
155
  pick?: string[];
56
156
  omit?: string[];
57
157
  include?: string[];
58
158
  sort?: string[];
159
+ limit?: number;
160
+ skip?: number;
59
161
  count?: boolean;
60
162
  }
61
- interface UpdateOptions<T> extends mongodb.UpdateOptions {
163
+ interface UpdateOptions<T> extends StrictOmit<mongodb.FindOneAndUpdateOptions, 'projection' | 'returnDocument' | 'includeResultMetadata'> {
62
164
  pick?: string[];
63
165
  omit?: string[];
64
166
  include?: string[];