@opra/core 0.3.0 → 0.4.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 (52) hide show
  1. package/cjs/adapter/adapter.js +319 -0
  2. package/cjs/{implementation → adapter}/express-adapter.js +3 -6
  3. package/cjs/adapter/http-adapter.js +242 -0
  4. package/cjs/adapter/metadata-resource.js +23 -0
  5. package/cjs/{implementation → adapter}/query-context.js +1 -1
  6. package/cjs/enums/http-headers.enum.js +1 -1
  7. package/cjs/{implementation → helpers}/headers-map.js +2 -2
  8. package/cjs/index.js +6 -5
  9. package/cjs/interfaces/resource.interface.js +2 -0
  10. package/cjs/services/json-collection-service.js +14 -14
  11. package/cjs/services/json-singleton-service.js +97 -0
  12. package/esm/{implementation → adapter}/adapter.d.ts +17 -9
  13. package/esm/adapter/adapter.js +315 -0
  14. package/esm/{implementation → adapter}/express-adapter.d.ts +2 -2
  15. package/esm/{implementation → adapter}/express-adapter.js +3 -6
  16. package/esm/{implementation → adapter}/http-adapter.d.ts +2 -3
  17. package/esm/adapter/http-adapter.js +238 -0
  18. package/esm/adapter/metadata-resource.d.ts +8 -0
  19. package/esm/adapter/metadata-resource.js +20 -0
  20. package/esm/{implementation → adapter}/query-context.d.ts +6 -6
  21. package/esm/{implementation → adapter}/query-context.js +1 -1
  22. package/esm/enums/http-headers.enum.d.ts +1 -1
  23. package/esm/enums/http-headers.enum.js +1 -1
  24. package/esm/{implementation → helpers}/headers-map.d.ts +1 -1
  25. package/esm/{implementation → helpers}/headers-map.js +1 -1
  26. package/esm/index.d.ts +6 -5
  27. package/esm/index.js +6 -5
  28. package/esm/interfaces/resource.interface.d.ts +22 -0
  29. package/esm/interfaces/resource.interface.js +1 -0
  30. package/esm/services/json-collection-service.d.ts +11 -12
  31. package/esm/services/json-collection-service.js +15 -15
  32. package/esm/services/json-singleton-service.d.ts +39 -0
  33. package/esm/services/json-singleton-service.js +92 -0
  34. package/esm/types.d.ts +2 -8
  35. package/esm/utils/create-i18n.d.ts +1 -1
  36. package/package.json +15 -13
  37. package/cjs/implementation/adapter-utils/entity-resource-execute.util.js +0 -86
  38. package/cjs/implementation/adapter-utils/resource-execute.util.js +0 -11
  39. package/cjs/implementation/adapter-utils/resource-prepare.util.js +0 -11
  40. package/cjs/implementation/adapter.js +0 -130
  41. package/cjs/implementation/http-adapter.js +0 -253
  42. package/cjs/interfaces/entity-service.interface.js +0 -30
  43. package/esm/implementation/adapter-utils/entity-resource-execute.util.d.ts +0 -3
  44. package/esm/implementation/adapter-utils/entity-resource-execute.util.js +0 -82
  45. package/esm/implementation/adapter-utils/resource-execute.util.d.ts +0 -3
  46. package/esm/implementation/adapter-utils/resource-execute.util.js +0 -7
  47. package/esm/implementation/adapter-utils/resource-prepare.util.d.ts +0 -3
  48. package/esm/implementation/adapter-utils/resource-prepare.util.js +0 -7
  49. package/esm/implementation/adapter.js +0 -126
  50. package/esm/implementation/http-adapter.js +0 -249
  51. package/esm/interfaces/entity-service.interface.d.ts +0 -19
  52. package/esm/interfaces/entity-service.interface.js +0 -26
@@ -0,0 +1,238 @@
1
+ import { BadRequestError, InternalServerError, IssueSeverity, MethodNotAllowedError, NotFoundError, OpraException, wrapException } from '@opra/exception';
2
+ import { CollectionCreateQuery, CollectionDeleteManyQuery, CollectionDeleteQuery, CollectionGetQuery, CollectionResourceInfo, CollectionSearchQuery, CollectionUpdateManyQuery, CollectionUpdateQuery, ComplexType, ContainerResourceInfo, FieldGetQuery, OpraSchema, SingletonGetQuery, SingletonResourceInfo, UnionType, } from '@opra/schema';
3
+ import { OpraURL } from '@opra/url';
4
+ import { HttpHeaders, HttpStatus } from '../enums/index.js';
5
+ import { HeadersMap } from '../helpers/headers-map.js';
6
+ import { OpraAdapter } from './adapter.js';
7
+ import { QueryContext } from './query-context.js';
8
+ export class OpraHttpAdapter extends OpraAdapter {
9
+ prepareRequests(executionContext) {
10
+ const req = executionContext.getRequestWrapper();
11
+ // todo implement batch requests
12
+ if (this.isBatch(executionContext)) {
13
+ throw new Error('not implemented yet');
14
+ }
15
+ const url = new OpraURL(req.getUrl());
16
+ return [
17
+ this.prepareRequest(executionContext, url, req.getMethod(), new HeadersMap(req.getHeaders()), req.getBody())
18
+ ];
19
+ }
20
+ prepareRequest(executionContext, url, method, headers, body) {
21
+ if (!url.path.size)
22
+ throw new BadRequestError();
23
+ if (method !== 'GET' && url.path.size > 1)
24
+ throw new BadRequestError();
25
+ const query = this.buildQuery(url, method, body);
26
+ if (!query)
27
+ throw new MethodNotAllowedError({
28
+ message: `Method "${method}" is not allowed by target endpoint`
29
+ });
30
+ return new QueryContext({
31
+ service: this.document,
32
+ executionContext,
33
+ query,
34
+ headers: new HeadersMap(),
35
+ params: url.searchParams,
36
+ continueOnError: query.operation === 'read'
37
+ });
38
+ }
39
+ buildQuery(url, method, body) {
40
+ const pathLen = url.path.size;
41
+ let p = url.path.get(0);
42
+ let resource = this._internalResources.get(p.resource) || this.document.getResource(p.resource);
43
+ let container;
44
+ let pathIndex = 0;
45
+ while (resource && resource instanceof ContainerResourceInfo) {
46
+ container = resource;
47
+ p = url.path.get(++pathIndex);
48
+ resource = container.getResource(p.resource);
49
+ }
50
+ try {
51
+ method = method.toUpperCase();
52
+ let query;
53
+ if (resource instanceof SingletonResourceInfo && !p.key) {
54
+ switch (method) {
55
+ case 'GET': {
56
+ query = new SingletonGetQuery(resource);
57
+ }
58
+ }
59
+ }
60
+ else if (resource instanceof CollectionResourceInfo) {
61
+ switch (method) {
62
+ case 'GET': {
63
+ if (p.key) {
64
+ const searchParams = url.searchParams;
65
+ query = new CollectionGetQuery(resource, p.key, {
66
+ pick: searchParams.get('$pick'),
67
+ omit: searchParams.get('$omit'),
68
+ include: searchParams.get('$include')
69
+ });
70
+ }
71
+ else {
72
+ const searchParams = url.searchParams;
73
+ query = new CollectionSearchQuery(resource, {
74
+ filter: searchParams.get('$filter'),
75
+ limit: searchParams.get('$limit'),
76
+ skip: searchParams.get('$skip'),
77
+ distinct: searchParams.get('$distinct'),
78
+ count: searchParams.get('$count'),
79
+ sort: searchParams.get('$sort'),
80
+ pick: searchParams.get('$pick'),
81
+ omit: searchParams.get('$omit'),
82
+ include: searchParams.get('$include')
83
+ });
84
+ }
85
+ break;
86
+ }
87
+ case 'DELETE': {
88
+ const searchParams = url.searchParams;
89
+ query = p.key
90
+ ? new CollectionDeleteQuery(resource, p.key)
91
+ : new CollectionDeleteManyQuery(resource, {
92
+ filter: searchParams.get('$filter'),
93
+ });
94
+ break;
95
+ }
96
+ case 'POST': {
97
+ if (!p.key) {
98
+ const searchParams = url.searchParams;
99
+ query = new CollectionCreateQuery(resource, body, {
100
+ pick: searchParams.get('$pick'),
101
+ omit: searchParams.get('$omit'),
102
+ include: searchParams.get('$include')
103
+ });
104
+ }
105
+ break;
106
+ }
107
+ case 'PATCH': {
108
+ if (p.key) {
109
+ const searchParams = url.searchParams;
110
+ query = new CollectionUpdateQuery(resource, p.key, body, {
111
+ pick: searchParams.get('$pick'),
112
+ omit: searchParams.get('$omit'),
113
+ include: searchParams.get('$include')
114
+ });
115
+ }
116
+ else {
117
+ const searchParams = url.searchParams;
118
+ query = new CollectionUpdateManyQuery(resource, body, {
119
+ filter: searchParams.get('$filter')
120
+ });
121
+ }
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ else
127
+ throw new InternalServerError();
128
+ if (query instanceof SingletonGetQuery || query instanceof CollectionGetQuery || query instanceof FieldGetQuery) {
129
+ // Move through properties
130
+ let parentType;
131
+ const curPath = [];
132
+ let parent = query;
133
+ while (++pathIndex < pathLen) {
134
+ p = url.path.get(pathIndex);
135
+ parentType = parent.dataType;
136
+ if (parent.dataType instanceof UnionType) {
137
+ if (parent.dataType.name === 'any')
138
+ parentType = this.document.getComplexDataType('object');
139
+ else
140
+ throw new TypeError(`"${resource.name}.${curPath.join()}" is a UnionType and needs type casting.`);
141
+ }
142
+ if (!(parentType instanceof ComplexType))
143
+ throw new TypeError(`"${resource.name}.${curPath.join()}" is not a ComplexType and has no fields.`);
144
+ curPath.push(p.resource);
145
+ parent.child = new FieldGetQuery(parent, p.resource, { castingType: parentType });
146
+ parent = parent.child;
147
+ }
148
+ }
149
+ return query;
150
+ }
151
+ catch (e) {
152
+ if (e instanceof OpraException)
153
+ throw e;
154
+ throw new BadRequestError(e);
155
+ }
156
+ }
157
+ async sendResponse(executionContext, queryContexts) {
158
+ const outputPackets = [];
159
+ for (const ctx of queryContexts) {
160
+ const v = this.createOutput(ctx);
161
+ outputPackets.push(v);
162
+ }
163
+ if (this.isBatch(executionContext)) {
164
+ // this.writeError([], new InternalServerError({message: 'Not implemented yet'}));
165
+ return;
166
+ }
167
+ if (!outputPackets.length)
168
+ return this.sendError(executionContext, new NotFoundError());
169
+ const out = outputPackets[0];
170
+ const resp = executionContext.getResponseWrapper();
171
+ resp.setStatus(out.status);
172
+ resp.setHeader(HttpHeaders.Content_Type, 'application/json');
173
+ resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
174
+ resp.setHeader(HttpHeaders.Pragma, 'no-cache');
175
+ resp.setHeader(HttpHeaders.Expires, '-1');
176
+ resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
177
+ if (out.headers) {
178
+ for (const [k, v] of Object.entries(out.headers)) {
179
+ resp.setHeader(k, v);
180
+ }
181
+ }
182
+ resp.send(JSON.stringify(out.body));
183
+ resp.end();
184
+ }
185
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
186
+ isBatch(executionContext) {
187
+ return false;
188
+ }
189
+ createOutput(ctx) {
190
+ const { query } = ctx;
191
+ let body;
192
+ let status = ctx.status || 0;
193
+ const errors = ctx.errors.map(e => wrapException(e));
194
+ if (errors && errors.length) {
195
+ // Sort errors from fatal to info
196
+ errors.sort((a, b) => {
197
+ const i = IssueSeverity.Keys.indexOf(a.issue.severity) - IssueSeverity.Keys.indexOf(b.issue.severity);
198
+ if (i === 0)
199
+ return b.status - a.status;
200
+ return i;
201
+ });
202
+ if (!status || status < HttpStatus.BAD_REQUEST) {
203
+ status = errors[0].status;
204
+ if (status < HttpStatus.BAD_REQUEST)
205
+ status = HttpStatus.INTERNAL_SERVER_ERROR;
206
+ }
207
+ body = {
208
+ operation: ctx.query.method,
209
+ errors: errors.map(e => e.issue)
210
+ };
211
+ }
212
+ else {
213
+ body = ctx.response;
214
+ status = status || (query.operation === 'create' ? HttpStatus.CREATED : HttpStatus.OK);
215
+ }
216
+ body = this.i18n.deep(body);
217
+ return {
218
+ status,
219
+ headers: ctx.responseHeaders.toObject(),
220
+ body
221
+ };
222
+ }
223
+ async sendError(executionContext, error) {
224
+ const resp = executionContext.getResponseWrapper();
225
+ resp.setStatus(error.status || 500);
226
+ resp.setHeader(HttpHeaders.Content_Type, 'application/json');
227
+ resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
228
+ resp.setHeader(HttpHeaders.Pragma, 'no-cache');
229
+ resp.setHeader(HttpHeaders.Expires, '-1');
230
+ resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
231
+ const issue = this.i18n.deep(error.issue);
232
+ const body = {
233
+ operation: 'unknown',
234
+ errors: [issue]
235
+ };
236
+ resp.send(JSON.stringify(body));
237
+ }
238
+ }
@@ -0,0 +1,8 @@
1
+ import { SingletonResourceInfo } from '@opra/schema';
2
+ import { ISingletonResource } from '../interfaces/resource.interface.js';
3
+ import { JsonSingletonService } from '../services/json-singleton-service.js';
4
+ export declare class MetadataResource implements ISingletonResource<any> {
5
+ service: JsonSingletonService<any>;
6
+ init(resource: SingletonResourceInfo): void;
7
+ get(): any;
8
+ }
@@ -0,0 +1,20 @@
1
+ import { __decorate } from "tslib";
2
+ import { OprSingletonResource } from '@opra/schema';
3
+ import { JsonSingletonService } from '../services/json-singleton-service.js';
4
+ let MetadataResource = class MetadataResource {
5
+ service;
6
+ init(resource) {
7
+ this.service = new JsonSingletonService(resource.dataType, {
8
+ data: resource.document.getMetadata(true)
9
+ });
10
+ }
11
+ get() {
12
+ return this.service.get();
13
+ }
14
+ };
15
+ MetadataResource = __decorate([
16
+ OprSingletonResource(Object, {
17
+ name: '$metadata'
18
+ })
19
+ ], MetadataResource);
20
+ export { MetadataResource };
@@ -1,15 +1,15 @@
1
1
  import { OpraException } from '@opra/exception';
2
- import { OpraAnyQuery, OpraApi } from '@opra/schema';
3
- import { SearchParams } from '@opra/url';
2
+ import { OpraDocument, OpraQuery } from '@opra/schema';
3
+ import { OpraURLSearchParams } from '@opra/url';
4
4
  import { HttpStatus } from '../enums/index.js';
5
+ import { HeadersMap } from '../helpers/headers-map.js';
5
6
  import { ContextType, IExecutionContext, IHttpExecutionContext } from '../interfaces/execution-context.interface.js';
6
- import { HeadersMap } from './headers-map.js';
7
7
  export declare type QueryContextArgs = Pick<QueryContext, 'service' | 'executionContext' | 'query' | 'params' | 'headers' | 'userContext' | 'parentValue' | 'continueOnError'>;
8
8
  export declare class QueryContext {
9
- readonly service: OpraApi;
9
+ readonly service: OpraDocument;
10
10
  readonly executionContext: IExecutionContext;
11
- readonly query: OpraAnyQuery;
12
- readonly params: SearchParams;
11
+ readonly query: OpraQuery;
12
+ readonly params: OpraURLSearchParams;
13
13
  readonly headers: HeadersMap;
14
14
  readonly parentValue?: any;
15
15
  readonly resultPath: string;
@@ -1,5 +1,5 @@
1
1
  import { OpraURLSearchParams } from '@opra/url';
2
- import { HeadersMap } from './headers-map.js';
2
+ import { HeadersMap } from '../helpers/headers-map.js';
3
3
  export class QueryContext {
4
4
  service;
5
5
  executionContext;
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export declare enum HttpHeaders {
5
5
  X_Opra_Version = "X-Opra-Version",
6
- X_Opra_Schema = "X-Opra-Schema",
6
+ X_Opra_DataType = "X-Opra-DataType",
7
7
  X_Opra_Count = "X-Opra-Count",
8
8
  /**
9
9
  * Defines the authentication method that should be used to access a resource.
@@ -6,7 +6,7 @@ export var HttpHeaders;
6
6
  (function (HttpHeaders) {
7
7
  /* *** Custom Headers *** */
8
8
  HttpHeaders["X_Opra_Version"] = "X-Opra-Version";
9
- HttpHeaders["X_Opra_Schema"] = "X-Opra-Schema";
9
+ HttpHeaders["X_Opra_DataType"] = "X-Opra-DataType";
10
10
  HttpHeaders["X_Opra_Count"] = "X-Opra-Count";
11
11
  /* *** Authentication *** */
12
12
  /**
@@ -1,4 +1,4 @@
1
- import { ResponsiveMap } from '@opra/schema';
1
+ import { ResponsiveMap } from '@opra/common';
2
2
  export declare class HeadersMap extends ResponsiveMap<string, string> {
3
3
  constructor(data?: any);
4
4
  toObject(): Record<string, string>;
@@ -1,4 +1,4 @@
1
- import { ResponsiveMap } from '@opra/schema';
1
+ import { ResponsiveMap } from '@opra/common';
2
2
  import { HttpHeaders } from '../enums/index.js';
3
3
  export class HeadersMap extends ResponsiveMap {
4
4
  constructor(data) {
package/esm/index.d.ts CHANGED
@@ -2,10 +2,11 @@ import "reflect-metadata";
2
2
  export * from './types.js';
3
3
  export * from './enums/index.js';
4
4
  export * from './interfaces/execution-context.interface.js';
5
- export * from './interfaces/entity-service.interface.js';
6
- export * from './implementation/query-context.js';
7
- export * from './implementation/adapter.js';
8
- export * from './implementation/http-adapter.js';
9
- export * from './implementation/express-adapter.js';
5
+ export * from './interfaces/resource.interface.js';
6
+ export * from './adapter/query-context.js';
7
+ export * from './adapter/adapter.js';
8
+ export * from './adapter/http-adapter.js';
9
+ export * from './adapter/express-adapter.js';
10
10
  export * from './services/data-service.js';
11
11
  export * from './services/json-collection-service.js';
12
+ export * from './services/json-singleton-service.js';
package/esm/index.js CHANGED
@@ -2,10 +2,11 @@ import "reflect-metadata";
2
2
  export * from './types.js';
3
3
  export * from './enums/index.js';
4
4
  export * from './interfaces/execution-context.interface.js';
5
- export * from './interfaces/entity-service.interface.js';
6
- export * from './implementation/query-context.js';
7
- export * from './implementation/adapter.js';
8
- export * from './implementation/http-adapter.js';
9
- export * from './implementation/express-adapter.js';
5
+ export * from './interfaces/resource.interface.js';
6
+ export * from './adapter/query-context.js';
7
+ export * from './adapter/adapter.js';
8
+ export * from './adapter/http-adapter.js';
9
+ export * from './adapter/express-adapter.js';
10
10
  export * from './services/data-service.js';
11
11
  export * from './services/json-collection-service.js';
12
+ export * from './services/json-singleton-service.js';
@@ -0,0 +1,22 @@
1
+ import { Maybe } from 'ts-gems';
2
+ import { ResourceInfo } from '@opra/schema';
3
+ import { PartialOutput } from '../types.js';
4
+ export interface IResource {
5
+ init?(resource: ResourceInfo): void | Promise<void>;
6
+ }
7
+ export interface ICollectionResource<T, TOutput = PartialOutput<T>> extends IResource {
8
+ create?(...args: any[]): TOutput | Promise<TOutput>;
9
+ count?(...args: any[]): number | Promise<number>;
10
+ delete?(...args: any[]): boolean | Promise<boolean>;
11
+ deleteMany?(...args: any[]): number | Promise<number>;
12
+ get?(...args: any[]): Maybe<TOutput> | Promise<Maybe<TOutput>>;
13
+ search?(...args: any[]): TOutput[] | Promise<TOutput[]>;
14
+ update?(...args: any[]): Maybe<TOutput> | Promise<Maybe<TOutput>>;
15
+ updateMany?(...args: any[]): number | Promise<number>;
16
+ }
17
+ export interface ISingletonResource<T, TOutput = PartialOutput<T>> extends IResource {
18
+ create?(...args: any[]): TOutput | Promise<TOutput>;
19
+ delete?(...args: any[]): boolean | Promise<boolean>;
20
+ get?(...args: any[]): Maybe<TOutput> | Promise<Maybe<TOutput>>;
21
+ update?(...args: any[]): Maybe<TOutput> | Promise<Maybe<TOutput>>;
22
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,22 +1,21 @@
1
1
  import { Maybe } from 'ts-gems';
2
- import { ComplexType, EntityResource, OpraAnyQuery, OpraSchema } from '@opra/schema';
2
+ import { CollectionResourceInfo, ComplexType, OpraQuery, OpraSchema } from '@opra/schema';
3
3
  import { Expression } from '@opra/url';
4
- import { QueryContext } from '../implementation/query-context.js';
5
- import { IEntityService } from '../interfaces/entity-service.interface.js';
6
- import { EntityInput, EntityOutput } from '../types.js';
4
+ import { QueryContext } from '../adapter/query-context.js';
5
+ import { PartialInput, PartialOutput } from '../types.js';
7
6
  export interface JsonCollectionServiceOptions {
8
7
  resourceName?: string;
9
8
  defaultLimit?: number;
10
9
  data?: any[];
11
10
  }
12
- export declare class JsonCollectionService<T, TOutput = EntityOutput<T>> implements IEntityService {
13
- readonly resource: EntityResource;
11
+ export declare class JsonCollectionService<T, TOutput = PartialOutput<T>> {
12
+ readonly resource: CollectionResourceInfo;
14
13
  private _status;
15
14
  private _initError;
16
15
  private _dbName;
17
16
  private _initData?;
18
17
  defaultLimit: number;
19
- constructor(resource: EntityResource, options?: JsonCollectionServiceOptions);
18
+ constructor(resource: CollectionResourceInfo, options?: JsonCollectionServiceOptions);
20
19
  get dataType(): ComplexType;
21
20
  get primaryKey(): string;
22
21
  get resourceName(): string;
@@ -25,15 +24,15 @@ export declare class JsonCollectionService<T, TOutput = EntityOutput<T>> impleme
25
24
  get(keyValue: any, options?: JsonCollectionService.GetOptions): Promise<Maybe<TOutput>>;
26
25
  count(options?: JsonCollectionService.SearchOptions): Promise<number>;
27
26
  search(options?: JsonCollectionService.SearchOptions): Promise<TOutput[]>;
28
- create(data: EntityInput<T>, options?: JsonCollectionService.CreateOptions): Promise<TOutput>;
29
- update(keyValue: any, data: EntityInput<T>, options?: JsonCollectionService.UpdateOptions): Promise<Maybe<TOutput>>;
30
- updateMany(data: EntityInput<T>, options?: JsonCollectionService.UpdateManyOptions): Promise<number>;
27
+ create(data: PartialInput<T>, options?: JsonCollectionService.CreateOptions): Promise<TOutput>;
28
+ update(keyValue: any, data: PartialInput<T>, options?: JsonCollectionService.UpdateOptions): Promise<Maybe<TOutput>>;
29
+ updateMany(data: PartialInput<T>, options?: JsonCollectionService.UpdateManyOptions): Promise<number>;
31
30
  delete(keyValue: any): Promise<boolean>;
32
31
  deleteMany(options?: JsonCollectionService.DeleteManyOptions): Promise<number>;
33
32
  private _waitInitializing;
34
33
  protected _init(): Promise<void>;
35
- protected _prepare(query: OpraAnyQuery): {
36
- method: OpraSchema.EntityMethod;
34
+ protected _prepare(query: OpraQuery): {
35
+ method: OpraSchema.CollectionMethod;
37
36
  options: any;
38
37
  keyValue?: any;
39
38
  values?: any;
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import merge from 'putil-merge';
3
3
  import { nSQL } from "@nano-sql/core";
4
4
  import { BadRequestError, MethodNotAllowedError, ResourceConflictError } from '@opra/exception';
5
- import { ComplexType, EntityResource } from '@opra/schema';
5
+ import { CollectionResourceInfo, ComplexType } from '@opra/schema';
6
6
  import { $parse, ArrayExpression, BooleanLiteral, ComparisonExpression, DateLiteral, Expression, LogicalExpression, NullLiteral, NumberLiteral, ParenthesesExpression, QualifiedIdentifier, StringLiteral, TimeLiteral } from '@opra/url';
7
7
  import { pathToTree } from '../utils/path-to-tree.js';
8
8
  let dbId = 1;
@@ -191,7 +191,7 @@ export class JsonCollectionService {
191
191
  indexes: {}
192
192
  };
193
193
  for (const [k, f] of this.resource.dataType.fields.entries()) {
194
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
194
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
195
195
  const o = table.model[k + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
196
196
  if (k === this.primaryKey)
197
197
  o.pk = true;
@@ -199,21 +199,21 @@ export class JsonCollectionService {
199
199
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
200
200
  const indexes = table.indexes;
201
201
  // Add indexes for sort fields
202
- const searchMethod = this.resource.metadata.methods.search;
203
- if (searchMethod) {
204
- if (searchMethod.sortFields) {
205
- searchMethod.sortFields.forEach(fieldName => {
202
+ const searchResolver = this.resource.metadata.search;
203
+ if (searchResolver) {
204
+ if (searchResolver.sortFields) {
205
+ searchResolver.sortFields.forEach(fieldName => {
206
206
  const f = this.dataType.getField(fieldName);
207
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
207
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
208
208
  const t = dataTypeToSQLType(fieldType, !!f.isArray);
209
209
  if (indexingTypes.includes(t))
210
210
  indexes[fieldName + ':' + t] = {};
211
211
  });
212
212
  }
213
- if (searchMethod.filters) {
214
- searchMethod.filters.forEach(filter => {
213
+ if (searchResolver.filters) {
214
+ searchResolver.filters.forEach(filter => {
215
215
  const f = this.dataType.getField(filter.field);
216
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
216
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
217
217
  const t = dataTypeToSQLType(fieldType, !!f.isArray);
218
218
  if (indexingTypes.includes(t))
219
219
  indexes[filter.field + ':' + t] = {};
@@ -241,10 +241,10 @@ export class JsonCollectionService {
241
241
  }
242
242
  }
243
243
  _prepare(query) {
244
- if (query.resource instanceof EntityResource) {
244
+ if (query.resource instanceof CollectionResourceInfo) {
245
245
  if (query.dataType !== this.dataType)
246
246
  throw new TypeError(`Query data type (${query.dataType.name}) ` +
247
- `differs from JsonDataService data type (${this.dataType.name})`);
247
+ `differs from JsonCollectionService data type (${this.dataType.name})`);
248
248
  }
249
249
  switch (query.method) {
250
250
  case 'count': {
@@ -272,7 +272,7 @@ export class JsonCollectionService {
272
272
  };
273
273
  }
274
274
  case 'get': {
275
- if (query.kind === 'GetInstanceQuery') {
275
+ if (query.kind === 'CollectionGetQuery') {
276
276
  const options = _.omitBy({
277
277
  pick: query.pick,
278
278
  omit: query.omit,
@@ -286,7 +286,7 @@ export class JsonCollectionService {
286
286
  args: [keyValue, options]
287
287
  };
288
288
  }
289
- if (query.kind === 'GetFieldQuery') {
289
+ if (query.kind === 'FieldGetQuery') {
290
290
  // todo
291
291
  }
292
292
  break;
@@ -365,7 +365,7 @@ export class JsonCollectionService {
365
365
  }
366
366
  _convertSelect(args) {
367
367
  const result = [];
368
- const document = this.dataType.owner;
368
+ const document = this.dataType.document;
369
369
  const processDataType = (dt, path, pick, omit, include) => {
370
370
  let kl;
371
371
  for (const [k, f] of dt.fields) {
@@ -0,0 +1,39 @@
1
+ import { DataType, OpraQuery, OpraSchema } from '@opra/schema';
2
+ import { QueryContext } from '../adapter/query-context.js';
3
+ import { PartialOutput } from '../types.js';
4
+ export interface JsonSingletonServiceOptions<T> {
5
+ data: T;
6
+ resourceName?: string;
7
+ }
8
+ export declare class JsonSingletonService<T, TOutput = PartialOutput<T>> {
9
+ readonly dataType: DataType;
10
+ protected _data?: T;
11
+ constructor(dataType: DataType, options?: JsonSingletonServiceOptions<T>);
12
+ processRequest(ctx: QueryContext): Promise<any>;
13
+ get(options?: JsonSingletonService.GetOptions): TOutput | undefined;
14
+ protected _prepare(query: OpraQuery): {
15
+ method: OpraSchema.SingletonMethod;
16
+ options: any;
17
+ keyValue?: any;
18
+ values?: any;
19
+ args: any[];
20
+ };
21
+ }
22
+ export declare namespace JsonSingletonService {
23
+ type CreateOptions = {
24
+ query?: string;
25
+ pick?: string[];
26
+ omit?: string[];
27
+ include?: string[];
28
+ };
29
+ type GetOptions = {
30
+ pick?: string[];
31
+ omit?: string[];
32
+ include?: string[];
33
+ };
34
+ type UpdateOptions = {
35
+ pick?: string[];
36
+ omit?: string[];
37
+ include?: string[];
38
+ };
39
+ }