@opra/core 0.0.13 → 0.1.1

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 (106) hide show
  1. package/cjs/enums/http-headers.enum.js +2 -1
  2. package/cjs/implementation/adapter-utils/entity-resource-execute.util.js +84 -0
  3. package/cjs/implementation/adapter-utils/resource-execute.util.js +11 -0
  4. package/cjs/implementation/adapter-utils/resource-prepare.util.js +11 -0
  5. package/cjs/implementation/{adapter/adapter.js → adapter.js} +21 -18
  6. package/cjs/implementation/{adapter/express-adapter.js → express-adapter.js} +0 -0
  7. package/cjs/implementation/{adapter/http-adapter.js → http-adapter.js} +26 -24
  8. package/cjs/implementation/query-context.js +5 -3
  9. package/cjs/index.js +5 -15
  10. package/cjs/{services/entity-resource-controller.js → interfaces/entity-service.interface.js} +0 -0
  11. package/cjs/interfaces/query.interface.js +10 -10
  12. package/cjs/services/json-data-service.js +11 -5
  13. package/cjs/utils/{string-path-to-object-tree.js → path-to-tree.js} +3 -3
  14. package/esm/enums/http-headers.enum.d.ts +2 -1
  15. package/esm/enums/http-headers.enum.js +2 -1
  16. package/esm/implementation/adapter-utils/entity-resource-execute.util.d.ts +3 -0
  17. package/esm/implementation/adapter-utils/entity-resource-execute.util.js +80 -0
  18. package/esm/implementation/adapter-utils/resource-execute.util.d.ts +3 -0
  19. package/esm/implementation/adapter-utils/resource-execute.util.js +7 -0
  20. package/esm/implementation/adapter-utils/resource-prepare.util.d.ts +3 -0
  21. package/esm/implementation/adapter-utils/resource-prepare.util.js +7 -0
  22. package/esm/implementation/{adapter/adapter.d.ts → adapter.d.ts} +5 -5
  23. package/esm/implementation/{adapter/adapter.js → adapter.js} +18 -15
  24. package/esm/implementation/{adapter/express-adapter.d.ts → express-adapter.d.ts} +2 -2
  25. package/esm/implementation/{adapter/express-adapter.js → express-adapter.js} +0 -0
  26. package/esm/implementation/{adapter/http-adapter.d.ts → http-adapter.d.ts} +6 -7
  27. package/esm/implementation/{adapter/http-adapter.js → http-adapter.js} +25 -23
  28. package/esm/implementation/query-context.d.ts +3 -4
  29. package/esm/implementation/query-context.js +5 -3
  30. package/esm/index.d.ts +5 -15
  31. package/esm/index.js +5 -15
  32. package/esm/{services/entity-resource-controller.d.ts → interfaces/entity-service.interface.d.ts} +0 -0
  33. package/esm/{services/entity-resource-controller.js → interfaces/entity-service.interface.js} +0 -0
  34. package/esm/interfaces/query.interface.d.ts +25 -26
  35. package/esm/interfaces/query.interface.js +10 -10
  36. package/esm/services/json-data-service.d.ts +2 -2
  37. package/esm/services/json-data-service.js +11 -5
  38. package/esm/types.d.ts +1 -8
  39. package/esm/utils/create-i18n.d.ts +1 -1
  40. package/esm/utils/path-to-tree.d.ts +4 -0
  41. package/esm/utils/{string-path-to-object-tree.js → path-to-tree.js} +1 -1
  42. package/package.json +6 -6
  43. package/cjs/constants.js +0 -6
  44. package/cjs/decorators/api-entity-resource.decorator.js +0 -24
  45. package/cjs/decorators/api-resolver.decorator.js +0 -13
  46. package/cjs/implementation/data-type/complex-type.js +0 -53
  47. package/cjs/implementation/data-type/data-type.js +0 -47
  48. package/cjs/implementation/data-type/entity-type.js +0 -34
  49. package/cjs/implementation/data-type/simple-type.js +0 -30
  50. package/cjs/implementation/opra-document.js +0 -112
  51. package/cjs/implementation/opra-service.js +0 -81
  52. package/cjs/implementation/resource/container-resource-handler.js +0 -30
  53. package/cjs/implementation/resource/entity-resource-handler.js +0 -103
  54. package/cjs/implementation/resource/resource-handler.js +0 -45
  55. package/cjs/implementation/schema-generator.js +0 -184
  56. package/cjs/interfaces/metadata/api-resolver.metadata.js +0 -2
  57. package/cjs/interfaces/metadata/opra-schema.metadata.js +0 -11
  58. package/cjs/interfaces/resource-container.interface.js +0 -2
  59. package/cjs/utils/class-utils.js +0 -37
  60. package/cjs/utils/headers.js +0 -58
  61. package/cjs/utils/internal-data-types.js +0 -81
  62. package/cjs/utils/responsive-object.js +0 -49
  63. package/cjs/utils/terminal-utils.js +0 -7
  64. package/esm/constants.d.ts +0 -3
  65. package/esm/constants.js +0 -3
  66. package/esm/decorators/api-entity-resource.decorator.d.ts +0 -5
  67. package/esm/decorators/api-entity-resource.decorator.js +0 -19
  68. package/esm/decorators/api-resolver.decorator.d.ts +0 -2
  69. package/esm/decorators/api-resolver.decorator.js +0 -9
  70. package/esm/implementation/data-type/complex-type.d.ts +0 -19
  71. package/esm/implementation/data-type/complex-type.js +0 -48
  72. package/esm/implementation/data-type/data-type.d.ts +0 -17
  73. package/esm/implementation/data-type/data-type.js +0 -43
  74. package/esm/implementation/data-type/entity-type.d.ts +0 -10
  75. package/esm/implementation/data-type/entity-type.js +0 -29
  76. package/esm/implementation/data-type/simple-type.d.ts +0 -15
  77. package/esm/implementation/data-type/simple-type.js +0 -26
  78. package/esm/implementation/opra-document.d.ts +0 -26
  79. package/esm/implementation/opra-document.js +0 -107
  80. package/esm/implementation/opra-service.d.ts +0 -20
  81. package/esm/implementation/opra-service.js +0 -76
  82. package/esm/implementation/resource/container-resource-handler.d.ts +0 -14
  83. package/esm/implementation/resource/container-resource-handler.js +0 -26
  84. package/esm/implementation/resource/entity-resource-handler.d.ts +0 -18
  85. package/esm/implementation/resource/entity-resource-handler.js +0 -98
  86. package/esm/implementation/resource/resource-handler.d.ts +0 -15
  87. package/esm/implementation/resource/resource-handler.js +0 -40
  88. package/esm/implementation/schema-generator.d.ts +0 -21
  89. package/esm/implementation/schema-generator.js +0 -180
  90. package/esm/interfaces/metadata/api-resolver.metadata.d.ts +0 -3
  91. package/esm/interfaces/metadata/api-resolver.metadata.js +0 -1
  92. package/esm/interfaces/metadata/opra-schema.metadata.d.ts +0 -7
  93. package/esm/interfaces/metadata/opra-schema.metadata.js +0 -10
  94. package/esm/interfaces/resource-container.interface.d.ts +0 -6
  95. package/esm/interfaces/resource-container.interface.js +0 -1
  96. package/esm/utils/class-utils.d.ts +0 -6
  97. package/esm/utils/class-utils.js +0 -30
  98. package/esm/utils/headers.d.ts +0 -9
  99. package/esm/utils/headers.js +0 -55
  100. package/esm/utils/internal-data-types.d.ts +0 -5
  101. package/esm/utils/internal-data-types.js +0 -78
  102. package/esm/utils/responsive-object.d.ts +0 -3
  103. package/esm/utils/responsive-object.js +0 -45
  104. package/esm/utils/string-path-to-object-tree.d.ts +0 -4
  105. package/esm/utils/terminal-utils.d.ts +0 -4
  106. package/esm/utils/terminal-utils.js +0 -4
@@ -0,0 +1,80 @@
1
+ import { translate } from '@opra/i18n';
2
+ import { ComplexType } from '@opra/schema';
3
+ import { HttpHeaders } from '../../enums/index.js';
4
+ import { ForbiddenError, ResourceNotFoundError } from '../../exception/index.js';
5
+ import { OpraQuery } from '../../interfaces/query.interface.js';
6
+ export async function entityResourceExecute(service, resource, context) {
7
+ const { query } = context;
8
+ if (OpraQuery.isSearchQuery(query)) {
9
+ const promises = [];
10
+ let search;
11
+ let count;
12
+ promises.push(executeFn(service, resource, context, query.queryType)
13
+ .then(v => search = v));
14
+ if (query.count) {
15
+ promises.push(executeFn(service, resource, context, 'count')
16
+ .then(v => count = v));
17
+ }
18
+ await Promise.all(promises);
19
+ context.response.value = {
20
+ ...search,
21
+ ...count
22
+ };
23
+ return;
24
+ }
25
+ context.response.value = await executeFn(service, resource, context, query.queryType);
26
+ }
27
+ async function executeFn(service, resource, context, queryType) {
28
+ const resolverInfo = resource.metadata.methods?.[queryType];
29
+ if (!resolverInfo.handler)
30
+ throw new ForbiddenError({
31
+ message: translate('RESOLVER_FORBIDDEN', { queryType }),
32
+ severity: 'error',
33
+ code: 'RESOLVER_FORBIDDEN'
34
+ });
35
+ let result = await resolverInfo.handler(context);
36
+ switch (queryType) {
37
+ case 'search':
38
+ context.response.headers.set(HttpHeaders.X_Opra_Schema, '/$schema/types/' + resource.dataType.name);
39
+ return {
40
+ items: Array.isArray(result) ? result : (context.response.value ? [result] : [])
41
+ };
42
+ case 'get':
43
+ case 'update':
44
+ if (!result) {
45
+ const query = context.query;
46
+ throw new ResourceNotFoundError(resource.name, query.keyValue);
47
+ }
48
+ break;
49
+ case 'count':
50
+ return { count: result || 0 };
51
+ case 'delete':
52
+ case 'deleteMany':
53
+ case 'updateMany':
54
+ let affectedRecords;
55
+ if (typeof result === 'number')
56
+ affectedRecords = result;
57
+ if (typeof result === 'boolean')
58
+ affectedRecords = result ? 1 : 0;
59
+ if (typeof result === 'object')
60
+ affectedRecords = result.affectedRows || result.affectedRecords;
61
+ return { affectedRecords };
62
+ }
63
+ if (!result)
64
+ return;
65
+ result = Array.isArray(result) ? result[0] : result;
66
+ let dataType = resource.dataType;
67
+ if (context.resultPath) {
68
+ const pathArray = context.resultPath.split('.');
69
+ for (const field of pathArray) {
70
+ const prop = dataType instanceof ComplexType ? dataType.fields.get(field) : undefined;
71
+ dataType = prop && prop.type ? service.types.get(prop.type) : undefined;
72
+ result = result && typeof result === 'object' && result[field];
73
+ }
74
+ }
75
+ if (queryType === 'create')
76
+ context.response.status = 201;
77
+ if (dataType)
78
+ context.response.headers.set(HttpHeaders.X_Opra_Schema, '/$schema/types/' + dataType.name);
79
+ return result;
80
+ }
@@ -0,0 +1,3 @@
1
+ import { BaseResource, OpraService } from '@opra/schema';
2
+ import { QueryContext } from '../query-context.js';
3
+ export declare function resourceExecute(service: OpraService, resource: BaseResource, context: QueryContext): Promise<void>;
@@ -0,0 +1,7 @@
1
+ import { EntityResource } from '@opra/schema';
2
+ import { entityResourceExecute } from './entity-resource-execute.util.js';
3
+ export async function resourceExecute(service, resource, context) {
4
+ if (resource instanceof EntityResource)
5
+ return await entityResourceExecute(service, resource, context);
6
+ throw new Error(`Executing "${resource.kind}" has not been implemented yet`);
7
+ }
@@ -0,0 +1,3 @@
1
+ import { BaseResource } from '@opra/schema';
2
+ import { QueryContext } from '../query-context.js';
3
+ export declare function resourcePrepare(resource: BaseResource, context: QueryContext): Promise<void>;
@@ -0,0 +1,7 @@
1
+ export async function resourcePrepare(resource, context) {
2
+ const { query } = context;
3
+ const fn = resource.metadata['pre_' + query.queryType];
4
+ if (fn && typeof fn === 'function') {
5
+ await fn(context);
6
+ }
7
+ }
@@ -1,8 +1,8 @@
1
1
  import { FallbackLng, I18n, LanguageResource } from '@opra/i18n';
2
- import { ApiException } from '../../exception/index.js';
3
- import { IExecutionContext } from '../../interfaces/execution-context.interface.js';
4
- import { OpraService } from '../opra-service.js';
5
- import { QueryContext } from '../query-context.js';
2
+ import { OpraService } from '@opra/schema';
3
+ import { ApiException } from '../exception/index.js';
4
+ import { IExecutionContext } from '../interfaces/execution-context.interface.js';
5
+ import { QueryContext } from './query-context.js';
6
6
  export declare namespace OpraAdapter {
7
7
  type UserContextResolver = (args: {
8
8
  executionContext: IExecutionContext;
@@ -52,6 +52,6 @@ export declare abstract class OpraAdapter<TExecutionContext extends IExecutionCo
52
52
  protected abstract sendError(executionContext: TExecutionContext, error: ApiException): Promise<void>;
53
53
  protected abstract isBatch(executionContext: TExecutionContext): boolean;
54
54
  protected handler(executionContext: TExecutionContext): Promise<void>;
55
- protected _metadataExecute(ctx: QueryContext): Promise<void>;
55
+ protected _getSchemaExecute(ctx: QueryContext): Promise<void>;
56
56
  protected static initI18n(options?: OpraAdapter.Options): Promise<I18n>;
57
57
  }
@@ -1,8 +1,11 @@
1
1
  import { AsyncEventEmitter } from 'strict-typed-events';
2
2
  import { I18n } from '@opra/i18n';
3
- import { BadRequestError, FailedDependencyError } from '../../exception/index.js';
4
- import { wrapError } from '../../exception/wrap-error.js';
5
- import { createI18n } from '../../utils/create-i18n.js';
3
+ import { HttpHeaders } from '../enums/index.js';
4
+ import { BadRequestError, FailedDependencyError } from '../exception/index.js';
5
+ import { wrapError } from '../exception/wrap-error.js';
6
+ import { createI18n } from '../utils/create-i18n.js';
7
+ import { resourceExecute } from './adapter-utils/resource-execute.util.js';
8
+ import { resourcePrepare } from './adapter-utils/resource-prepare.util.js';
6
9
  export class OpraAdapter {
7
10
  service;
8
11
  i18n;
@@ -39,19 +42,19 @@ export class OpraAdapter {
39
42
  }
40
43
  try {
41
44
  const promise = (async () => {
42
- if (context.query.queryType === 'metadata') {
43
- await this._metadataExecute(context);
45
+ if (context.query.queryType === 'schema') {
46
+ await this._getSchemaExecute(context);
44
47
  return;
45
48
  }
46
49
  const resource = context.query.resource;
47
- await resource.prepare(context);
50
+ await resourcePrepare(resource, context);
48
51
  if (this.userContextResolver && !userContext)
49
52
  userContext = this.userContextResolver({
50
53
  executionContext,
51
54
  isBatch: this.isBatch(executionContext)
52
55
  });
53
56
  context.userContext = userContext;
54
- await resource.execute(context);
57
+ await resourceExecute(this.service, resource, context);
55
58
  })().catch(e => {
56
59
  context.response.errors.push(e);
57
60
  });
@@ -92,7 +95,7 @@ export class OpraAdapter {
92
95
  }
93
96
  }
94
97
  }
95
- async _metadataExecute(ctx) {
98
+ async _getSchemaExecute(ctx) {
96
99
  const query = ctx.query;
97
100
  let out;
98
101
  if (query.resourcePath.length > 2)
@@ -100,23 +103,23 @@ export class OpraAdapter {
100
103
  if (query.resourcePath?.length) {
101
104
  if (query.resourcePath[0] === 'resources') {
102
105
  const resource = this.service.getResource(query.resourcePath[1]);
103
- out = resource.getMetadata();
106
+ out = resource.getSchema(true);
104
107
  query.resourcePath[1] = resource.name;
108
+ ctx.response.headers.set(HttpHeaders.X_Opra_Schema, 'http://www.oprajs.com/reference/v1/schema#' + resource.kind);
105
109
  }
106
110
  else if (query.resourcePath[0] === 'types') {
107
111
  const dataType = this.service.getDataType(query.resourcePath[1]);
108
- out = dataType.getMetadata();
112
+ out = dataType.getSchema(true);
109
113
  query.resourcePath[1] = dataType.name;
114
+ ctx.response.headers.set(HttpHeaders.X_Opra_Schema, 'http://www.oprajs.com/reference/v1/schema#' + dataType.kind);
110
115
  }
111
116
  else
112
117
  throw new BadRequestError();
113
- ctx.response.value = {
114
- '@opra:metadata': '/$metadata/' + query.resourcePath.join('/'),
115
- ...out
116
- };
118
+ ctx.response.value = out;
117
119
  return;
118
120
  }
119
- ctx.response.value = this.service.getMetadata();
121
+ ctx.response.headers.set(HttpHeaders.X_Opra_Schema, 'http://www.oprajs.com/reference/v1/schema');
122
+ ctx.response.value = this.service.getSchema(true);
120
123
  }
121
124
  static async initI18n(options) {
122
125
  if (options?.i18n instanceof I18n)
@@ -1,6 +1,6 @@
1
1
  import type { Application } from 'express';
2
- import type { IHttpExecutionContext } from '../../interfaces/execution-context.interface';
3
- import type { OpraService } from '../opra-service.js';
2
+ import { OpraService } from '@opra/schema';
3
+ import type { IHttpExecutionContext } from '../interfaces/execution-context.interface';
4
4
  import { OpraHttpAdapter } from './http-adapter.js';
5
5
  export declare namespace OpraExpressAdapter {
6
6
  interface Options extends OpraHttpAdapter.Options {
@@ -1,10 +1,9 @@
1
1
  import { OpraURL } from '@opra/url';
2
- import { ApiException } from '../../exception/index.js';
3
- import { IHttpExecutionContext } from '../../interfaces/execution-context.interface.js';
4
- import { OpraMetadataQuery, OpraQuery } from '../../interfaces/query.interface.js';
5
- import { HeadersObject } from '../../utils/headers.js';
6
- import { QueryContext } from '../query-context.js';
2
+ import { ApiException } from '../exception/index.js';
3
+ import { IHttpExecutionContext } from '../interfaces/execution-context.interface.js';
4
+ import { OpraGetSchemaQuery, OpraQuery } from '../interfaces/query.interface.js';
7
5
  import { OpraAdapter } from './adapter.js';
6
+ import { QueryContext } from './query-context.js';
8
7
  export declare namespace OpraHttpAdapter {
9
8
  type Options = OpraAdapter.Options & {
10
9
  prefix?: string;
@@ -17,8 +16,8 @@ interface PreparedOutput {
17
16
  }
18
17
  export declare class OpraHttpAdapter<TExecutionContext extends IHttpExecutionContext> extends OpraAdapter<IHttpExecutionContext> {
19
18
  protected prepareRequests(executionContext: TExecutionContext): QueryContext[];
20
- prepareRequest(executionContext: IHttpExecutionContext, url: OpraURL, method: string, headers: HeadersObject, body?: any): QueryContext;
21
- buildMetadataQuery(url: OpraURL): OpraMetadataQuery;
19
+ prepareRequest(executionContext: IHttpExecutionContext, url: OpraURL, method: string, headers: Map<string, string>, body?: any): QueryContext;
20
+ buildGetSchemaQuery(url: OpraURL): OpraGetSchemaQuery;
22
21
  buildQuery(url: OpraURL, method: string, body?: any): OpraQuery | undefined;
23
22
  protected sendResponse(executionContext: TExecutionContext, queryContexts: QueryContext[]): Promise<void>;
24
23
  protected isBatch(executionContext: TExecutionContext): boolean;
@@ -1,15 +1,11 @@
1
+ import { ComplexType, ContainerResource, EntityResource, OpraSchema, ResponsiveMap } from '@opra/schema';
1
2
  import { OpraURL } from '@opra/url';
2
- import { OpraVersion } from '../../constants.js';
3
- import { HttpHeaders, HttpStatus } from '../../enums/index.js';
4
- import { BadRequestError, InternalServerError, MethodNotAllowedError, NotFoundError, } from '../../exception/index.js';
5
- import { wrapError } from '../../exception/wrap-error.js';
6
- import { OpraQuery } from '../../interfaces/query.interface.js';
7
- import { Headers } from '../../utils/headers.js';
8
- import { ComplexType } from '../data-type/complex-type.js';
9
- import { QueryContext } from '../query-context.js';
10
- import { ContainerResourceHandler } from '../resource/container-resource-handler.js';
11
- import { EntityResourceHandler } from '../resource/entity-resource-handler.js';
3
+ import { HttpHeaders, HttpStatus } from '../enums/index.js';
4
+ import { BadRequestError, InternalServerError, MethodNotAllowedError, NotFoundError, } from '../exception/index.js';
5
+ import { wrapError } from '../exception/wrap-error.js';
6
+ import { OpraQuery } from '../interfaces/query.interface.js';
12
7
  import { OpraAdapter } from './adapter.js';
8
+ import { QueryContext } from './query-context.js';
13
9
  export class OpraHttpAdapter extends OpraAdapter {
14
10
  prepareRequests(executionContext) {
15
11
  const req = executionContext.getRequestWrapper();
@@ -19,7 +15,7 @@ export class OpraHttpAdapter extends OpraAdapter {
19
15
  }
20
16
  const url = new OpraURL(req.getUrl());
21
17
  return [
22
- this.prepareRequest(executionContext, url, req.getMethod(), Headers.from(req.getHeaders()), req.getBody())
18
+ this.prepareRequest(executionContext, url, req.getMethod(), new ResponsiveMap(req.getHeaders()), req.getBody())
23
19
  ];
24
20
  }
25
21
  prepareRequest(executionContext, url, method, headers, body) {
@@ -41,7 +37,7 @@ export class OpraHttpAdapter extends OpraAdapter {
41
37
  continueOnError: query.operation === 'read'
42
38
  });
43
39
  }
44
- buildMetadataQuery(url) {
40
+ buildGetSchemaQuery(url) {
45
41
  const pathLen = url.path.size;
46
42
  const resourcePath = [];
47
43
  let pathIndex = 0;
@@ -49,7 +45,7 @@ export class OpraHttpAdapter extends OpraAdapter {
49
45
  const p = url.path.get(pathIndex++);
50
46
  if (p.key)
51
47
  throw new BadRequestError();
52
- if (p.resource !== '$metadata') {
48
+ if (p.resource !== '$schema') {
53
49
  if (pathIndex === 1)
54
50
  resourcePath.push('resources');
55
51
  resourcePath.push(p.resource);
@@ -60,7 +56,7 @@ export class OpraHttpAdapter extends OpraAdapter {
60
56
  omit: url.searchParams.get('$omit'),
61
57
  include: url.searchParams.get('$include'),
62
58
  };
63
- return OpraQuery.forGetMetadata(resourcePath, opts);
59
+ return OpraQuery.forGetSchema(resourcePath, opts);
64
60
  }
65
61
  buildQuery(url, method, body) {
66
62
  let container = this.service;
@@ -69,10 +65,10 @@ export class OpraHttpAdapter extends OpraAdapter {
69
65
  // Check if requesting metadata
70
66
  for (let i = 0; i < pathLen; i++) {
71
67
  const p = url.path.get(i);
72
- if (p.resource === '$metadata') {
68
+ if (p.resource === '$schema') {
73
69
  if (method !== 'GET')
74
70
  return;
75
- return this.buildMetadataQuery(url);
71
+ return this.buildGetSchemaQuery(url);
76
72
  }
77
73
  }
78
74
  let pathIndex = 0;
@@ -80,12 +76,12 @@ export class OpraHttpAdapter extends OpraAdapter {
80
76
  let p = url.path.get(pathIndex++);
81
77
  const resource = container.getResource(p.resource);
82
78
  // Move through path directories (containers)
83
- if (resource instanceof ContainerResourceHandler) {
79
+ if (resource instanceof ContainerResource) {
84
80
  container = resource;
85
81
  continue;
86
82
  }
87
83
  method = method.toUpperCase();
88
- if (resource instanceof EntityResourceHandler) {
84
+ if (resource instanceof EntityResource) {
89
85
  const scope = p.key ? 'instance' : 'collection';
90
86
  if (pathIndex < pathLen && !(method === 'GET' && scope === 'instance'))
91
87
  return;
@@ -119,10 +115,10 @@ export class OpraHttpAdapter extends OpraAdapter {
119
115
  ? this.service.getDataType(nested.property.type || 'string')
120
116
  : query.resource.dataType;
121
117
  if (!(dataType instanceof ComplexType))
122
- throw new Error(`"${path}" is not a ComplexType and has no properties.`);
118
+ throw new Error(`"${path}" is not a ComplexType and has no fields.`);
123
119
  p = url.path.get(pathIndex++);
124
120
  path += '.' + p.resource;
125
- const prop = dataType.properties?.[p.resource];
121
+ const prop = dataType.fields.get(p.resource);
126
122
  if (!prop)
127
123
  throw new NotFoundError({ message: `Invalid or unknown resource path (${path})` });
128
124
  const q = OpraQuery.forGetProperty(prop);
@@ -209,7 +205,7 @@ export class OpraHttpAdapter extends OpraAdapter {
209
205
  resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
210
206
  resp.setHeader(HttpHeaders.Pragma, 'no-cache');
211
207
  resp.setHeader(HttpHeaders.Expires, '-1');
212
- resp.setHeader(HttpHeaders.X_Opra_Version, OpraVersion);
208
+ resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
213
209
  if (out.headers) {
214
210
  for (const [k, v] of Object.entries(out.headers)) {
215
211
  resp.setHeader(k, v);
@@ -241,10 +237,16 @@ export class OpraHttpAdapter extends OpraAdapter {
241
237
  delete body.errors;
242
238
  status = status || (query.operation === 'create' ? HttpStatus.CREATED : HttpStatus.OK);
243
239
  }
240
+ // Convert headers map to object
241
+ const headers = Array.from(ctx.response.headers.keys()).map(k => k.toLowerCase()).sort()
242
+ .reduce((a, k) => {
243
+ a[k] = ctx.response.headers.get(k);
244
+ return a;
245
+ }, {});
244
246
  body = this.i18n.deep(body);
245
247
  return {
246
248
  status,
247
- headers: ctx.response.headers,
249
+ headers,
248
250
  body
249
251
  };
250
252
  }
@@ -255,7 +257,7 @@ export class OpraHttpAdapter extends OpraAdapter {
255
257
  resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
256
258
  resp.setHeader(HttpHeaders.Pragma, 'no-cache');
257
259
  resp.setHeader(HttpHeaders.Expires, '-1');
258
- resp.setHeader(HttpHeaders.X_Opra_Version, OpraVersion);
260
+ resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
259
261
  resp.send(JSON.stringify(error.response));
260
262
  }
261
263
  }
@@ -1,17 +1,16 @@
1
+ import { OpraService, ResponsiveMap } from '@opra/schema';
1
2
  import { SearchParams } from '@opra/url';
2
3
  import { HttpStatus } from '../enums/index.js';
3
4
  import { ApiException } from '../exception/index.js';
4
5
  import { ContextType, IExecutionContext, IHttpExecutionContext } from '../interfaces/execution-context.interface.js';
5
6
  import { OpraQuery } from '../interfaces/query.interface.js';
6
- import { HeadersObject } from '../utils/headers.js';
7
- import { OpraService } from './opra-service.js';
8
7
  export declare type QueryContextArgs = Pick<QueryContext, 'service' | 'executionContext' | 'query' | 'params' | 'headers' | 'userContext' | 'parentValue' | 'continueOnError'>;
9
8
  export declare class QueryContext {
10
9
  readonly service: OpraService;
11
10
  readonly executionContext: IExecutionContext;
12
11
  readonly query: OpraQuery;
13
12
  readonly params: SearchParams;
14
- readonly headers: HeadersObject;
13
+ readonly headers: Map<string, string>;
15
14
  readonly parentValue?: any;
16
15
  readonly resultPath: string;
17
16
  readonly response: QueryResponse;
@@ -23,7 +22,7 @@ export declare class QueryContext {
23
22
  }
24
23
  export declare type QueryResponseArgs = Pick<QueryResponse, 'status' | 'value' | 'total'>;
25
24
  export declare class QueryResponse {
26
- headers: HeadersObject;
25
+ headers: ResponsiveMap<string, string>;
27
26
  errors: ApiException[];
28
27
  status?: HttpStatus;
29
28
  value?: any;
@@ -1,5 +1,6 @@
1
+ import { ResponsiveMap } from '@opra/schema';
1
2
  import { OpraURLSearchParams } from '@opra/url';
2
- import { Headers } from '../utils/headers.js';
3
+ import { HttpHeaders } from '../enums/index.js';
3
4
  export class QueryContext {
4
5
  service;
5
6
  executionContext;
@@ -15,7 +16,7 @@ export class QueryContext {
15
16
  Object.assign(this, args);
16
17
  this.response = new QueryResponse();
17
18
  this.params = this.params || new OpraURLSearchParams();
18
- this.headers = this.headers || Headers.create();
19
+ this.headers = this.headers || new ResponsiveMap();
19
20
  this.resultPath = this.resultPath || '';
20
21
  }
21
22
  get type() {
@@ -28,7 +29,7 @@ export class QueryContext {
28
29
  }
29
30
  }
30
31
  export class QueryResponse {
31
- headers = Headers.create();
32
+ headers;
32
33
  errors = [];
33
34
  status;
34
35
  value;
@@ -36,5 +37,6 @@ export class QueryResponse {
36
37
  constructor(args) {
37
38
  if (args)
38
39
  Object.assign(this, args);
40
+ this.headers = new ResponsiveMap(undefined, Array.from(Object.values(HttpHeaders)));
39
41
  }
40
42
  }
package/esm/index.d.ts CHANGED
@@ -1,23 +1,13 @@
1
1
  import "reflect-metadata";
2
- export * from './constants.js';
3
2
  export * from './types.js';
4
3
  export * from './enums/index.js';
5
4
  export * from './exception/index.js';
6
- export * from './decorators/api-entity-resource.decorator.js';
7
5
  export * from './interfaces/execution-context.interface.js';
8
6
  export * from './interfaces/query.interface.js';
9
- export * from './interfaces/resource-container.interface.js';
7
+ export * from './interfaces/entity-service.interface.js';
10
8
  export * from './implementation/query-context.js';
11
- export * from './implementation/opra-document.js';
12
- export * from './implementation/opra-service.js';
13
- export * from './implementation/schema-generator.js';
14
- export * from './implementation/adapter/adapter.js';
15
- export * from './implementation/adapter/http-adapter.js';
16
- export * from './implementation/adapter/express-adapter.js';
17
- export * from './implementation/data-type/data-type.js';
18
- export * from './implementation/data-type/complex-type.js';
19
- export * from './implementation/data-type/simple-type.js';
20
- export * from './implementation/resource/resource-handler.js';
21
- export * from './implementation/resource/entity-resource-handler.js';
22
- export * from './services/entity-resource-controller.js';
9
+ export * from './implementation/adapter.js';
10
+ export * from './implementation/http-adapter.js';
11
+ export * from './implementation/express-adapter.js';
12
+ export * from './services/data-service.js';
23
13
  export * from './services/json-data-service.js';
package/esm/index.js CHANGED
@@ -1,23 +1,13 @@
1
1
  import "reflect-metadata";
2
- export * from './constants.js';
3
2
  export * from './types.js';
4
3
  export * from './enums/index.js';
5
4
  export * from './exception/index.js';
6
- export * from './decorators/api-entity-resource.decorator.js';
7
5
  export * from './interfaces/execution-context.interface.js';
8
6
  export * from './interfaces/query.interface.js';
9
- export * from './interfaces/resource-container.interface.js';
7
+ export * from './interfaces/entity-service.interface.js';
10
8
  export * from './implementation/query-context.js';
11
- export * from './implementation/opra-document.js';
12
- export * from './implementation/opra-service.js';
13
- export * from './implementation/schema-generator.js';
14
- export * from './implementation/adapter/adapter.js';
15
- export * from './implementation/adapter/http-adapter.js';
16
- export * from './implementation/adapter/express-adapter.js';
17
- export * from './implementation/data-type/data-type.js';
18
- export * from './implementation/data-type/complex-type.js';
19
- export * from './implementation/data-type/simple-type.js';
20
- export * from './implementation/resource/resource-handler.js';
21
- export * from './implementation/resource/entity-resource-handler.js';
22
- export * from './services/entity-resource-controller.js';
9
+ export * from './implementation/adapter.js';
10
+ export * from './implementation/http-adapter.js';
11
+ export * from './implementation/express-adapter.js';
12
+ export * from './services/data-service.js';
23
13
  export * from './services/json-data-service.js';
@@ -1,17 +1,16 @@
1
1
  import { StrictOmit } from 'ts-gems';
2
- import { OpraSchema } from '@opra/schema';
2
+ import { EntityResource, OpraSchema } from '@opra/schema';
3
3
  import { Expression } from '@opra/url';
4
- import { EntityResourceHandler } from '../implementation/resource/entity-resource-handler.js';
5
- import { KeyValue, OperationType, QueryScope, QueryType } from '../types.js';
6
- export declare type OpraQuery = OpraMetadataQuery | OpraCreateQuery | OpraGetEntityQuery | OpraSearchQuery | OpraUpdateQuery | OpraUpdateManyQuery | OpraDeleteQuery | OpraDeleteManyQuery;
4
+ import { KeyValue, QueryType } from '../types.js';
5
+ export declare type OpraQuery = OpraGetSchemaQuery | OpraCreateQuery | OpraGetEntityQuery | OpraSearchQuery | OpraUpdateQuery | OpraUpdateManyQuery | OpraDeleteQuery | OpraDeleteManyQuery;
7
6
  interface BaseOpraQuery {
8
7
  queryType: QueryType;
9
- scope: QueryScope;
10
- operation: OperationType;
8
+ scope: OpraSchema.QueryScope;
9
+ operation: OpraSchema.OperationType;
11
10
  }
12
- export interface OpraMetadataQuery extends BaseOpraQuery {
13
- queryType: 'metadata';
14
- scope: QueryScope;
11
+ export interface OpraGetSchemaQuery extends BaseOpraQuery {
12
+ queryType: 'schema';
13
+ scope: OpraSchema.QueryScope;
15
14
  operation: 'read';
16
15
  resourcePath: string[];
17
16
  }
@@ -19,7 +18,7 @@ export interface OpraCreateQuery extends BaseOpraQuery {
19
18
  queryType: 'create';
20
19
  scope: 'collection';
21
20
  operation: 'create';
22
- resource: EntityResourceHandler;
21
+ resource: EntityResource;
23
22
  data: {};
24
23
  pick?: string[];
25
24
  omit?: string[];
@@ -29,7 +28,7 @@ export interface OpraGetEntityQuery extends BaseOpraQuery {
29
28
  queryType: 'get';
30
29
  scope: 'instance';
31
30
  operation: 'read';
32
- resource: EntityResourceHandler;
31
+ resource: EntityResource;
33
32
  keyValue: KeyValue;
34
33
  pick?: string[];
35
34
  omit?: string[];
@@ -40,14 +39,14 @@ export interface OpraPropertyQuery extends BaseOpraQuery {
40
39
  queryType: 'get';
41
40
  scope: 'property';
42
41
  operation: 'read';
43
- property: OpraSchema.Property;
42
+ property: OpraSchema.Field;
44
43
  nested?: OpraPropertyQuery;
45
44
  }
46
45
  export interface OpraUpdateQuery extends BaseOpraQuery {
47
46
  queryType: 'update';
48
47
  scope: 'instance';
49
48
  operation: 'update';
50
- resource: EntityResourceHandler;
49
+ resource: EntityResource;
51
50
  keyValue: KeyValue;
52
51
  data: {};
53
52
  pick?: string[];
@@ -58,7 +57,7 @@ export interface OpraUpdateManyQuery extends BaseOpraQuery {
58
57
  queryType: 'updateMany';
59
58
  scope: 'collection';
60
59
  operation: 'update';
61
- resource: EntityResourceHandler;
60
+ resource: EntityResource;
62
61
  filter?: string | Expression;
63
62
  data: {};
64
63
  }
@@ -66,21 +65,21 @@ export interface OpraDeleteQuery extends BaseOpraQuery {
66
65
  queryType: 'delete';
67
66
  scope: 'instance';
68
67
  operation: 'delete';
69
- resource: EntityResourceHandler;
68
+ resource: EntityResource;
70
69
  keyValue: KeyValue;
71
70
  }
72
71
  export interface OpraDeleteManyQuery extends BaseOpraQuery {
73
72
  queryType: 'deleteMany';
74
73
  scope: 'collection';
75
74
  operation: 'delete';
76
- resource: EntityResourceHandler;
75
+ resource: EntityResource;
77
76
  filter?: string | Expression;
78
77
  }
79
78
  export interface OpraSearchQuery extends BaseOpraQuery {
80
79
  queryType: 'search';
81
80
  scope: 'collection';
82
81
  operation: 'read';
83
- resource: EntityResourceHandler;
82
+ resource: EntityResource;
84
83
  pick?: string[];
85
84
  omit?: string[];
86
85
  include?: string[];
@@ -99,15 +98,15 @@ export declare type UpdateManyQueryOptions = StrictOmit<OpraUpdateManyQuery, 'qu
99
98
  export declare type DeleteQueryOptions = StrictOmit<OpraDeleteQuery, 'queryType' | 'scope' | 'operation' | 'resource' | 'keyValue'>;
100
99
  export declare type DeleteManyQueryOption = StrictOmit<OpraDeleteManyQuery, 'queryType' | 'scope' | 'operation' | 'resource'>;
101
100
  export declare namespace OpraQuery {
102
- function forCreate(resource: EntityResourceHandler, values: {}, options?: CreateQueryOptions): OpraCreateQuery;
103
- function forGetMetadata(resourcePath: string[], options?: GetEntityQueryOptions): OpraMetadataQuery;
104
- function forGetEntity(resource: EntityResourceHandler, key: KeyValue, options?: GetEntityQueryOptions): OpraGetEntityQuery;
105
- function forSearch(resource: EntityResourceHandler, options?: SearchQueryOptions): OpraSearchQuery;
106
- function forGetProperty(property: OpraSchema.Property, options?: StrictOmit<OpraPropertyQuery, 'queryType' | 'scope' | 'operation' | 'property'>): OpraPropertyQuery;
107
- function forUpdate(resource: EntityResourceHandler, keyValue: KeyValue, values: any, options?: UpdateQueryOptions): OpraUpdateQuery;
108
- function forUpdateMany(resource: EntityResourceHandler, values: any, options?: UpdateManyQueryOptions): OpraUpdateManyQuery;
109
- function forDelete(resource: EntityResourceHandler, key: KeyValue): OpraDeleteQuery;
110
- function forDeleteMany(resource: EntityResourceHandler, options?: DeleteManyQueryOption): OpraDeleteManyQuery;
101
+ function forCreate(resource: EntityResource, values: {}, options?: CreateQueryOptions): OpraCreateQuery;
102
+ function forGetSchema(resourcePath: string[], options?: GetEntityQueryOptions): OpraGetSchemaQuery;
103
+ function forGetEntity(resource: EntityResource, key: KeyValue, options?: GetEntityQueryOptions): OpraGetEntityQuery;
104
+ function forSearch(resource: EntityResource, options?: SearchQueryOptions): OpraSearchQuery;
105
+ function forGetProperty(property: OpraSchema.Field, options?: StrictOmit<OpraPropertyQuery, 'queryType' | 'scope' | 'operation' | 'property'>): OpraPropertyQuery;
106
+ function forUpdate(resource: EntityResource, keyValue: KeyValue, values: any, options?: UpdateQueryOptions): OpraUpdateQuery;
107
+ function forUpdateMany(resource: EntityResource, values: any, options?: UpdateManyQueryOptions): OpraUpdateManyQuery;
108
+ function forDelete(resource: EntityResource, key: KeyValue): OpraDeleteQuery;
109
+ function forDeleteMany(resource: EntityResource, options?: DeleteManyQueryOption): OpraDeleteManyQuery;
111
110
  function isCreateQuery(q: any): q is OpraCreateQuery;
112
111
  function isSearchQuery(q: any): q is OpraSearchQuery;
113
112
  function isReadQuery(q: any): q is OpraGetEntityQuery;