@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
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JsonDataService = void 0;
3
+ exports.JsonCollectionService = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
6
  const putil_merge_1 = tslib_1.__importDefault(require("putil-merge"));
@@ -10,7 +10,8 @@ const schema_1 = require("@opra/schema");
10
10
  const url_1 = require("@opra/url");
11
11
  const path_to_tree_js_1 = require("../utils/path-to-tree.js");
12
12
  let dbId = 1;
13
- class JsonDataService {
13
+ const indexingTypes = ['int', 'float', 'number', 'date', 'string'];
14
+ class JsonCollectionService {
14
15
  resource;
15
16
  _status = '';
16
17
  _initError;
@@ -19,6 +20,8 @@ class JsonDataService {
19
20
  defaultLimit;
20
21
  constructor(resource, options) {
21
22
  this.resource = resource;
23
+ if (this.resource.keyFields.length > 1)
24
+ throw new TypeError('JsonDataService currently doesn\'t support multiple primary keys');
22
25
  this.defaultLimit = options?.defaultLimit ?? 10;
23
26
  this._initData = options?.data;
24
27
  }
@@ -26,7 +29,7 @@ class JsonDataService {
26
29
  return this.resource.dataType;
27
30
  }
28
31
  get primaryKey() {
29
- return this.resource.dataType.primaryKey;
32
+ return this.resource.keyFields[0];
30
33
  }
31
34
  get resourceName() {
32
35
  return this.resource.name;
@@ -59,11 +62,16 @@ class JsonDataService {
59
62
  include: options?.include,
60
63
  });
61
64
  (0, core_1.nSQL)().useDatabase(this._dbName);
62
- const rows = await (0, core_1.nSQL)(this.resourceName)
63
- .query('select', select)
64
- .where([this.primaryKey, '=', keyValue])
65
- .exec();
66
- return unFlatten(rows[0]);
65
+ try {
66
+ const rows = await (0, core_1.nSQL)(this.resourceName)
67
+ .query('select', select)
68
+ .where([this.primaryKey, '=', keyValue])
69
+ .exec();
70
+ return unFlatten(rows[0]);
71
+ }
72
+ catch (e) {
73
+ throw e;
74
+ }
67
75
  }
68
76
  async count(options) {
69
77
  await this._init();
@@ -99,19 +107,19 @@ class JsonDataService {
99
107
  await this._init();
100
108
  const keyValue = data[this.primaryKey];
101
109
  (0, core_1.nSQL)().useDatabase(this._dbName);
102
- const rows = await (0, core_1.nSQL)(this._initData).query('select', [this.primaryKey])
110
+ const rows = await (0, core_1.nSQL)(this.resourceName).query('select', [this.primaryKey])
103
111
  .where([this.primaryKey, '=', keyValue])
104
112
  .exec();
105
113
  if (rows.length)
106
114
  throw new exception_1.ResourceConflictError(this.resourceName, this.primaryKey);
107
- await (0, core_1.nSQL)(this._initData).query('upsert', data)
115
+ await (0, core_1.nSQL)(this.resourceName).query('upsert', data)
108
116
  .exec();
109
117
  return await this.get(keyValue, options);
110
118
  }
111
119
  async update(keyValue, data, options) {
112
120
  await this._init();
113
121
  (0, core_1.nSQL)().useDatabase(this._dbName);
114
- await (0, core_1.nSQL)(this._initData)
122
+ await (0, core_1.nSQL)(this.resourceName)
115
123
  .query('conform rows', (row) => {
116
124
  const out = (0, putil_merge_1.default)({}, row, { deep: true, clone: true });
117
125
  (0, putil_merge_1.default)(out, data, { deep: true });
@@ -119,16 +127,15 @@ class JsonDataService {
119
127
  })
120
128
  .where([this.primaryKey, '=', keyValue])
121
129
  .exec();
122
- await (0, core_1.nSQL)(this._initData).query("rebuild indexes").exec();
130
+ // await nSQL(this.resourceName).query("rebuild indexes").exec();
123
131
  return this.get(keyValue, options);
124
132
  }
125
133
  async updateMany(data, options) {
126
134
  await this._init();
127
135
  const filter = this._convertFilter(options?.filter);
128
- await this._init();
129
136
  (0, core_1.nSQL)().useDatabase(this._dbName);
130
137
  let affected = 0;
131
- await (0, core_1.nSQL)(this._initData)
138
+ await (0, core_1.nSQL)(this.resourceName)
132
139
  .query('conform rows', (row) => {
133
140
  const out = (0, putil_merge_1.default)({}, row, { deep: true, clone: true });
134
141
  (0, putil_merge_1.default)(out, data, { deep: true });
@@ -137,13 +144,13 @@ class JsonDataService {
137
144
  })
138
145
  .where(filter)
139
146
  .exec();
140
- await (0, core_1.nSQL)(this._initData).query("rebuild indexes").exec();
147
+ // await nSQL(this.resourceName).query("rebuild indexes").exec();
141
148
  return affected;
142
149
  }
143
150
  async delete(keyValue) {
144
151
  await this._init();
145
152
  (0, core_1.nSQL)().useDatabase(this._dbName);
146
- const result = await (0, core_1.nSQL)(this._initData)
153
+ const result = await (0, core_1.nSQL)(this.resourceName)
147
154
  .query('delete')
148
155
  .where([this.primaryKey, '=', keyValue])
149
156
  .exec();
@@ -153,7 +160,7 @@ class JsonDataService {
153
160
  await this._init();
154
161
  const filter = this._convertFilter(options?.filter);
155
162
  (0, core_1.nSQL)().useDatabase(this._dbName);
156
- const result = await (0, core_1.nSQL)(this._initData)
163
+ const result = await (0, core_1.nSQL)(this.resourceName)
157
164
  .query('delete')
158
165
  .where(filter)
159
166
  .exec();
@@ -182,36 +189,45 @@ class JsonDataService {
182
189
  this._status = 'initializing';
183
190
  this._dbName = 'JsonDataService_DB_' + (dbId++);
184
191
  try {
185
- const model = {
192
+ const table = {
186
193
  name: this.resourceName,
187
- model: {
188
- '*:any': {}
189
- },
190
- indexes: {},
191
- primaryKey: this.primaryKey
194
+ model: {},
195
+ indexes: {}
192
196
  };
197
+ for (const [k, f] of this.resource.dataType.fields.entries()) {
198
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
199
+ const o = table.model[k + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
200
+ if (k === this.primaryKey)
201
+ o.pk = true;
202
+ }
203
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
204
+ const indexes = table.indexes;
193
205
  // Add indexes for sort fields
194
- const searchMethod = this.resource.metadata.methods.search;
195
- if (searchMethod) {
196
- if (searchMethod.sortFields) {
197
- searchMethod.sortFields.forEach(fieldName => {
206
+ const searchResolver = this.resource.metadata.search;
207
+ if (searchResolver) {
208
+ if (searchResolver.sortFields) {
209
+ searchResolver.sortFields.forEach(fieldName => {
198
210
  const f = this.dataType.getField(fieldName);
199
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
200
- model.indexes[fieldName + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
211
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
212
+ const t = dataTypeToSQLType(fieldType, !!f.isArray);
213
+ if (indexingTypes.includes(t))
214
+ indexes[fieldName + ':' + t] = {};
201
215
  });
202
216
  }
203
- if (searchMethod.filters) {
204
- searchMethod.filters.forEach(filter => {
217
+ if (searchResolver.filters) {
218
+ searchResolver.filters.forEach(filter => {
205
219
  const f = this.dataType.getField(filter.field);
206
- const fieldType = this.resource.owner.getDataType(f.type || 'string');
207
- model.indexes[filter.field + ':' + dataTypeToSQLType(fieldType, !!f.isArray)] = {};
220
+ const fieldType = this.resource.document.getDataType(f.type || 'string');
221
+ const t = dataTypeToSQLType(fieldType, !!f.isArray);
222
+ if (indexingTypes.includes(t))
223
+ indexes[filter.field + ':' + t] = {};
208
224
  });
209
225
  }
210
226
  }
211
227
  await (0, core_1.nSQL)().createDatabase({
212
228
  id: this._dbName,
213
229
  version: 3,
214
- tables: [model]
230
+ tables: [table]
215
231
  });
216
232
  this._status = 'initialized';
217
233
  if (this._initData) {
@@ -225,13 +241,14 @@ class JsonDataService {
225
241
  catch (e) {
226
242
  this._initError = e;
227
243
  this._status = 'error';
244
+ throw e;
228
245
  }
229
246
  }
230
247
  _prepare(query) {
231
- if (query.resource instanceof schema_1.EntityResource) {
248
+ if (query.resource instanceof schema_1.CollectionResourceInfo) {
232
249
  if (query.dataType !== this.dataType)
233
250
  throw new TypeError(`Query data type (${query.dataType.name}) ` +
234
- `differs from JsonDataService data type (${this.dataType.name})`);
251
+ `differs from JsonCollectionService data type (${this.dataType.name})`);
235
252
  }
236
253
  switch (query.method) {
237
254
  case 'count': {
@@ -259,7 +276,7 @@ class JsonDataService {
259
276
  };
260
277
  }
261
278
  case 'get': {
262
- if (query.kind === 'GetInstanceQuery') {
279
+ if (query.kind === 'CollectionGetQuery') {
263
280
  const options = lodash_1.default.omitBy({
264
281
  pick: query.pick,
265
282
  omit: query.omit,
@@ -273,7 +290,7 @@ class JsonDataService {
273
290
  args: [keyValue, options]
274
291
  };
275
292
  }
276
- if (query.kind === 'GetFieldQuery') {
293
+ if (query.kind === 'FieldGetQuery') {
277
294
  // todo
278
295
  }
279
296
  break;
@@ -352,7 +369,7 @@ class JsonDataService {
352
369
  }
353
370
  _convertSelect(args) {
354
371
  const result = [];
355
- const document = this.dataType.owner;
372
+ const document = this.dataType.document;
356
373
  const processDataType = (dt, path, pick, omit, include) => {
357
374
  let kl;
358
375
  for (const [k, f] of dt.fields) {
@@ -439,7 +456,7 @@ class JsonDataService {
439
456
  throw new Error(`${ast.kind} is not implemented yet`);
440
457
  }
441
458
  }
442
- exports.JsonDataService = JsonDataService;
459
+ exports.JsonCollectionService = JsonCollectionService;
443
460
  function unFlatten(input) {
444
461
  if (!input)
445
462
  return;
@@ -464,7 +481,7 @@ function dataTypeToSQLType(dataType, isArray) {
464
481
  out = 'object';
465
482
  else {
466
483
  switch (dataType.name) {
467
- case 'booolean':
484
+ case 'boolean':
468
485
  case 'number':
469
486
  case 'string':
470
487
  out = dataType.name;
@@ -472,10 +489,10 @@ function dataTypeToSQLType(dataType, isArray) {
472
489
  case 'integer':
473
490
  out = 'int';
474
491
  break;
475
- case 'date':
476
- case 'date-time':
477
- out = 'date';
478
- break;
492
+ // case 'date': //there is bug in nano-sql.
493
+ // case 'date-time':
494
+ // out = 'date';
495
+ // break;
479
496
  case 'time':
480
497
  out = 'string';
481
498
  break;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonSingletonService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
+ const schema_1 = require("@opra/schema");
7
+ class JsonSingletonService {
8
+ dataType;
9
+ _data;
10
+ constructor(dataType, options) {
11
+ this.dataType = dataType;
12
+ this._data = options?.data;
13
+ }
14
+ async processRequest(ctx) {
15
+ const prepared = this._prepare(ctx.query);
16
+ const fn = this[prepared.method];
17
+ if (!fn)
18
+ throw new TypeError(`Unimplemented method (${prepared.method})`);
19
+ // @ts-ignore
20
+ return fn.apply(this, prepared.args);
21
+ }
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ get(options) {
24
+ return this._data;
25
+ }
26
+ _prepare(query) {
27
+ if (query.resource instanceof schema_1.SingletonResourceInfo) {
28
+ if (query.dataType !== this.dataType)
29
+ throw new TypeError(`Query data type (${query.dataType.name}) ` +
30
+ `differs from JsonCollectionService data type (${this.dataType.name})`);
31
+ }
32
+ switch (query.method) {
33
+ case 'create': {
34
+ const options = lodash_1.default.omitBy({
35
+ pick: query.pick,
36
+ omit: query.omit,
37
+ include: query.include
38
+ }, lodash_1.default.isNil);
39
+ const { data } = query;
40
+ return {
41
+ method: query.method,
42
+ values: data,
43
+ options,
44
+ args: [data, options]
45
+ };
46
+ }
47
+ case 'get': {
48
+ if (query.kind === 'CollectionGetQuery') {
49
+ const options = lodash_1.default.omitBy({
50
+ pick: query.pick,
51
+ omit: query.omit,
52
+ include: query.include
53
+ }, lodash_1.default.isNil);
54
+ const keyValue = query.keyValue;
55
+ return {
56
+ method: query.method,
57
+ keyValue,
58
+ options,
59
+ args: [keyValue, options]
60
+ };
61
+ }
62
+ if (query.kind === 'FieldGetQuery') {
63
+ // todo
64
+ }
65
+ break;
66
+ }
67
+ case 'update': {
68
+ const options = lodash_1.default.omitBy({
69
+ pick: query.pick,
70
+ omit: query.omit,
71
+ include: query.include
72
+ }, lodash_1.default.isNil);
73
+ const { data } = query;
74
+ const keyValue = query.keyValue;
75
+ return {
76
+ method: query.method,
77
+ keyValue: query.keyValue,
78
+ values: data,
79
+ options,
80
+ args: [keyValue, data, options]
81
+ };
82
+ }
83
+ case 'delete': {
84
+ const options = {};
85
+ const keyValue = query.keyValue;
86
+ return {
87
+ method: query.method,
88
+ keyValue,
89
+ options,
90
+ args: [keyValue, options]
91
+ };
92
+ }
93
+ }
94
+ throw new Error(`Unimplemented query type "${query.method}"`);
95
+ }
96
+ }
97
+ exports.JsonSingletonService = JsonSingletonService;
@@ -1,6 +1,7 @@
1
+ import { ResponsiveMap } from '@opra/common';
1
2
  import { OpraException } from '@opra/exception';
2
3
  import { FallbackLng, I18n, LanguageResource } from '@opra/i18n';
3
- import { OpraService } from '@opra/schema';
4
+ import { CollectionGetQuery, CollectionResourceInfo, ComplexType, DataType, FieldGetQuery, OpraDocument, ResourceInfo, SingletonGetQuery, SingletonResourceInfo } from '@opra/schema';
4
5
  import { IExecutionContext } from '../interfaces/execution-context.interface.js';
5
6
  import { QueryContext } from './query-context.js';
6
7
  export declare namespace OpraAdapter {
@@ -41,17 +42,24 @@ export declare namespace OpraAdapter {
41
42
  }
42
43
  }
43
44
  export declare abstract class OpraAdapter<TExecutionContext extends IExecutionContext> {
44
- readonly service: OpraService;
45
- readonly i18n: I18n;
46
- readonly userContextResolver?: OpraAdapter.UserContextResolver;
47
- constructor(service: OpraService, options?: Omit<OpraAdapter.Options, 'i18n'> & {
48
- i18n: I18n;
49
- });
45
+ readonly document: OpraDocument;
46
+ protected i18n: I18n;
47
+ protected userContextResolver?: OpraAdapter.UserContextResolver;
48
+ protected _internalResources: ResponsiveMap<string, ResourceInfo>;
49
+ constructor(document: OpraDocument);
50
50
  protected abstract prepareRequests(executionContext: TExecutionContext): QueryContext[];
51
51
  protected abstract sendResponse(executionContext: TExecutionContext, queryContexts: QueryContext[]): Promise<void>;
52
52
  protected abstract sendError(executionContext: TExecutionContext, error: OpraException): Promise<void>;
53
53
  protected abstract isBatch(executionContext: TExecutionContext): boolean;
54
54
  protected handler(executionContext: TExecutionContext): Promise<void>;
55
- protected _getSchemaExecute(ctx: QueryContext): Promise<void>;
56
- protected static initI18n(options?: OpraAdapter.Options): Promise<I18n>;
55
+ protected _resourcePrepare(resource: ResourceInfo, context: QueryContext): Promise<void>;
56
+ protected _resourceExecute(document: OpraDocument, resource: ResourceInfo, context: QueryContext): Promise<void>;
57
+ protected _init(options?: OpraAdapter.Options): Promise<void>;
58
+ protected _collectionResourceExecute(document: OpraDocument, resource: CollectionResourceInfo, context: QueryContext): Promise<any>;
59
+ protected _singletonResourceExecute(document: OpraDocument, resource: SingletonResourceInfo, context: QueryContext): Promise<any>;
60
+ protected _pathWalkThrough(query: CollectionGetQuery | SingletonGetQuery | FieldGetQuery, dataType: ComplexType, value: any, parentPath: string): Promise<{
61
+ value?: any;
62
+ dataType?: DataType;
63
+ path: string;
64
+ }>;
57
65
  }