@opra/core 0.2.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 +7 -6
  9. package/cjs/interfaces/resource.interface.js +2 -0
  10. package/cjs/services/{json-data-service.js → json-collection-service.js} +62 -45
  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 +7 -6
  27. package/esm/index.js +7 -6
  28. package/esm/interfaces/resource.interface.d.ts +22 -0
  29. package/esm/interfaces/resource.interface.js +1 -0
  30. package/esm/services/{json-data-service.d.ts → json-collection-service.d.ts} +18 -19
  31. package/esm/services/{json-data-service.js → json-collection-service.js} +61 -44
  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 +16 -14
  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
@@ -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
- export * from './services/json-data-service.js';
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
- export * from './services/json-data-service.js';
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,39 +1,38 @@
1
1
  import { Maybe } from 'ts-gems';
2
- import { EntityResource, EntityType, 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';
7
- export interface JsonDataServiceOptions {
4
+ import { QueryContext } from '../adapter/query-context.js';
5
+ import { PartialInput, PartialOutput } from '../types.js';
6
+ export interface JsonCollectionServiceOptions {
8
7
  resourceName?: string;
9
8
  defaultLimit?: number;
10
9
  data?: any[];
11
10
  }
12
- export declare class JsonDataService<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?: JsonDataServiceOptions);
20
- get dataType(): EntityType;
18
+ constructor(resource: CollectionResourceInfo, options?: JsonCollectionServiceOptions);
19
+ get dataType(): ComplexType;
21
20
  get primaryKey(): string;
22
21
  get resourceName(): string;
23
22
  close(): Promise<void>;
24
23
  processRequest(ctx: QueryContext): Promise<any>;
25
- get(keyValue: any, options?: JsonDataService.GetOptions): Promise<Maybe<TOutput>>;
26
- count(options?: JsonDataService.SearchOptions): Promise<number>;
27
- search(options?: JsonDataService.SearchOptions): Promise<TOutput[]>;
28
- create(data: EntityInput<T>, options?: JsonDataService.CreateOptions): Promise<TOutput>;
29
- update(keyValue: any, data: EntityInput<T>, options?: JsonDataService.UpdateOptions): Promise<Maybe<TOutput>>;
30
- updateMany(data: EntityInput<T>, options?: JsonDataService.UpdateManyOptions): Promise<number>;
24
+ get(keyValue: any, options?: JsonCollectionService.GetOptions): Promise<Maybe<TOutput>>;
25
+ count(options?: JsonCollectionService.SearchOptions): Promise<number>;
26
+ search(options?: JsonCollectionService.SearchOptions): Promise<TOutput[]>;
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
- deleteMany(options?: JsonDataService.DeleteManyOptions): Promise<number>;
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;
@@ -46,7 +45,7 @@ export declare class JsonDataService<T, TOutput = EntityOutput<T>> implements IE
46
45
  }): string[];
47
46
  protected _convertFilter(str: string | Expression | undefined | {}): any;
48
47
  }
49
- export declare namespace JsonDataService {
48
+ export declare namespace JsonCollectionService {
50
49
  type CountOptions = {
51
50
  filter?: string | Expression | {};
52
51
  };
@@ -2,11 +2,12 @@ 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;
9
- export class JsonDataService {
9
+ const indexingTypes = ['int', 'float', 'number', 'date', 'string'];
10
+ export class JsonCollectionService {
10
11
  resource;
11
12
  _status = '';
12
13
  _initError;
@@ -15,6 +16,8 @@ export class JsonDataService {
15
16
  defaultLimit;
16
17
  constructor(resource, options) {
17
18
  this.resource = resource;
19
+ if (this.resource.keyFields.length > 1)
20
+ throw new TypeError('JsonDataService currently doesn\'t support multiple primary keys');
18
21
  this.defaultLimit = options?.defaultLimit ?? 10;
19
22
  this._initData = options?.data;
20
23
  }
@@ -22,7 +25,7 @@ export class JsonDataService {
22
25
  return this.resource.dataType;
23
26
  }
24
27
  get primaryKey() {
25
- return this.resource.dataType.primaryKey;
28
+ return this.resource.keyFields[0];
26
29
  }
27
30
  get resourceName() {
28
31
  return this.resource.name;
@@ -55,11 +58,16 @@ export class JsonDataService {
55
58
  include: options?.include,
56
59
  });
57
60
  nSQL().useDatabase(this._dbName);
58
- const rows = await nSQL(this.resourceName)
59
- .query('select', select)
60
- .where([this.primaryKey, '=', keyValue])
61
- .exec();
62
- return unFlatten(rows[0]);
61
+ try {
62
+ const rows = await nSQL(this.resourceName)
63
+ .query('select', select)
64
+ .where([this.primaryKey, '=', keyValue])
65
+ .exec();
66
+ return unFlatten(rows[0]);
67
+ }
68
+ catch (e) {
69
+ throw e;
70
+ }
63
71
  }
64
72
  async count(options) {
65
73
  await this._init();
@@ -95,19 +103,19 @@ export class JsonDataService {
95
103
  await this._init();
96
104
  const keyValue = data[this.primaryKey];
97
105
  nSQL().useDatabase(this._dbName);
98
- const rows = await nSQL(this._initData).query('select', [this.primaryKey])
106
+ const rows = await nSQL(this.resourceName).query('select', [this.primaryKey])
99
107
  .where([this.primaryKey, '=', keyValue])
100
108
  .exec();
101
109
  if (rows.length)
102
110
  throw new ResourceConflictError(this.resourceName, this.primaryKey);
103
- await nSQL(this._initData).query('upsert', data)
111
+ await nSQL(this.resourceName).query('upsert', data)
104
112
  .exec();
105
113
  return await this.get(keyValue, options);
106
114
  }
107
115
  async update(keyValue, data, options) {
108
116
  await this._init();
109
117
  nSQL().useDatabase(this._dbName);
110
- await nSQL(this._initData)
118
+ await nSQL(this.resourceName)
111
119
  .query('conform rows', (row) => {
112
120
  const out = merge({}, row, { deep: true, clone: true });
113
121
  merge(out, data, { deep: true });
@@ -115,16 +123,15 @@ export class JsonDataService {
115
123
  })
116
124
  .where([this.primaryKey, '=', keyValue])
117
125
  .exec();
118
- await nSQL(this._initData).query("rebuild indexes").exec();
126
+ // await nSQL(this.resourceName).query("rebuild indexes").exec();
119
127
  return this.get(keyValue, options);
120
128
  }
121
129
  async updateMany(data, options) {
122
130
  await this._init();
123
131
  const filter = this._convertFilter(options?.filter);
124
- await this._init();
125
132
  nSQL().useDatabase(this._dbName);
126
133
  let affected = 0;
127
- await nSQL(this._initData)
134
+ await nSQL(this.resourceName)
128
135
  .query('conform rows', (row) => {
129
136
  const out = merge({}, row, { deep: true, clone: true });
130
137
  merge(out, data, { deep: true });
@@ -133,13 +140,13 @@ export class JsonDataService {
133
140
  })
134
141
  .where(filter)
135
142
  .exec();
136
- await nSQL(this._initData).query("rebuild indexes").exec();
143
+ // await nSQL(this.resourceName).query("rebuild indexes").exec();
137
144
  return affected;
138
145
  }
139
146
  async delete(keyValue) {
140
147
  await this._init();
141
148
  nSQL().useDatabase(this._dbName);
142
- const result = await nSQL(this._initData)
149
+ const result = await nSQL(this.resourceName)
143
150
  .query('delete')
144
151
  .where([this.primaryKey, '=', keyValue])
145
152
  .exec();
@@ -149,7 +156,7 @@ export class JsonDataService {
149
156
  await this._init();
150
157
  const filter = this._convertFilter(options?.filter);
151
158
  nSQL().useDatabase(this._dbName);
152
- const result = await nSQL(this._initData)
159
+ const result = await nSQL(this.resourceName)
153
160
  .query('delete')
154
161
  .where(filter)
155
162
  .exec();
@@ -178,36 +185,45 @@ export class JsonDataService {
178
185
  this._status = 'initializing';
179
186
  this._dbName = 'JsonDataService_DB_' + (dbId++);
180
187
  try {
181
- const model = {
188
+ const table = {
182
189
  name: this.resourceName,
183
- model: {
184
- '*:any': {}
185
- },
186
- indexes: {},
187
- primaryKey: this.primaryKey
190
+ model: {},
191
+ indexes: {}
188
192
  };
193
+ for (const [k, f] of this.resource.dataType.fields.entries()) {
194
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
195
+ const o = table.model[k + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
196
+ if (k === this.primaryKey)
197
+ o.pk = true;
198
+ }
199
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
200
+ const indexes = table.indexes;
189
201
  // Add indexes for sort fields
190
- const searchMethod = this.resource.metadata.methods.search;
191
- if (searchMethod) {
192
- if (searchMethod.sortFields) {
193
- searchMethod.sortFields.forEach(fieldName => {
202
+ const searchResolver = this.resource.metadata.search;
203
+ if (searchResolver) {
204
+ if (searchResolver.sortFields) {
205
+ searchResolver.sortFields.forEach(fieldName => {
194
206
  const f = this.dataType.getField(fieldName);
195
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
196
- model.indexes[fieldName + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
207
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
208
+ const t = dataTypeToSQLType(fieldType, !!f.isArray);
209
+ if (indexingTypes.includes(t))
210
+ indexes[fieldName + ':' + t] = {};
197
211
  });
198
212
  }
199
- if (searchMethod.filters) {
200
- searchMethod.filters.forEach(filter => {
213
+ if (searchResolver.filters) {
214
+ searchResolver.filters.forEach(filter => {
201
215
  const f = this.dataType.getField(filter.field);
202
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
203
- model.indexes[filter.field + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
216
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
217
+ const t = dataTypeToSQLType(fieldType, !!f.isArray);
218
+ if (indexingTypes.includes(t))
219
+ indexes[filter.field + ':' + t] = {};
204
220
  });
205
221
  }
206
222
  }
207
223
  await nSQL().createDatabase({
208
224
  id: this._dbName,
209
225
  version: 3,
210
- tables: [model]
226
+ tables: [table]
211
227
  });
212
228
  this._status = 'initialized';
213
229
  if (this._initData) {
@@ -221,13 +237,14 @@ export class JsonDataService {
221
237
  catch (e) {
222
238
  this._initError = e;
223
239
  this._status = 'error';
240
+ throw e;
224
241
  }
225
242
  }
226
243
  _prepare(query) {
227
- if (query.resource instanceof EntityResource) {
244
+ if (query.resource instanceof CollectionResourceInfo) {
228
245
  if (query.dataType !== this.dataType)
229
246
  throw new TypeError(`Query data type (${query.dataType.name}) ` +
230
- `differs from JsonDataService data type (${this.dataType.name})`);
247
+ `differs from JsonCollectionService data type (${this.dataType.name})`);
231
248
  }
232
249
  switch (query.method) {
233
250
  case 'count': {
@@ -255,7 +272,7 @@ export class JsonDataService {
255
272
  };
256
273
  }
257
274
  case 'get': {
258
- if (query.kind === 'GetInstanceQuery') {
275
+ if (query.kind === 'CollectionGetQuery') {
259
276
  const options = _.omitBy({
260
277
  pick: query.pick,
261
278
  omit: query.omit,
@@ -269,7 +286,7 @@ export class JsonDataService {
269
286
  args: [keyValue, options]
270
287
  };
271
288
  }
272
- if (query.kind === 'GetFieldQuery') {
289
+ if (query.kind === 'FieldGetQuery') {
273
290
  // todo
274
291
  }
275
292
  break;
@@ -348,7 +365,7 @@ export class JsonDataService {
348
365
  }
349
366
  _convertSelect(args) {
350
367
  const result = [];
351
- const document = this.dataType.owner;
368
+ const document = this.dataType.document;
352
369
  const processDataType = (dt, path, pick, omit, include) => {
353
370
  let kl;
354
371
  for (const [k, f] of dt.fields) {
@@ -459,7 +476,7 @@ function dataTypeToSQLType(dataType, isArray) {
459
476
  out = 'object';
460
477
  else {
461
478
  switch (dataType.name) {
462
- case 'booolean':
479
+ case 'boolean':
463
480
  case 'number':
464
481
  case 'string':
465
482
  out = dataType.name;
@@ -467,10 +484,10 @@ function dataTypeToSQLType(dataType, isArray) {
467
484
  case 'integer':
468
485
  out = 'int';
469
486
  break;
470
- case 'date':
471
- case 'date-time':
472
- out = 'date';
473
- break;
487
+ // case 'date': //there is bug in nano-sql.
488
+ // case 'date-time':
489
+ // out = 'date';
490
+ // break;
474
491
  case 'time':
475
492
  out = 'string';
476
493
  break;
@@ -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
+ }
@@ -0,0 +1,92 @@
1
+ import _ from 'lodash';
2
+ import { SingletonResourceInfo } from '@opra/schema';
3
+ export class JsonSingletonService {
4
+ dataType;
5
+ _data;
6
+ constructor(dataType, options) {
7
+ this.dataType = dataType;
8
+ this._data = options?.data;
9
+ }
10
+ async processRequest(ctx) {
11
+ const prepared = this._prepare(ctx.query);
12
+ const fn = this[prepared.method];
13
+ if (!fn)
14
+ throw new TypeError(`Unimplemented method (${prepared.method})`);
15
+ // @ts-ignore
16
+ return fn.apply(this, prepared.args);
17
+ }
18
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
+ get(options) {
20
+ return this._data;
21
+ }
22
+ _prepare(query) {
23
+ if (query.resource instanceof SingletonResourceInfo) {
24
+ if (query.dataType !== this.dataType)
25
+ throw new TypeError(`Query data type (${query.dataType.name}) ` +
26
+ `differs from JsonCollectionService data type (${this.dataType.name})`);
27
+ }
28
+ switch (query.method) {
29
+ case 'create': {
30
+ const options = _.omitBy({
31
+ pick: query.pick,
32
+ omit: query.omit,
33
+ include: query.include
34
+ }, _.isNil);
35
+ const { data } = query;
36
+ return {
37
+ method: query.method,
38
+ values: data,
39
+ options,
40
+ args: [data, options]
41
+ };
42
+ }
43
+ case 'get': {
44
+ if (query.kind === 'CollectionGetQuery') {
45
+ const options = _.omitBy({
46
+ pick: query.pick,
47
+ omit: query.omit,
48
+ include: query.include
49
+ }, _.isNil);
50
+ const keyValue = query.keyValue;
51
+ return {
52
+ method: query.method,
53
+ keyValue,
54
+ options,
55
+ args: [keyValue, options]
56
+ };
57
+ }
58
+ if (query.kind === 'FieldGetQuery') {
59
+ // todo
60
+ }
61
+ break;
62
+ }
63
+ case 'update': {
64
+ const options = _.omitBy({
65
+ pick: query.pick,
66
+ omit: query.omit,
67
+ include: query.include
68
+ }, _.isNil);
69
+ const { data } = query;
70
+ const keyValue = query.keyValue;
71
+ return {
72
+ method: query.method,
73
+ keyValue: query.keyValue,
74
+ values: data,
75
+ options,
76
+ args: [keyValue, data, options]
77
+ };
78
+ }
79
+ case 'delete': {
80
+ const options = {};
81
+ const keyValue = query.keyValue;
82
+ return {
83
+ method: query.method,
84
+ keyValue,
85
+ options,
86
+ args: [keyValue, options]
87
+ };
88
+ }
89
+ }
90
+ throw new Error(`Unimplemented query type "${query.method}"`);
91
+ }
92
+ }
package/esm/types.d.ts CHANGED
@@ -1,8 +1,2 @@
1
- import { Builtin, DeepPickWritable } from 'ts-gems';
2
- export declare type EntityInput<T> = DeepNullableIfPartial<DeepPickWritable<T>>;
3
- export declare type EntityOutput<T> = DeepNullableIfPartial<T>;
4
- export declare type DeepNullableIfPartial<T> = _DeepNullableIfPartial<T>;
5
- declare type _DeepNullableIfPartial<T> = T extends Builtin ? T : T extends Promise<infer U> ? Promise<DeepNullableIfPartial<U>> : T extends (infer U)[] ? DeepNullableIfPartial<U>[] : {
6
- [P in keyof T]?: DeepNullableIfPartial<Exclude<T[P], undefined>> | null;
7
- };
8
- export {};
1
+ import { PartialInput, PartialOutput } from '@opra/common';
2
+ export { PartialInput, PartialOutput };
@@ -1,3 +1,3 @@
1
1
  import { I18n } from '@opra/i18n';
2
- import { OpraAdapter } from '../implementation/adapter.js';
2
+ import { OpraAdapter } from '../adapter/adapter.js';
3
3
  export declare function createI18n(options?: OpraAdapter.I18nOptions): Promise<I18n>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Opra schema package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "postbuild": "npm run _copyi18n && npm run _copy_pkg_files",
19
19
  "_copy_pkg_files": "cp README.md package.json ../../LICENSE ../../build/core && cp ../../package.cjs.json ../../build/core/cjs/package.json",
20
20
  "_copyi18n": "cp -R i18n ../../build/core/i18n",
21
- "lint": "eslint .",
21
+ "lint": "eslint . --max-warnings=0",
22
22
  "test": "jest",
23
23
  "cover": "jest --collect-coverage",
24
24
  "clean": "npm run clean:src && npm run clean:dist && npm run clean:cover",
@@ -27,24 +27,26 @@
27
27
  "clean:cover": "rimraf ../../coverage/core"
28
28
  },
29
29
  "dependencies": {
30
- "@opra/exception": "^0.2.0",
31
- "@opra/i18n": "^0.2.0",
32
- "@opra/optionals": "^0.2.0",
33
- "@opra/schema": "^0.2.0",
34
- "@opra/url": "^0.2.0",
35
30
  "@nano-sql/core": "^2.3.7",
36
- "express": "^4.18.1",
31
+ "@opra/common": "^0.4.0",
32
+ "@opra/exception": "^0.4.0",
33
+ "@opra/i18n": "^0.4.0",
34
+ "@opra/optionals": "^0.4.0",
35
+ "@opra/schema": "^0.4.0",
36
+ "@opra/url": "^0.4.0",
37
+ "axiosist": "^1.0.0",
37
38
  "body-parser": "^1.20.1",
39
+ "express": "^4.18.2",
38
40
  "lodash": "^4.17.21",
39
41
  "putil-isplainobject": "^1.1.4",
40
- "putil-varhelpers": "^1.6.4",
41
42
  "putil-merge": "^3.9.0",
42
- "strict-typed-events": "^2.2.0",
43
- "ts-gems": "^2.2.0"
43
+ "putil-varhelpers": "^1.6.4",
44
+ "strict-typed-events": "^2.3.1",
45
+ "ts-gems": "^2.3.0"
44
46
  },
45
47
  "devDependencies": {
46
- "@types/express": "^4.17.14",
47
- "@faker-js/faker": "^7.5.0"
48
+ "@faker-js/faker": "^7.6.0",
49
+ "@types/express": "^4.17.14"
48
50
  },
49
51
  "type": "module",
50
52
  "types": "esm/index.d.ts",
@@ -79,4 +81,4 @@
79
81
  "http",
80
82
  "web"
81
83
  ]
82
- }
84
+ }