@appweaver/core 1.1.5 → 1.2.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/cache/eviction/lfu-eviction-index.js +3 -0
- package/export/export-service.d.ts +4 -2
- package/export/export-service.js +27 -17
- package/factory/create-model.js +72 -36
- package/factory/create-service.js +1 -1
- package/memory/in-memory.js +10 -6
- package/package.json +3 -3
- package/resource/index.d.ts +1 -0
- package/resource/index.js +1 -0
- package/resource/resource-schema.d.ts +0 -5
- package/resource/resource-schema.js +25 -10
- package/resource/resource-service.d.ts +214 -36
- package/resource/resource-service.js +247 -402
- package/resource/schemas/index.d.ts +3 -0
- package/resource/schemas/index.js +19 -0
- package/resource/schemas/resource-aggregate-schema.d.ts +54 -0
- package/resource/schemas/resource-aggregate-schema.js +131 -0
- package/resource/schemas/resource-filter-schema.d.ts +39 -0
- package/resource/schemas/resource-filter-schema.js +153 -0
- package/resource/schemas/resource-sort-schema.d.ts +37 -0
- package/resource/schemas/resource-sort-schema.js +114 -0
- package/resource/utils/aggregate-util.d.ts +113 -0
- package/resource/utils/aggregate-util.js +323 -0
- package/resource/utils/filter-util.d.ts +24 -0
- package/resource/utils/filter-util.js +283 -0
- package/resource/utils/index.d.ts +4 -0
- package/resource/utils/index.js +20 -0
- package/resource/utils/relation-util.d.ts +84 -0
- package/resource/utils/relation-util.js +344 -0
- package/resource/utils/sort-util.d.ts +20 -0
- package/resource/utils/sort-util.js +218 -0
- package/security/create-auth-resources.js +2 -2
- package/security/helper.js +1 -1
- package/security/resources/api-key/model.js +1 -0
- package/security/resources/api-key/service.d.ts +1 -1
- package/security/resources/role/model.js +1 -1
- package/server/create-server.js +6 -3
- package/server/register-route.js +1 -0
- package/server/swagger.js +87 -21
- package/server/virtual-projection.js +10 -8
- package/types/generated.d.ts +110 -4
- package/utils/schema-util.js +1 -1
- package/utils/virtual-util.js +1 -1
|
@@ -1,36 +1,179 @@
|
|
|
1
|
-
import { ActionType, AggregateResponse, AggregateSelect, IResourceService, QueryResponse, Resource, ResourceClient, ResourceData } from '@appweaver/common';
|
|
2
|
-
export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Resource, Create = ResourceData<Resource>, Update = Partial<ResourceData<Resource>>, Query =
|
|
1
|
+
import { ActionType, AggregateResponse, AggregateSelect, IResourceService, QueryFilter, QueryResponse, QuerySort, Resource, ResourceClient, ResourceData } from '@appweaver/common';
|
|
2
|
+
export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Resource, Create = ResourceData<Resource>, Update = Partial<ResourceData<Resource>>, Query = QueryFilter<ReadOne>> implements IResourceService<ReadOne, ReadMany, Create, Update, Query> {
|
|
3
3
|
readonly modelName: string;
|
|
4
|
+
/**
|
|
5
|
+
* Creates the service for the given resource model and resolves its database
|
|
6
|
+
* client from the Prisma client instance.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} modelName The resource model name this service operates on,
|
|
9
|
+
* as defined by its model file (i.e. `User`, `Post`).
|
|
10
|
+
* @throws An error if no database client exists for the provided model name.
|
|
11
|
+
*/
|
|
4
12
|
constructor(modelName: string);
|
|
13
|
+
/**
|
|
14
|
+
* The underlying Prisma model delegate for this resource, useful for
|
|
15
|
+
* executing custom database operations that the service methods do not cover.
|
|
16
|
+
*
|
|
17
|
+
* @returns {ResourceClient} The resource client of the model this service was
|
|
18
|
+
* created for.
|
|
19
|
+
*/
|
|
5
20
|
get client(): ResourceClient;
|
|
21
|
+
/**
|
|
22
|
+
* Finds a single resource by its id, applying the read restrictions and the
|
|
23
|
+
* access check of this service, and including all relation and file fields
|
|
24
|
+
* configured for output on the find action. A resource event is emitted after
|
|
25
|
+
* a successful lookup.
|
|
26
|
+
*
|
|
27
|
+
* @param {number} id The id of the resource to find.
|
|
28
|
+
* @returns {Promise<Object>} The found resource with its virtual fields and
|
|
29
|
+
* relation counts projected.
|
|
30
|
+
* @throws {@link HttpError} 404 if the resource does not exist or is filtered
|
|
31
|
+
* out by the read restrictions, 403 if the access check denies it, and 500 on
|
|
32
|
+
* a database error.
|
|
33
|
+
*/
|
|
6
34
|
find(id: number): Promise<ReadOne>;
|
|
7
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Queries a page of resources matching the provided filter. The filter is
|
|
37
|
+
* mapped to a database query, combined with the optional `searchText` full
|
|
38
|
+
* text search query and the read restrictions of this service, and executed
|
|
39
|
+
* together with the total count in a single transaction. A resource event is
|
|
40
|
+
* emitted after a successful query.
|
|
41
|
+
*
|
|
42
|
+
* @param {Object} [filter] The query filter object, supporting the logical
|
|
43
|
+
* (`_and`, `_or`, `_not`, `_nor`), comparison (`_eq`, `_ne`, `_gt`, `_gte`,
|
|
44
|
+
* `_lt`, `_lte`, `_in`, `_nin`, `_between`, `_like`, `_ilike`, `_starts`,
|
|
45
|
+
* `_ends`, `_contains`, `_exists`), list (`_has`, `_hasSome`, `_hasEvery`,
|
|
46
|
+
* `_isEmpty`), and relation (`_some`, `_every`, `_none`) operators, as well
|
|
47
|
+
* as plain field values. Its `searchText` property, if present, is passed to
|
|
48
|
+
* {@link ResourceService.textSearchQuery} instead of being matched as a
|
|
49
|
+
* field.
|
|
50
|
+
* @param {number} [page] The one-based page number of results to return.
|
|
51
|
+
* @param {number} [size] The maximum number of results per page.
|
|
52
|
+
* @param {QuerySort} [sort] The fields to sort by, either as a comma-separated
|
|
53
|
+
* list where a field prefixed with `-` is sorted in descending order
|
|
54
|
+
* (i.e. `-createdAt,id`), or as an object of field directions
|
|
55
|
+
* (i.e. `{ createdAt: 'desc', id: 'asc' }`). Both forms support the fields of
|
|
56
|
+
* the included to-one relations, given with a dot notation (`author.createdAt`)
|
|
57
|
+
* or as a nested object (`{ author: { createdAt: 'desc' } }`).
|
|
58
|
+
* @returns {Promise<QueryResponse<Object>>} The paged query response containing
|
|
59
|
+
* the returned resources, the count of the returned items and the total count
|
|
60
|
+
* of matching resources.
|
|
61
|
+
* @throws {@link HttpError} 400 if the sort input names a field that cannot be
|
|
62
|
+
* sorted by, and 500 on a database error.
|
|
63
|
+
*/
|
|
64
|
+
query(filter?: Query, page?: number, size?: number, sort?: QuerySort<ReadMany>): Promise<QueryResponse<ReadMany>>;
|
|
65
|
+
/**
|
|
66
|
+
* Aggregates resources matching the provided filter over a date range, both
|
|
67
|
+
* as a single overall result and as a series of results for the equally sized
|
|
68
|
+
* periods the range is split into. All aggregations are executed in a single
|
|
69
|
+
* transaction.
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} [filter] The query filter object, mapped the same way as in
|
|
72
|
+
* {@link ResourceService.query}.
|
|
73
|
+
* @param {AggregateSelect<Object>} select The aggregation operations to perform
|
|
74
|
+
* per field (i.e. `{ views: { count: true, sum: true } }`). Only the numeric
|
|
75
|
+
* fields of the model accept every operator, while its date fields accept
|
|
76
|
+
* `count`, `min`, `max`, `first` and `last`. The `first` and `last` operators
|
|
77
|
+
* take the value the earliest and the latest record of a period holds, which
|
|
78
|
+
* costs one additional query per period and boundary, skipped for the periods
|
|
79
|
+
* holding no record.
|
|
80
|
+
* @param {string} [dateField] The date field the range is applied on.
|
|
81
|
+
* @param {string} [from] The ISO date string of the range start. Defaults to
|
|
82
|
+
* seven days before the range end.
|
|
83
|
+
* @param {string} [to] The ISO date string of the range end. Defaults to the
|
|
84
|
+
* current date and time.
|
|
85
|
+
* @param {number} [step] The size of a single period in units of the
|
|
86
|
+
* automatically selected time unit. If not provided, one unit is used and the
|
|
87
|
+
* unit is derived from the range length (seconds up to a minute, minutes up to
|
|
88
|
+
* an hour, hours up to a day, days up to a month, months up to a year, and
|
|
89
|
+
* years beyond that).
|
|
90
|
+
* @param {boolean} [safeIncrement] Whether the period increments use the
|
|
91
|
+
* derived time unit and stay consistent across daylight saving time changes.
|
|
92
|
+
* When false, the step is interpreted in seconds.
|
|
93
|
+
* @returns {Promise<AggregateResponse<Object>>} The aggregation response with
|
|
94
|
+
* the overall total and one result per period, each labeled with the median
|
|
95
|
+
* date of its period.
|
|
96
|
+
* @throws {@link HttpError} 400 if the selection is empty or names a field or
|
|
97
|
+
* operator that cannot be aggregated, and 500 on a database error.
|
|
98
|
+
*/
|
|
8
99
|
aggregate(filter: Query | undefined, select: AggregateSelect<ReadOne>, dateField?: string, from?: string, to?: string, step?: number, safeIncrement?: boolean): Promise<AggregateResponse<ReadOne>>;
|
|
100
|
+
/**
|
|
101
|
+
* Creates a new resource. The provided data is merged with the write
|
|
102
|
+
* restrictions, checked for access, sanitized against the model configuration
|
|
103
|
+
* and mapped to the relation write actions (connect, create, or
|
|
104
|
+
* connect-or-create) before the record is created. The `createdBy` audit
|
|
105
|
+
* relation is connected to the currently authenticated user when configured.
|
|
106
|
+
* The resource cache is invalidated and a resource event is emitted after a
|
|
107
|
+
* successful create.
|
|
108
|
+
*
|
|
109
|
+
* @param {Object} data The data of the resource to create, including any inline
|
|
110
|
+
* relation and file payloads.
|
|
111
|
+
* @returns {Promise<Object>} The created resource with its virtual fields and
|
|
112
|
+
* relation counts projected.
|
|
113
|
+
* @throws {@link HttpError} 403 if the access check denies the action, 400 if
|
|
114
|
+
* an inline relation payload is missing required fields or the relation does
|
|
115
|
+
* not accept new records, and 500 on a database error.
|
|
116
|
+
*/
|
|
9
117
|
create(data: Create): Promise<ReadOne>;
|
|
118
|
+
/**
|
|
119
|
+
* Updates an existing resource by its id. The current record is loaded with
|
|
120
|
+
* the read restrictions applied and checked for access, then updated with the
|
|
121
|
+
* data merged with the write restrictions inside a single transaction.
|
|
122
|
+
* Relations missing from the new value are disconnected, or deleted when
|
|
123
|
+
* `orphanRemoval` is configured for them. The resource cache is invalidated
|
|
124
|
+
* and a resource event carrying both the previous and the current state is
|
|
125
|
+
* emitted after a successful update.
|
|
126
|
+
*
|
|
127
|
+
* @param {number} id The id of the resource to update.
|
|
128
|
+
* @param {Object} data The partial data to update the resource with, including
|
|
129
|
+
* any inline relation and file payloads.
|
|
130
|
+
* @returns {Promise<Object>} The updated resource with its virtual fields and
|
|
131
|
+
* relation counts projected.
|
|
132
|
+
* @throws {@link HttpError} 404 if the resource does not exist or is filtered
|
|
133
|
+
* out by the read restrictions, 403 if the access check denies the action, 400
|
|
134
|
+
* if an inline relation payload is missing required fields or the relation
|
|
135
|
+
* does not accept new records, and 500 on a database error.
|
|
136
|
+
*/
|
|
10
137
|
update(id: number, data: Update): Promise<ReadOne>;
|
|
138
|
+
/**
|
|
139
|
+
* Deletes an existing resource by its id. The current record is loaded with
|
|
140
|
+
* the read restrictions applied and checked for access before it is deleted
|
|
141
|
+
* inside a single transaction. The resource cache is invalidated and a
|
|
142
|
+
* resource event is emitted after a successful delete.
|
|
143
|
+
*
|
|
144
|
+
* @param {number} id The id of the resource to delete.
|
|
145
|
+
* @returns {Promise<Object>} The deleted resource with its virtual fields and
|
|
146
|
+
* relation counts projected.
|
|
147
|
+
* @throws {@link HttpError} 404 if the resource does not exist or is filtered
|
|
148
|
+
* out by the read restrictions, 403 if the access check denies the action, and
|
|
149
|
+
* 500 on a database error.
|
|
150
|
+
*/
|
|
11
151
|
delete(id: number): Promise<ReadOne>;
|
|
12
152
|
/**
|
|
13
153
|
* This method should be overridden with custom logic for restricting read
|
|
14
154
|
* operations on specific data for currently logged-in user and other
|
|
15
155
|
* authorization rules. The returned object will be applied as a filter on
|
|
16
156
|
* all actions (except create action) which will prevent unwanted data access
|
|
17
|
-
* and modifications. This method can also cancel current action by
|
|
18
|
-
* an error, recommended is {@link HttpError } with appropriate HTTP
|
|
19
|
-
* code.
|
|
157
|
+
* and modifications. This method can also cancel the current action by
|
|
158
|
+
* throwing an error, recommended is {@link HttpError } with appropriate HTTP
|
|
159
|
+
* error code.
|
|
20
160
|
*
|
|
21
|
-
* @param action The called action method on this service (find,
|
|
22
|
-
* aggregate, update, or delete)
|
|
23
|
-
* @param data The passed data to the called function
|
|
24
|
-
* object. If the data is a type of number, then it represents the
|
|
25
|
-
* id, otherwise it depends on the action and can be one of the
|
|
161
|
+
* @param {ActionType} action The called action method on this service (find,
|
|
162
|
+
* query, aggregate, update, or delete)
|
|
163
|
+
* @param {Object|number} data The passed data to the called function can be
|
|
164
|
+
* number or object. If the data is a type of number, then it represents the
|
|
165
|
+
* resource id, otherwise it depends on the action and can be one of the
|
|
166
|
+
* following:
|
|
26
167
|
*
|
|
27
168
|
* - query and aggregate -> filter object
|
|
28
169
|
* - update -> combined id and the data object (i.e. { id, ...data })
|
|
29
170
|
*
|
|
30
171
|
* For other actions (find and delete) it represents the resource id.
|
|
31
|
-
* @return The
|
|
172
|
+
* @return {Promise<Object>} The database-level `where` conditions containing
|
|
173
|
+
* additional query restrictions. The returned object is applied directly to
|
|
174
|
+
* the database query, so it uses the native Prisma filter syntax.
|
|
32
175
|
*/
|
|
33
|
-
protected readRestrictions(action: Exclude<ActionType, 'create'>, data: any): Promise<
|
|
176
|
+
protected readRestrictions(action: Exclude<ActionType, 'create'>, data: any): Promise<any>;
|
|
34
177
|
/**
|
|
35
178
|
* This method should be overridden with custom logic for restricting write
|
|
36
179
|
* operations on specific data for currently logged-in users and other
|
|
@@ -40,13 +183,15 @@ export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Res
|
|
|
40
183
|
* current action by throwing an error, with the recommended type being
|
|
41
184
|
* {@link HttpError} with the appropriate HTTP error code.
|
|
42
185
|
*
|
|
43
|
-
* @param action The called action method on this service
|
|
44
|
-
*
|
|
45
|
-
*
|
|
186
|
+
* @param {'create'|'update'} action The called action method on this service
|
|
187
|
+
* (create or update)
|
|
188
|
+
* @param {Object} data The passed data to the called function, which should be
|
|
189
|
+
* an object representing the resource data to be created or updated. For
|
|
46
190
|
* update operations, this object will also include the resource ID.
|
|
47
191
|
*
|
|
48
|
-
* @return A partial object containing additional data
|
|
49
|
-
* applied, or an empty object if no restrictions are
|
|
192
|
+
* @return {Promise<Object>} A partial object containing additional data
|
|
193
|
+
* restrictions to be applied, or an empty object if no restrictions are
|
|
194
|
+
* necessary.
|
|
50
195
|
*/
|
|
51
196
|
protected writeRestrictions(action: 'create' | 'update', data: any): Promise<Partial<Create & Update>>;
|
|
52
197
|
/**
|
|
@@ -55,10 +200,11 @@ export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Res
|
|
|
55
200
|
* a currently authenticated user or other logic, this method should return
|
|
56
201
|
* false. Otherwise, it returns true and continues with the request execution.
|
|
57
202
|
*
|
|
58
|
-
* @param action The called action method on this service (find,
|
|
59
|
-
* aggregate, create, update, or delete)
|
|
60
|
-
* @param resource The resource object that is being
|
|
61
|
-
* @returns True if the access for resource is granted, false
|
|
203
|
+
* @param {ActionType} action The called action method on this service (find,
|
|
204
|
+
* query, aggregate, create, update, or delete)
|
|
205
|
+
* @param {Object} resource The resource object that is being checked for access.
|
|
206
|
+
* @returns {Promise<boolean>} True if the access for resource is granted, false
|
|
207
|
+
* otherwise.
|
|
62
208
|
*/
|
|
63
209
|
protected checkAccess(action: ActionType, resource: ReadOne): Promise<boolean>;
|
|
64
210
|
/**
|
|
@@ -67,22 +213,54 @@ export declare abstract class ResourceService<ReadOne = Resource, ReadMany = Res
|
|
|
67
213
|
* search text into a format suitable for text search functionality, returning
|
|
68
214
|
* a query object that can be used to filter results.
|
|
69
215
|
*
|
|
70
|
-
* @param searchText The text string used for searching resources.
|
|
71
|
-
* @returns A query object that represents the conditions for the text
|
|
72
|
-
* search operation
|
|
73
|
-
* retrieve matching resources.
|
|
216
|
+
* @param {string} searchText The text string used for searching resources.
|
|
217
|
+
* @returns {Object} A query object that represents the conditions for the text
|
|
218
|
+
* search operation, using the native Prisma filter syntax. This will be used
|
|
219
|
+
* by the database query methods to retrieve matching resources.
|
|
220
|
+
*/
|
|
221
|
+
protected textSearchQuery(searchText: string): any;
|
|
222
|
+
/**
|
|
223
|
+
* Removes the `searchText` property from the provided filter and converts it
|
|
224
|
+
* into a text search query using
|
|
225
|
+
* {@link ResourceService.textSearchQuery}. The filter object is mutated so the
|
|
226
|
+
* search text is not matched as a regular resource field.
|
|
227
|
+
*
|
|
228
|
+
* @param {Object} filter The request filter object, possibly containing a
|
|
229
|
+
* `searchText` property. The property is deleted from this object when present.
|
|
230
|
+
* @returns {Object} The text search query for the extracted search text, or an
|
|
231
|
+
* empty object if the filter contains no search text.
|
|
74
232
|
*/
|
|
75
|
-
protected textSearchQuery(searchText: string): Query;
|
|
76
233
|
private extractTextSearchQuery;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Prepares a resource for the response by resolving the virtual fields of its
|
|
236
|
+
* model and flattening the Prisma `_count` aggregation into the individual
|
|
237
|
+
* relation count fields (i.e. `_count.posts` becomes `postsCount`).
|
|
238
|
+
*
|
|
239
|
+
* @param {Object} resource The resource object as returned by the database
|
|
240
|
+
* client.
|
|
241
|
+
* @returns {Object} The same resource with the virtual fields resolved and, if a
|
|
242
|
+
* `_count` selection was present, with a count property per counted relation
|
|
243
|
+
* and the `_count` property removed.
|
|
244
|
+
*/
|
|
80
245
|
private projectResource;
|
|
246
|
+
/**
|
|
247
|
+
* Prepares a write payload for the database by removing the virtual fields
|
|
248
|
+
* that have no column, filling in default values for the hidden required
|
|
249
|
+
* scalars of a create action, and recursively applying the same rules to the
|
|
250
|
+
* nested relation and file payloads. Unique key values, arrays of them and null
|
|
251
|
+
* values are left untouched, so the relation actions can still map them to the
|
|
252
|
+
* connect and disconnect operations.
|
|
253
|
+
*
|
|
254
|
+
* @param {'create'|'update'} action The write action the payload is sanitized
|
|
255
|
+
* for. Default values for the hidden required scalars are only applied on a
|
|
256
|
+
* create action.
|
|
257
|
+
* @param {Object} data The write payload to sanitize.
|
|
258
|
+
* @param {string} [resourceName] The name of the model the payload belongs to.
|
|
259
|
+
* Defaults to the model of this service and is set to the related model name
|
|
260
|
+
* when recursing into a nested relation or file payload.
|
|
261
|
+
* @returns {Object} A shallow copy of the payload without the virtual fields,
|
|
262
|
+
* with the missing hidden required scalars defaulted, and with the nested
|
|
263
|
+
* payloads sanitized against their own models.
|
|
264
|
+
*/
|
|
81
265
|
private sanitizeData;
|
|
82
|
-
private mapQueryFilter;
|
|
83
|
-
private mapRelationInclusions;
|
|
84
|
-
private buildNestedInclusion;
|
|
85
|
-
private shouldIncludeRelation;
|
|
86
|
-
private mapRelationActions;
|
|
87
|
-
private createdByConnect;
|
|
88
266
|
}
|