@loomcore/api 0.0.52 → 0.0.54
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.
|
@@ -52,10 +52,8 @@ export class ApiController {
|
|
|
52
52
|
apiUtils.apiResponse(res, 200, { data: pagedResult }, this.modelSpec, this.publicSchema);
|
|
53
53
|
}
|
|
54
54
|
async getById(req, res, next) {
|
|
55
|
-
console.log('Starting getById, id:', req.params?.id);
|
|
56
55
|
let id = req.params?.id;
|
|
57
56
|
res.set('Content-Type', 'application/json');
|
|
58
|
-
console.log('Calling this.service.getById()');
|
|
59
57
|
const entity = await this.service.getById(req.userContext, id);
|
|
60
58
|
apiUtils.apiResponse(res, 200, { data: entity }, this.modelSpec, this.publicSchema);
|
|
61
59
|
}
|
|
@@ -73,7 +73,6 @@ export class GenericApiService {
|
|
|
73
73
|
return pipeline;
|
|
74
74
|
}
|
|
75
75
|
async getAll(userContext) {
|
|
76
|
-
console.log('In GenericApiService.getAll');
|
|
77
76
|
const query = this.prepareQuery(userContext, {});
|
|
78
77
|
let entities = [];
|
|
79
78
|
if (this.getAdditionalPipelineStages().length > 0) {
|
|
@@ -87,9 +86,8 @@ export class GenericApiService {
|
|
|
87
86
|
return this.transformList(entities);
|
|
88
87
|
}
|
|
89
88
|
async get(userContext, queryOptions = { ...DefaultQueryOptions }) {
|
|
90
|
-
console.log('In GenericApiService.get');
|
|
91
89
|
const preparedOptions = this.prepareQueryOptions(userContext, queryOptions);
|
|
92
|
-
const match = dbUtils.buildMongoMatchFromQueryOptions(preparedOptions);
|
|
90
|
+
const match = dbUtils.buildMongoMatchFromQueryOptions(preparedOptions, this.modelSpec);
|
|
93
91
|
const additionalStages = this.getAdditionalPipelineStages();
|
|
94
92
|
const results = [...additionalStages];
|
|
95
93
|
if (preparedOptions.orderBy) {
|
|
@@ -124,35 +122,25 @@ export class GenericApiService {
|
|
|
124
122
|
return pagedResult;
|
|
125
123
|
}
|
|
126
124
|
async getById(userContext, id) {
|
|
127
|
-
console.log(`--- GenericApiService.getById ENTER ---`);
|
|
128
|
-
console.log(`ID received: ${id}`);
|
|
129
125
|
if (!entityUtils.isValidObjectId(id)) {
|
|
130
126
|
throw new BadRequestError('id is not a valid ObjectId');
|
|
131
127
|
}
|
|
132
128
|
const baseQuery = { _id: new ObjectId(id) };
|
|
133
129
|
const query = this.prepareQuery(userContext, baseQuery);
|
|
134
|
-
console.log('Constructed query:', JSON.stringify(query, null, 2));
|
|
135
130
|
let entity = null;
|
|
136
131
|
if (this.getAdditionalPipelineStages().length > 0) {
|
|
137
|
-
console.log('Branch: Executing with aggregation pipeline.');
|
|
138
132
|
const pipeline = [
|
|
139
133
|
{ $match: query },
|
|
140
134
|
...this.getAdditionalPipelineStages()
|
|
141
135
|
];
|
|
142
|
-
console.log('Aggregation Pipeline:', JSON.stringify(pipeline, null, 2));
|
|
143
136
|
entity = await this.collection.aggregate(pipeline).next();
|
|
144
137
|
}
|
|
145
138
|
else {
|
|
146
|
-
console.log('Branch: Executing with findOne.');
|
|
147
139
|
entity = await this.collection.findOne(query);
|
|
148
140
|
}
|
|
149
|
-
console.log('IMMEDIATE DB RESULT (entity):', JSON.stringify(entity, null, 2));
|
|
150
141
|
if (!entity) {
|
|
151
|
-
console.log('Entity not found, throwing IdNotFoundError.');
|
|
152
142
|
throw new IdNotFoundError();
|
|
153
143
|
}
|
|
154
|
-
console.log('Entity before transformSingle:', JSON.stringify(entity, null, 2));
|
|
155
|
-
console.log(`--- GenericApiService.getById EXIT ---`);
|
|
156
144
|
return this.transformSingle(entity);
|
|
157
145
|
}
|
|
158
146
|
async getCount(userContext) {
|
|
@@ -373,14 +361,12 @@ export class GenericApiService {
|
|
|
373
361
|
return list.map(item => this.transformSingle(item));
|
|
374
362
|
}
|
|
375
363
|
transformSingle(single) {
|
|
376
|
-
console.log('Starting base class transformSingle, entity:', JSON.stringify(single, null, 2));
|
|
377
364
|
if (!single)
|
|
378
365
|
return single;
|
|
379
366
|
if (!this.modelSpec?.fullSchema) {
|
|
380
367
|
throw new ServerError(`Cannot transform entity: No model specification with schema provided for ${this.pluralResourceName}`);
|
|
381
368
|
}
|
|
382
369
|
const transformedEntity = dbUtils.convertObjectIdsToStrings(single, this.modelSpec.fullSchema);
|
|
383
|
-
console.log('Leaving base class transformSingle, transformedEntity:', JSON.stringify(transformedEntity, null, 2));
|
|
384
370
|
return transformedEntity;
|
|
385
371
|
}
|
|
386
372
|
stripSenderProvidedSystemProperties(userContext, doc, allowId = false) {
|
package/dist/utils/db.utils.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
2
|
import { TSchema } from '@sinclair/typebox';
|
|
3
|
-
import { IQueryOptions, Filter } from '@loomcore/common/models';
|
|
3
|
+
import { IQueryOptions, Filter, IModelSpec } from '@loomcore/common/models';
|
|
4
4
|
export declare const PROPERTIES_THAT_ARE_NOT_OBJECT_IDS: string[];
|
|
5
5
|
declare function convertObjectIdsToStrings<T>(entity: T, schema?: TSchema): T;
|
|
6
6
|
declare function convertStringsToObjectIds(entity: any, schema: TSchema): any;
|
|
7
7
|
declare function convertStringToObjectId(value: any): ObjectId | any;
|
|
8
|
-
declare function buildMongoMatchFromQueryOptions(queryOptions: IQueryOptions): {
|
|
8
|
+
declare function buildMongoMatchFromQueryOptions(queryOptions: IQueryOptions, modelSpec?: IModelSpec): {
|
|
9
9
|
$match: any;
|
|
10
10
|
};
|
|
11
11
|
declare function buildSQLWhereClauseFromQueryOptions(queryOptions: IQueryOptions, columnAliasMap: {
|
package/dist/utils/db.utils.js
CHANGED
|
@@ -2,6 +2,21 @@ import { ObjectId } from 'mongodb';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import { entityUtils } from '@loomcore/common/utils';
|
|
4
4
|
import { stringUtils } from './string.utils.js';
|
|
5
|
+
function getPropertySchema(key, schema) {
|
|
6
|
+
if (!schema || typeof schema !== 'object')
|
|
7
|
+
return undefined;
|
|
8
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
9
|
+
for (const nestedSchema of schema.allOf) {
|
|
10
|
+
const propSchema = getPropertySchema(key, nestedSchema);
|
|
11
|
+
if (propSchema)
|
|
12
|
+
return propSchema;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (schema.type === 'object' && schema.properties) {
|
|
16
|
+
return schema.properties[key];
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
5
20
|
export const PROPERTIES_THAT_ARE_NOT_OBJECT_IDS = ['_orgId'];
|
|
6
21
|
function convertObjectIdsToStrings(entity, schema) {
|
|
7
22
|
if (!entity)
|
|
@@ -149,27 +164,30 @@ function convertStringToObjectId(value) {
|
|
|
149
164
|
}
|
|
150
165
|
return value;
|
|
151
166
|
}
|
|
152
|
-
function buildMongoMatchFromQueryOptions(queryOptions) {
|
|
167
|
+
function buildMongoMatchFromQueryOptions(queryOptions, modelSpec) {
|
|
153
168
|
const filters = queryOptions.filters || {};
|
|
169
|
+
const schema = modelSpec?.fullSchema;
|
|
154
170
|
let match = {};
|
|
155
171
|
for (const [key, value] of Object.entries(filters)) {
|
|
156
172
|
if (value) {
|
|
173
|
+
const propSchema = schema ? getPropertySchema(key, schema) : undefined;
|
|
157
174
|
if (value.eq !== undefined) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
&& entityUtils.isValidObjectId(
|
|
162
|
-
match[key] = new ObjectId(
|
|
175
|
+
const isObjectIdField = propSchema?.format === 'objectid';
|
|
176
|
+
const valueToCompare = value.eq;
|
|
177
|
+
if ((isObjectIdField || (!schema && key.endsWith('Id') && !PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(key)))
|
|
178
|
+
&& typeof valueToCompare === 'string' && entityUtils.isValidObjectId(valueToCompare)) {
|
|
179
|
+
match[key] = new ObjectId(valueToCompare);
|
|
163
180
|
}
|
|
164
|
-
else if (typeof
|
|
165
|
-
match[key] = Number(
|
|
181
|
+
else if (typeof valueToCompare === 'string' && !isNaN(Number(valueToCompare))) {
|
|
182
|
+
match[key] = Number(valueToCompare);
|
|
166
183
|
}
|
|
167
184
|
else {
|
|
168
|
-
match[key] =
|
|
185
|
+
match[key] = valueToCompare;
|
|
169
186
|
}
|
|
170
187
|
}
|
|
171
188
|
else if (value.in !== undefined && Array.isArray(value.in)) {
|
|
172
|
-
|
|
189
|
+
const isObjectIdArray = propSchema?.type === 'array' && propSchema.items?.format === 'objectid';
|
|
190
|
+
if (isObjectIdArray || (!schema && (key.endsWith('Id') || key.endsWith('Ids')) && !PROPERTIES_THAT_ARE_NOT_OBJECT_IDS.includes(key))) {
|
|
173
191
|
const objectIds = value.in
|
|
174
192
|
.filter(val => typeof val === 'string' && entityUtils.isValidObjectId(val))
|
|
175
193
|
.map(val => new ObjectId(val));
|