@opra/core 0.23.1 → 0.24.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.
Files changed (30) hide show
  1. package/cjs/adapter/{operation-context.js → endpoint-context.js} +5 -5
  2. package/cjs/adapter/http/http-adapter-base.js +2 -4
  3. package/cjs/adapter/http/request-handlers/entity-request-handler.js +82 -68
  4. package/cjs/adapter/http/request-handlers/request-handler-base.js +5 -5
  5. package/cjs/adapter/http/request-handlers/storage-request-handler.js +16 -17
  6. package/cjs/adapter/platform-adapter.host.js +1 -1
  7. package/cjs/augmentation/resource.augmentation.js +6 -6
  8. package/cjs/index.js +1 -1
  9. package/esm/adapter/{operation-context.js → endpoint-context.js} +4 -4
  10. package/esm/adapter/http/http-adapter-base.js +2 -4
  11. package/esm/adapter/http/request-handlers/entity-request-handler.js +82 -68
  12. package/esm/adapter/http/request-handlers/request-handler-base.js +5 -5
  13. package/esm/adapter/http/request-handlers/storage-request-handler.js +16 -17
  14. package/esm/adapter/platform-adapter.host.js +1 -1
  15. package/esm/augmentation/resource.augmentation.js +7 -7
  16. package/esm/index.js +1 -1
  17. package/i18n/en/error.json +3 -2
  18. package/package.json +2 -2
  19. package/types/adapter/{operation-context.d.ts → endpoint-context.d.ts} +3 -3
  20. package/types/adapter/http/request-handlers/entity-request-handler.d.ts +4 -4
  21. package/types/adapter/http/request-handlers/request-handler-base.d.ts +1 -1
  22. package/types/adapter/http/request-handlers/storage-request-handler.d.ts +3 -3
  23. package/types/adapter/platform-adapter.d.ts +2 -2
  24. package/types/adapter/request.d.ts +1 -1
  25. package/types/adapter/response.d.ts +1 -1
  26. package/types/augmentation/collection.augmentation.d.ts +21 -16
  27. package/types/augmentation/resource.augmentation.d.ts +6 -1
  28. package/types/augmentation/singleton.augmentation.d.ts +14 -10
  29. package/types/augmentation/storage.augmentation.d.ts +9 -5
  30. package/types/index.d.ts +1 -1
@@ -2,7 +2,7 @@ import bodyParser from 'body-parser';
2
2
  import { toBoolean, toInt } from 'putil-varhelpers';
3
3
  import * as valgen from 'valgen';
4
4
  import { BadRequestError, Collection, HttpHeaderCodes, HttpStatusCodes, InternalServerError, MethodNotAllowedError, OpraException, ResourceNotFoundError, Singleton, translate, } from '@opra/common';
5
- import { OperationContext } from '../../operation-context.js';
5
+ import { EndpointContext } from '../../endpoint-context.js';
6
6
  import { RequestHost } from '../../request.host.js';
7
7
  import { ResponseHost } from '../../response.host.js';
8
8
  import { parseArrayParam } from '../helpers/query-parsers.js';
@@ -23,9 +23,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
23
23
  if (!request)
24
24
  return;
25
25
  const response = new ResponseHost({ http: outgoing });
26
- const context = OperationContext.from(executionContext, request, response);
27
- // Execute operation
28
- await this.executeOperation(context);
26
+ const context = EndpointContext.from(executionContext, request, response);
27
+ await this.callEndpoint(context);
29
28
  if (response.errors.length) {
30
29
  context.errors.push(...response.errors);
31
30
  return;
@@ -48,7 +47,15 @@ export class EntityRequestHandler extends RequestHandlerBase {
48
47
  }
49
48
  async parseRequest(incoming) {
50
49
  const p = incoming.parsedUrl.path[0];
51
- const resource = this.adapter.api.getResource(p.resource);
50
+ const resource = this.adapter.api.getResource(p.resource, true);
51
+ if (!resource)
52
+ throw new BadRequestError({
53
+ message: translate('error:SOURCE_NOT_FOUND,', 'Resource not found'),
54
+ code: 'SOURCE_NOT_FOUND',
55
+ details: {
56
+ path: incoming.parsedUrl.address
57
+ }
58
+ });
52
59
  try {
53
60
  if (resource instanceof Collection)
54
61
  return await this.parseCollectionRequest(resource, incoming);
@@ -68,18 +75,18 @@ export class EntityRequestHandler extends RequestHandlerBase {
68
75
  throw new BadRequestError(e);
69
76
  }
70
77
  }
71
- async executeOperation(context) {
78
+ async callEndpoint(context) {
72
79
  const request = context.request;
73
80
  const { response } = context;
74
81
  const resource = request.resource;
75
- // Call operation handler method
82
+ // Call endpoint handler method
76
83
  let value;
77
84
  try {
78
- value = await request.controller[request.operation].call(request.controller, context);
85
+ value = await request.controller[request.endpoint].call(request.controller, context);
79
86
  if (value == null)
80
87
  value = response.value;
81
- const { operation } = request;
82
- if (operation === 'delete' || operation === 'deleteMany' || operation === 'updateMany') {
88
+ const { endpoint } = request;
89
+ if (endpoint === 'delete' || endpoint === 'deleteMany' || endpoint === 'updateMany') {
83
90
  let affected = 0;
84
91
  if (typeof value === 'number')
85
92
  affected = value;
@@ -87,15 +94,15 @@ export class EntityRequestHandler extends RequestHandlerBase {
87
94
  affected = value ? 1 : 0;
88
95
  if (typeof value === 'object')
89
96
  affected = value.affected || value.affectedRows ||
90
- (operation === 'updateMany' ? value.updated : value.deleted);
97
+ (endpoint === 'updateMany' ? value.updated : value.deleted);
91
98
  response.value = affected;
92
99
  }
93
100
  else {
94
- // "get" and "update" operations must return the entity instance, otherwise it means resource not found
95
- if (value == null && (request.operation === 'get' || request.operation === 'update'))
101
+ // "get" and "update" endpoints must return the entity instance, otherwise it means resource not found
102
+ if (value == null && (request.endpoint === 'get' || request.endpoint === 'update'))
96
103
  throw new ResourceNotFoundError(resource.name, request.key);
97
- // "findMany" operation should return array of entity instances
98
- if (request.operation === 'findMany')
104
+ // "findMany" endpoint should return array of entity instances
105
+ if (request.endpoint === 'findMany')
99
106
  value = value == null ? [] : Array.isArray(value) ? value : [value];
100
107
  else
101
108
  value = value == null ? {} : Array.isArray(value) ? value[0] : value;
@@ -111,33 +118,40 @@ export class EntityRequestHandler extends RequestHandlerBase {
111
118
  const resource = request.resource;
112
119
  const outgoing = response.switchToHttp();
113
120
  let responseObject;
114
- if (request.operation === 'delete' || request.operation === 'deleteMany' || request.operation === 'updateMany') {
121
+ if (request.endpoint === 'delete' || request.endpoint === 'deleteMany') {
122
+ responseObject = {
123
+ resource: resource.name,
124
+ operation: 'delete',
125
+ affected: response.value
126
+ };
127
+ }
128
+ else if (request.endpoint === 'updateMany') {
115
129
  responseObject = {
116
130
  resource: resource.name,
117
- operation: request.operation,
131
+ operation: 'update',
118
132
  affected: response.value
119
133
  };
120
134
  }
121
135
  else {
122
136
  if (!response.value)
123
- throw new InternalServerError(`"${request.operation}" operation should return value`);
124
- const encode = resource.getEncoder(request.operation);
137
+ throw new InternalServerError(`"${request.endpoint}" endpoint should return value`);
138
+ const encode = resource.getEncoder(request.endpoint);
125
139
  const data = encode(response.value, { coerce: true });
126
- if (request.operation === 'create')
140
+ if (request.endpoint === 'create')
127
141
  outgoing.statusCode = 201;
128
142
  responseObject = {
129
143
  resource: resource.name,
130
- operation: request.operation,
144
+ endpoint: request.endpoint,
131
145
  data
132
146
  };
133
- if (request.operation === 'create' || request.operation === 'update')
147
+ if (request.endpoint === 'create' || request.endpoint === 'update')
134
148
  responseObject.affected = 1;
135
- if (request.operation === 'findMany' && response.count != null && response.count >= 0)
149
+ if (request.endpoint === 'findMany' && response.count != null && response.count >= 0)
136
150
  responseObject.totalCount = response.count;
137
151
  }
138
152
  outgoing.statusCode = outgoing.statusCode || HttpStatusCodes.OK;
139
153
  const body = this.adapter._i18n.deep(responseObject);
140
- outgoing.setHeader(HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
154
+ outgoing.setHeader(HttpHeaderCodes.Content_Type, 'application/opra+json; charset=utf-8');
141
155
  outgoing.send(JSON.stringify(body));
142
156
  outgoing.end();
143
157
  }
@@ -151,8 +165,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
151
165
  switch (incoming.method) {
152
166
  case 'POST': {
153
167
  if (p.key == null) {
154
- const operationMeta = await this.assertOperation(resource, 'create');
155
- const jsonReader = this.getBodyLoader(operationMeta);
168
+ const endpointMeta = await this.assertEndpoint(resource, 'create');
169
+ const jsonReader = this.getBodyLoader(endpointMeta);
156
170
  const decode = resource.getDecoder('create');
157
171
  let data = await jsonReader(incoming);
158
172
  data = decode(data, { coerce: true });
@@ -160,11 +174,11 @@ export class EntityRequestHandler extends RequestHandlerBase {
160
174
  const omit = parseArrayParam(params.get('$omit'));
161
175
  const include = parseArrayParam(params.get('$include'));
162
176
  return new RequestHost({
163
- controller: operationMeta.controller,
177
+ controller: endpointMeta.controller,
164
178
  http: incoming,
165
179
  contentId,
166
180
  resource,
167
- operation: 'create',
181
+ endpoint: 'create',
168
182
  data,
169
183
  params: {
170
184
  pick: pick && resource.normalizeFieldPath(pick),
@@ -177,24 +191,24 @@ export class EntityRequestHandler extends RequestHandlerBase {
177
191
  }
178
192
  case 'DELETE': {
179
193
  if (p.key != null) {
180
- const operationMeta = await this.assertOperation(resource, 'delete');
194
+ const endpointMeta = await this.assertEndpoint(resource, 'delete');
181
195
  return new RequestHost({
182
- controller: operationMeta.controller,
196
+ controller: endpointMeta.controller,
183
197
  http: incoming,
184
198
  contentId,
185
199
  resource,
186
- operation: 'delete',
200
+ endpoint: 'delete',
187
201
  key: resource.parseKeyValue(p.key)
188
202
  });
189
203
  }
190
- const operationMeta = await this.assertOperation(resource, 'deleteMany');
204
+ const endpointMeta = await this.assertEndpoint(resource, 'deleteMany');
191
205
  const filter = resource.normalizeFilter(params.get('$filter'));
192
206
  return new RequestHost({
193
- controller: operationMeta.controller,
207
+ controller: endpointMeta.controller,
194
208
  http: incoming,
195
209
  contentId,
196
210
  resource,
197
- operation: 'deleteMany',
211
+ endpoint: 'deleteMany',
198
212
  params: {
199
213
  filter
200
214
  }
@@ -205,13 +219,13 @@ export class EntityRequestHandler extends RequestHandlerBase {
205
219
  const omit = parseArrayParam(params.get('$omit'));
206
220
  const include = parseArrayParam(params.get('$include'));
207
221
  if (p.key != null) {
208
- const operationMeta = await this.assertOperation(resource, 'get');
222
+ const endpointMeta = await this.assertEndpoint(resource, 'get');
209
223
  return new RequestHost({
210
- controller: operationMeta.controller,
224
+ controller: endpointMeta.controller,
211
225
  http: incoming,
212
226
  contentId,
213
227
  resource,
214
- operation: 'get',
228
+ endpoint: 'get',
215
229
  key: resource.parseKeyValue(p.key),
216
230
  params: {
217
231
  pick: pick && resource.normalizeFieldPath(pick),
@@ -220,15 +234,15 @@ export class EntityRequestHandler extends RequestHandlerBase {
220
234
  }
221
235
  });
222
236
  }
223
- const operationMeta = await this.assertOperation(resource, 'findMany');
237
+ const endpointMeta = await this.assertEndpoint(resource, 'findMany');
224
238
  const filter = resource.normalizeFilter(params.get('$filter'));
225
239
  const sort = parseArrayParam(params.get('$sort'));
226
240
  return new RequestHost({
227
- controller: operationMeta.controller,
241
+ controller: endpointMeta.controller,
228
242
  http: incoming,
229
243
  contentId,
230
244
  resource,
231
- operation: 'findMany',
245
+ endpoint: 'findMany',
232
246
  params: {
233
247
  pick: pick && resource.normalizeFieldPath(pick),
234
248
  omit: omit && resource.normalizeFieldPath(omit),
@@ -244,8 +258,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
244
258
  }
245
259
  case 'PATCH': {
246
260
  if (p.key != null) {
247
- const operationMeta = await this.assertOperation(resource, 'update');
248
- const jsonReader = this.getBodyLoader(operationMeta);
261
+ const endpointMeta = await this.assertEndpoint(resource, 'update');
262
+ const jsonReader = this.getBodyLoader(endpointMeta);
249
263
  const decode = resource.getDecoder('update');
250
264
  let data = await jsonReader(incoming);
251
265
  data = decode(data, { coerce: true });
@@ -253,11 +267,11 @@ export class EntityRequestHandler extends RequestHandlerBase {
253
267
  const omit = parseArrayParam(params.get('$omit'));
254
268
  const include = parseArrayParam(params.get('$include'));
255
269
  return new RequestHost({
256
- controller: operationMeta.controller,
270
+ controller: endpointMeta.controller,
257
271
  http: incoming,
258
272
  contentId,
259
273
  resource,
260
- operation: 'update',
274
+ endpoint: 'update',
261
275
  key: resource.parseKeyValue(p.key),
262
276
  data,
263
277
  params: {
@@ -267,18 +281,18 @@ export class EntityRequestHandler extends RequestHandlerBase {
267
281
  }
268
282
  });
269
283
  }
270
- const operationMeta = await this.assertOperation(resource, 'updateMany');
271
- const jsonReader = this.getBodyLoader(operationMeta);
284
+ const endpointMeta = await this.assertEndpoint(resource, 'updateMany');
285
+ const jsonReader = this.getBodyLoader(endpointMeta);
272
286
  const decode = resource.getDecoder('updateMany');
273
287
  let data = await jsonReader(incoming);
274
288
  data = decode(data, { coerce: true });
275
289
  const filter = resource.normalizeFilter(params.get('$filter'));
276
290
  return new RequestHost({
277
- controller: operationMeta.controller,
291
+ controller: endpointMeta.controller,
278
292
  http: incoming,
279
293
  contentId,
280
294
  resource,
281
- operation: 'updateMany',
295
+ endpoint: 'updateMany',
282
296
  data,
283
297
  params: {
284
298
  filter,
@@ -287,7 +301,7 @@ export class EntityRequestHandler extends RequestHandlerBase {
287
301
  }
288
302
  }
289
303
  throw new MethodNotAllowedError({
290
- message: `Collection resources do not accept http "${incoming.method}" method`
304
+ message: `Collection resource do not accept http "${incoming.method}" method`
291
305
  });
292
306
  }
293
307
  async parseSingletonRequest(resource, incoming) {
@@ -298,8 +312,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
298
312
  const params = incoming.parsedUrl.searchParams;
299
313
  switch (incoming.method) {
300
314
  case 'POST': {
301
- const operationMeta = await this.assertOperation(resource, 'create');
302
- const jsonReader = this.getBodyLoader(operationMeta);
315
+ const endpointMeta = await this.assertEndpoint(resource, 'create');
316
+ const jsonReader = this.getBodyLoader(endpointMeta);
303
317
  const decode = resource.getDecoder('create');
304
318
  let data = await jsonReader(incoming);
305
319
  data = decode(data, { coerce: true });
@@ -307,11 +321,11 @@ export class EntityRequestHandler extends RequestHandlerBase {
307
321
  const omit = parseArrayParam(params.get('$omit'));
308
322
  const include = parseArrayParam(params.get('$include'));
309
323
  return new RequestHost({
310
- controller: operationMeta.controller,
324
+ controller: endpointMeta.controller,
311
325
  http: incoming,
312
326
  contentId,
313
327
  resource,
314
- operation: 'create',
328
+ endpoint: 'create',
315
329
  data,
316
330
  params: {
317
331
  pick: pick && resource.normalizeFieldPath(pick),
@@ -321,26 +335,26 @@ export class EntityRequestHandler extends RequestHandlerBase {
321
335
  });
322
336
  }
323
337
  case 'DELETE': {
324
- const operationMeta = await this.assertOperation(resource, 'delete');
338
+ const endpointMeta = await this.assertEndpoint(resource, 'delete');
325
339
  return new RequestHost({
326
- controller: operationMeta.controller,
340
+ controller: endpointMeta.controller,
327
341
  http: incoming,
328
342
  contentId,
329
343
  resource,
330
- operation: 'delete',
344
+ endpoint: 'delete',
331
345
  });
332
346
  }
333
347
  case 'GET': {
334
- const operationMeta = await this.assertOperation(resource, 'get');
348
+ const endpointMeta = await this.assertEndpoint(resource, 'get');
335
349
  const pick = parseArrayParam(params.get('$pick'));
336
350
  const omit = parseArrayParam(params.get('$omit'));
337
351
  const include = parseArrayParam(params.get('$include'));
338
352
  return new RequestHost({
339
- controller: operationMeta.controller,
353
+ controller: endpointMeta.controller,
340
354
  http: incoming,
341
355
  contentId,
342
356
  resource,
343
- operation: 'get',
357
+ endpoint: 'get',
344
358
  params: {
345
359
  pick: pick && resource.normalizeFieldPath(pick),
346
360
  omit: omit && resource.normalizeFieldPath(omit),
@@ -349,8 +363,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
349
363
  });
350
364
  }
351
365
  case 'PATCH': {
352
- const operationMeta = await this.assertOperation(resource, 'update');
353
- const jsonReader = this.getBodyLoader(operationMeta);
366
+ const endpointMeta = await this.assertEndpoint(resource, 'update');
367
+ const jsonReader = this.getBodyLoader(endpointMeta);
354
368
  const decode = resource.getDecoder('update');
355
369
  let data = await jsonReader(incoming);
356
370
  data = decode(data, { coerce: true });
@@ -358,11 +372,11 @@ export class EntityRequestHandler extends RequestHandlerBase {
358
372
  const omit = parseArrayParam(params.get('$omit'));
359
373
  const include = parseArrayParam(params.get('$include'));
360
374
  return new RequestHost({
361
- controller: operationMeta.controller,
375
+ controller: endpointMeta.controller,
362
376
  http: incoming,
363
377
  contentId,
364
378
  resource,
365
- operation: 'update',
379
+ endpoint: 'update',
366
380
  data,
367
381
  params: {
368
382
  pick: pick && resource.normalizeFieldPath(pick),
@@ -373,14 +387,14 @@ export class EntityRequestHandler extends RequestHandlerBase {
373
387
  }
374
388
  }
375
389
  throw new MethodNotAllowedError({
376
- message: `Singleton resources do not accept http "${incoming.method}" method`
390
+ message: `Singleton resource do not accept http "${incoming.method}" method`
377
391
  });
378
392
  }
379
- getBodyLoader(operation) {
380
- let bodyLoader = this.bodyLoaders.get(operation);
393
+ getBodyLoader(endpoint) {
394
+ let bodyLoader = this.bodyLoaders.get(endpoint);
381
395
  if (!bodyLoader) {
382
396
  const parser = bodyParser.json({
383
- limit: operation.input?.maxContentSize,
397
+ limit: endpoint.input?.maxContentSize,
384
398
  type: 'json'
385
399
  });
386
400
  bodyLoader = (incoming) => {
@@ -393,7 +407,7 @@ export class EntityRequestHandler extends RequestHandlerBase {
393
407
  parser(incoming, {}, next);
394
408
  });
395
409
  };
396
- this.bodyLoaders.set(operation, bodyLoader);
410
+ this.bodyLoaders.set(endpoint, bodyLoader);
397
411
  }
398
412
  return bodyLoader;
399
413
  }
@@ -6,16 +6,16 @@ export class RequestHandlerBase {
6
6
  constructor(adapter) {
7
7
  this.adapter = adapter;
8
8
  }
9
- async assertOperation(resource, operation) {
9
+ async assertEndpoint(resource, endpoint) {
10
10
  const controller = await this.adapter.getController(resource);
11
- const operationMeta = (typeof controller?.[operation] === 'function') && resource.operations[operation];
12
- if (operationMeta)
11
+ const endpointMeta = (typeof controller?.[endpoint] === 'function') && resource.operations[endpoint];
12
+ if (endpointMeta)
13
13
  return {
14
- ...operationMeta,
14
+ ...endpointMeta,
15
15
  controller
16
16
  };
17
17
  throw new ForbiddenError({
18
- message: translate('RESOLVER_FORBIDDEN', { resource: resource.name, operation }, `'{{resource}}' endpoint does not accept '{{operation}}' operations`),
18
+ message: translate('RESOLVER_FORBIDDEN', { resource: resource.name, endpoint }, `'{{resource}}' endpoint does not accept '{{endpoint}}' operations`),
19
19
  severity: 'error',
20
20
  code: 'RESOLVER_FORBIDDEN'
21
21
  });
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs/promises';
2
2
  import os from 'os';
3
3
  import { BadRequestError, HttpStatusCodes, isReadable, OpraException, Storage, uid } from '@opra/common';
4
- import { OperationContext } from '../../operation-context.js';
4
+ import { EndpointContext } from '../../endpoint-context.js';
5
5
  import { RequestHost } from '../../request.host.js';
6
6
  import { ResponseHost } from '../../response.host.js';
7
7
  import { MultipartIterator } from '../helpers/multipart-helper.js';
@@ -22,9 +22,8 @@ export class StorageRequestHandler extends RequestHandlerBase {
22
22
  if (!request)
23
23
  return;
24
24
  const response = new ResponseHost({ http: outgoing });
25
- const context = OperationContext.from(executionContext, request, response);
26
- // Execute operation
27
- await this.executeOperation(context);
25
+ const context = EndpointContext.from(executionContext, request, response);
26
+ await this.callEndpoint(context);
28
27
  if (response.errors.length) {
29
28
  context.errors.push(...response.errors);
30
29
  return;
@@ -40,30 +39,30 @@ export class StorageRequestHandler extends RequestHandlerBase {
40
39
  return;
41
40
  switch (incoming.method) {
42
41
  case 'GET': {
43
- const operationMeta = await this.assertOperation(resource, 'get');
42
+ const endpointMeta = await this.assertEndpoint(resource, 'get');
44
43
  return new RequestHost({
45
- controller: operationMeta.controller,
44
+ controller: endpointMeta.controller,
46
45
  http: incoming,
47
46
  resource,
48
- operation: 'get',
47
+ endpoint: 'get',
49
48
  contentId
50
49
  });
51
50
  }
52
51
  case 'DELETE': {
53
- const operationMeta = await this.assertOperation(resource, 'delete');
52
+ const endpointMeta = await this.assertEndpoint(resource, 'delete');
54
53
  return new RequestHost({
55
- controller: operationMeta.controller,
54
+ controller: endpointMeta.controller,
56
55
  http: incoming,
57
56
  resource,
58
- operation: 'delete',
57
+ endpoint: 'delete',
59
58
  contentId
60
59
  });
61
60
  }
62
61
  case 'POST': {
63
- const operationMeta = await this.assertOperation(resource, 'post');
62
+ const endpointMeta = await this.assertEndpoint(resource, 'post');
64
63
  await fs.mkdir(this._uploadDir, { recursive: true });
65
64
  const multipartIterator = new MultipartIterator(incoming, {
66
- ...operationMeta,
65
+ ...endpointMeta,
67
66
  filename: () => this.adapter.serviceName + '_p' + process.pid +
68
67
  't' + String(Date.now()).substring(8) + 'r' + uid(12)
69
68
  });
@@ -74,10 +73,10 @@ export class StorageRequestHandler extends RequestHandlerBase {
74
73
  await multipartIterator.deleteFiles().catch(() => void 0);
75
74
  });
76
75
  return new RequestHost({
77
- controller: operationMeta.controller,
76
+ controller: endpointMeta.controller,
78
77
  http: incoming,
79
78
  resource,
80
- operation: 'post',
79
+ endpoint: 'post',
81
80
  contentId,
82
81
  parts: multipartIterator
83
82
  });
@@ -90,13 +89,13 @@ export class StorageRequestHandler extends RequestHandlerBase {
90
89
  throw new BadRequestError(e);
91
90
  }
92
91
  }
93
- async executeOperation(context) {
92
+ async callEndpoint(context) {
94
93
  const request = context.request;
95
94
  const { response } = context;
96
- // Call operation handler method
95
+ // Call endpoint handler method
97
96
  let value;
98
97
  try {
99
- value = await request.controller[request.operation].call(request.controller, context);
98
+ value = await request.controller[request.endpoint].call(request.controller, context);
100
99
  if (response.value == null)
101
100
  response.value = value;
102
101
  }
@@ -63,7 +63,7 @@ export class PlatformAdapterHost extends AsyncEventEmitter {
63
63
  this._i18n = this._i18n || I18n.defaultInstance;
64
64
  if (!this._i18n.isInitialized)
65
65
  await this._i18n.init();
66
- // Initialize all controllers
66
+ // Initialize all resources
67
67
  for (const resource of this.api.resources.values()) {
68
68
  await this.getController(resource);
69
69
  }
@@ -1,4 +1,4 @@
1
- import { Collection, METADATA_KEY, Resource, Singleton } from "@opra/common";
1
+ import { Collection, Resource, Singleton, SOURCE_METADATA } from "@opra/common";
2
2
  // @ts-ignore
3
3
  const oldConstruct = Resource.prototype._construct;
4
4
  // @ts-ignore
@@ -10,15 +10,15 @@ Resource.prototype._construct = function (init) {
10
10
  };
11
11
  Collection.OnInit = Singleton.OnInit = function () {
12
12
  return (target, propertyKey) => {
13
- const resourceMetadata = (Reflect.getOwnMetadata(METADATA_KEY, target.constructor) || {});
14
- resourceMetadata.onInit = target[propertyKey];
15
- Reflect.defineMetadata(METADATA_KEY, target.constructor, resourceMetadata);
13
+ const sourceMetadata = (Reflect.getOwnMetadata(SOURCE_METADATA, target.constructor) || {});
14
+ sourceMetadata.onInit = target[propertyKey];
15
+ Reflect.defineMetadata(SOURCE_METADATA, target.constructor, sourceMetadata);
16
16
  };
17
17
  };
18
18
  Collection.OnShutdown = Singleton.OnShutdown = function () {
19
19
  return (target, propertyKey) => {
20
- const resourceMetadata = (Reflect.getOwnMetadata(METADATA_KEY, target.constructor) || {});
21
- resourceMetadata.onShutdown = target[propertyKey];
22
- Reflect.defineMetadata(METADATA_KEY, target.constructor, resourceMetadata);
20
+ const sourceMetadata = (Reflect.getOwnMetadata(SOURCE_METADATA, target.constructor) || {});
21
+ sourceMetadata.onShutdown = target[propertyKey];
22
+ Reflect.defineMetadata(SOURCE_METADATA, target.constructor, sourceMetadata);
23
23
  };
24
24
  };
package/esm/index.js CHANGED
@@ -5,7 +5,7 @@ import './augmentation/singleton.augmentation.js';
5
5
  import './augmentation/storage.augmentation.js';
6
6
  export * from './types.js';
7
7
  export * from './adapter/execution-context.js';
8
- export * from './adapter/operation-context.js';
8
+ export * from './adapter/endpoint-context.js';
9
9
  export * from './adapter/platform-adapter.js';
10
10
  export * from './adapter/request.js';
11
11
  export * from './adapter/response.js';
@@ -8,11 +8,12 @@
8
8
  "NOT_FOUND": "Not found",
9
9
  "UNAUTHORIZED": "You have not been authenticated to perform this action",
10
10
  "UNPROCESSABLE_ENTITY": "Unprocessable entity",
11
+ "SOURCE_NOT_FOUND": "Source not found",
11
12
  "REQUEST_VALIDATION": "Request validation failed",
12
13
  "RESPONSE_VALIDATION": "Response validation failed",
13
- "RESOURCE_NOT_FOUND": "Resource not found: '{{resource}}'",
14
+ "RESOURCE_NOT_FOUND": "Resource not found",
14
15
  "RESOURCE_CONFLICT": "There is already an other {{resource}} resource with same field values ({{fields}})",
15
- "RESOLVER_FORBIDDEN": "The {{resource}} endpoint does not accept '{{operation}}' operations",
16
+ "RESOLVER_FORBIDDEN": "The {{resource}} endpoint does not accept '{{endpoint}}' operations",
16
17
  "UNKNOWN_FIELD": "Unknown field '{{field}}'",
17
18
  "UNACCEPTED_SORT_FIELD": "Field '{{field}}' is not available for sort operation",
18
19
  "UNACCEPTED_FILTER_FIELD": "Field '{{field}}' is not available for filter operation",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/core",
3
- "version": "0.23.1",
3
+ "version": "0.24.0",
4
4
  "description": "Opra schema package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -27,7 +27,7 @@
27
27
  "clean:cover": "rimraf ../../coverage/core"
28
28
  },
29
29
  "dependencies": {
30
- "@opra/common": "^0.23.1",
30
+ "@opra/common": "^0.24.0",
31
31
  "accepts": "^1.3.8",
32
32
  "content-disposition": "^0.5.4",
33
33
  "content-type": "^1.0.5",
@@ -1,11 +1,11 @@
1
1
  import type { ExecutionContext } from './execution-context';
2
2
  import type { Request } from './request';
3
3
  import type { Response } from './response';
4
- export interface OperationContext<TRequest extends Request = Request, TResponse extends Response = Response> extends ExecutionContext {
4
+ export interface EndpointContext<TRequest extends Request = Request, TResponse extends Response = Response> extends ExecutionContext {
5
5
  request: TRequest;
6
6
  response: TResponse;
7
7
  requestScope: Record<string | number | symbol, any>;
8
8
  }
9
- export declare namespace OperationContext {
10
- function from<TRequest extends Request = Request, TResponse extends Response = Response>(executionContext: ExecutionContext, request: TRequest, response: TResponse): OperationContext;
9
+ export declare namespace EndpointContext {
10
+ function from<TRequest extends Request = Request, TResponse extends Response = Response>(executionContext: ExecutionContext, request: TRequest, response: TResponse): EndpointContext;
11
11
  }
@@ -1,6 +1,6 @@
1
1
  import { Collection, OpraSchema, Singleton } from '@opra/common';
2
+ import { EndpointContext } from '../../endpoint-context.js';
2
3
  import { ExecutionContext } from '../../execution-context.js';
3
- import { OperationContext } from '../../operation-context.js';
4
4
  import { Request } from '../../request.js';
5
5
  import type { HttpAdapterBase } from '../http-adapter-base.js';
6
6
  import { HttpServerRequest } from '../http-server-request.js';
@@ -15,10 +15,10 @@ export declare class EntityRequestHandler extends RequestHandlerBase {
15
15
  constructor(adapter: HttpAdapterBase);
16
16
  processRequest(executionContext: ExecutionContext): Promise<void>;
17
17
  parseRequest(incoming: HttpServerRequest): Promise<Request | undefined>;
18
- executeOperation(context: OperationContext): Promise<void>;
19
- sendResponse(context: OperationContext): Promise<void>;
18
+ callEndpoint(context: EndpointContext): Promise<void>;
19
+ sendResponse(context: EndpointContext): Promise<void>;
20
20
  parseCollectionRequest(resource: Collection, incoming: HttpServerRequest): Promise<Request>;
21
21
  parseSingletonRequest(resource: Singleton, incoming: HttpServerRequest): Promise<Request>;
22
- getBodyLoader(operation: OpraSchema.Collection.CreateOperation | OpraSchema.Collection.UpdateOperation | OpraSchema.Collection.UpdateManyOperation): BodyLoaderFunction;
22
+ getBodyLoader(endpoint: OpraSchema.Collection.CreateEndpoint | OpraSchema.Collection.UpdateEndpoint | OpraSchema.Collection.UpdateManyEndpoint): BodyLoaderFunction;
23
23
  }
24
24
  export {};
@@ -9,7 +9,7 @@ export declare abstract class RequestHandlerBase implements RequestHandler {
9
9
  readonly adapter: HttpAdapterBase;
10
10
  protected constructor(adapter: HttpAdapterBase);
11
11
  abstract processRequest(executionContext: ExecutionContext): Promise<void>;
12
- assertOperation<T extends OpraSchema.Operation = OpraSchema.Operation>(resource: Resource, operation: string): Promise<T & {
12
+ assertEndpoint<T extends OpraSchema.Endpoint = OpraSchema.Endpoint>(resource: Resource, endpoint: string): Promise<T & {
13
13
  controller: any;
14
14
  }>;
15
15
  }