@opra/core 0.2.0 → 0.3.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.
- package/cjs/index.js +1 -1
- package/cjs/services/{json-data-service.js → json-collection-service.js} +49 -32
- package/esm/implementation/adapter-utils/entity-resource-execute.util.d.ts +2 -2
- package/esm/implementation/adapter-utils/resource-execute.util.d.ts +2 -2
- package/esm/implementation/adapter.d.ts +3 -3
- package/esm/implementation/express-adapter.d.ts +2 -2
- package/esm/implementation/query-context.d.ts +2 -2
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/interfaces/entity-service.interface.d.ts +1 -1
- package/esm/services/{json-data-service.d.ts → json-collection-service.d.ts} +13 -13
- package/esm/services/{json-data-service.js → json-collection-service.js} +47 -30
- package/package.json +7 -7
package/cjs/index.js
CHANGED
|
@@ -11,4 +11,4 @@ tslib_1.__exportStar(require("./implementation/adapter.js"), exports);
|
|
|
11
11
|
tslib_1.__exportStar(require("./implementation/http-adapter.js"), exports);
|
|
12
12
|
tslib_1.__exportStar(require("./implementation/express-adapter.js"), exports);
|
|
13
13
|
tslib_1.__exportStar(require("./services/data-service.js"), exports);
|
|
14
|
-
tslib_1.__exportStar(require("./services/json-
|
|
14
|
+
tslib_1.__exportStar(require("./services/json-collection-service.js"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
163
|
+
const result = await (0, core_1.nSQL)(this.resourceName)
|
|
157
164
|
.query('delete')
|
|
158
165
|
.where(filter)
|
|
159
166
|
.exec();
|
|
@@ -182,14 +189,19 @@ class JsonDataService {
|
|
|
182
189
|
this._status = 'initializing';
|
|
183
190
|
this._dbName = 'JsonDataService_DB_' + (dbId++);
|
|
184
191
|
try {
|
|
185
|
-
const
|
|
192
|
+
const table = {
|
|
186
193
|
name: this.resourceName,
|
|
187
|
-
model: {
|
|
188
|
-
|
|
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.owner.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
206
|
const searchMethod = this.resource.metadata.methods.search;
|
|
195
207
|
if (searchMethod) {
|
|
@@ -197,21 +209,25 @@ class JsonDataService {
|
|
|
197
209
|
searchMethod.sortFields.forEach(fieldName => {
|
|
198
210
|
const f = this.dataType.getField(fieldName);
|
|
199
211
|
const fieldType = this.resource.owner.getDataType(f.type || 'string');
|
|
200
|
-
|
|
212
|
+
const t = dataTypeToSQLType(fieldType, !!f.isArray);
|
|
213
|
+
if (indexingTypes.includes(t))
|
|
214
|
+
indexes[fieldName + ':' + t] = {};
|
|
201
215
|
});
|
|
202
216
|
}
|
|
203
217
|
if (searchMethod.filters) {
|
|
204
218
|
searchMethod.filters.forEach(filter => {
|
|
205
219
|
const f = this.dataType.getField(filter.field);
|
|
206
220
|
const fieldType = this.resource.owner.getDataType(f.type || 'string');
|
|
207
|
-
|
|
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: [
|
|
230
|
+
tables: [table]
|
|
215
231
|
});
|
|
216
232
|
this._status = 'initialized';
|
|
217
233
|
if (this._initData) {
|
|
@@ -225,6 +241,7 @@ 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) {
|
|
@@ -439,7 +456,7 @@ class JsonDataService {
|
|
|
439
456
|
throw new Error(`${ast.kind} is not implemented yet`);
|
|
440
457
|
}
|
|
441
458
|
}
|
|
442
|
-
exports.
|
|
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 '
|
|
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
|
-
|
|
478
|
-
|
|
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;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { EntityResource,
|
|
1
|
+
import { EntityResource, OpraApi } from '@opra/schema';
|
|
2
2
|
import { QueryContext } from '../query-context.js';
|
|
3
|
-
export declare function entityResourceExecute(service:
|
|
3
|
+
export declare function entityResourceExecute(service: OpraApi, resource: EntityResource, context: QueryContext): Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OpraApi, OpraResource } from '@opra/schema';
|
|
2
2
|
import { QueryContext } from '../query-context.js';
|
|
3
|
-
export declare function resourceExecute(service:
|
|
3
|
+
export declare function resourceExecute(service: OpraApi, resource: OpraResource, context: QueryContext): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OpraException } from '@opra/exception';
|
|
2
2
|
import { FallbackLng, I18n, LanguageResource } from '@opra/i18n';
|
|
3
|
-
import {
|
|
3
|
+
import { OpraApi } from '@opra/schema';
|
|
4
4
|
import { IExecutionContext } from '../interfaces/execution-context.interface.js';
|
|
5
5
|
import { QueryContext } from './query-context.js';
|
|
6
6
|
export declare namespace OpraAdapter {
|
|
@@ -41,10 +41,10 @@ export declare namespace OpraAdapter {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
export declare abstract class OpraAdapter<TExecutionContext extends IExecutionContext> {
|
|
44
|
-
readonly service:
|
|
44
|
+
readonly service: OpraApi;
|
|
45
45
|
readonly i18n: I18n;
|
|
46
46
|
readonly userContextResolver?: OpraAdapter.UserContextResolver;
|
|
47
|
-
constructor(service:
|
|
47
|
+
constructor(service: OpraApi, options?: Omit<OpraAdapter.Options, 'i18n'> & {
|
|
48
48
|
i18n: I18n;
|
|
49
49
|
});
|
|
50
50
|
protected abstract prepareRequests(executionContext: TExecutionContext): QueryContext[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Application } from 'express';
|
|
2
|
-
import {
|
|
2
|
+
import { OpraApi } from '@opra/schema';
|
|
3
3
|
import type { IHttpExecutionContext } from '../interfaces/execution-context.interface';
|
|
4
4
|
import { OpraHttpAdapter } from './http-adapter.js';
|
|
5
5
|
export declare namespace OpraExpressAdapter {
|
|
@@ -7,5 +7,5 @@ export declare namespace OpraExpressAdapter {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
export declare class OpraExpressAdapter extends OpraHttpAdapter<IHttpExecutionContext> {
|
|
10
|
-
static init(app: Application, service:
|
|
10
|
+
static init(app: Application, service: OpraApi, options?: OpraExpressAdapter.Options): Promise<OpraExpressAdapter>;
|
|
11
11
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { OpraException } from '@opra/exception';
|
|
2
|
-
import { OpraAnyQuery,
|
|
2
|
+
import { OpraAnyQuery, OpraApi } from '@opra/schema';
|
|
3
3
|
import { SearchParams } from '@opra/url';
|
|
4
4
|
import { HttpStatus } from '../enums/index.js';
|
|
5
5
|
import { ContextType, IExecutionContext, IHttpExecutionContext } from '../interfaces/execution-context.interface.js';
|
|
6
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:
|
|
9
|
+
readonly service: OpraApi;
|
|
10
10
|
readonly executionContext: IExecutionContext;
|
|
11
11
|
readonly query: OpraAnyQuery;
|
|
12
12
|
readonly params: SearchParams;
|
package/esm/index.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export * from './implementation/adapter.js';
|
|
|
8
8
|
export * from './implementation/http-adapter.js';
|
|
9
9
|
export * from './implementation/express-adapter.js';
|
|
10
10
|
export * from './services/data-service.js';
|
|
11
|
-
export * from './services/json-
|
|
11
|
+
export * from './services/json-collection-service.js';
|
package/esm/index.js
CHANGED
|
@@ -8,4 +8,4 @@ export * from './implementation/adapter.js';
|
|
|
8
8
|
export * from './implementation/http-adapter.js';
|
|
9
9
|
export * from './implementation/express-adapter.js';
|
|
10
10
|
export * from './services/data-service.js';
|
|
11
|
-
export * from './services/json-
|
|
11
|
+
export * from './services/json-collection-service.js';
|
|
@@ -14,6 +14,6 @@ export declare abstract class EntityResourceController<T, TOutput = EntityOutput
|
|
|
14
14
|
updateMany(ctx: QueryContext): Promise<Maybe<number>>;
|
|
15
15
|
delete(ctx: QueryContext): Promise<Maybe<boolean | number>>;
|
|
16
16
|
deleteMany(ctx: QueryContext): Promise<Maybe<number>>;
|
|
17
|
-
|
|
17
|
+
init?(service: OpraResource): void | Promise<void>;
|
|
18
18
|
abstract getService(ctx: QueryContext): IEntityService | Promise<IEntityService>;
|
|
19
19
|
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
import { Maybe } from 'ts-gems';
|
|
2
|
-
import {
|
|
2
|
+
import { ComplexType, EntityResource, OpraAnyQuery, OpraSchema } from '@opra/schema';
|
|
3
3
|
import { Expression } from '@opra/url';
|
|
4
4
|
import { QueryContext } from '../implementation/query-context.js';
|
|
5
5
|
import { IEntityService } from '../interfaces/entity-service.interface.js';
|
|
6
6
|
import { EntityInput, EntityOutput } from '../types.js';
|
|
7
|
-
export interface
|
|
7
|
+
export interface JsonCollectionServiceOptions {
|
|
8
8
|
resourceName?: string;
|
|
9
9
|
defaultLimit?: number;
|
|
10
10
|
data?: any[];
|
|
11
11
|
}
|
|
12
|
-
export declare class
|
|
12
|
+
export declare class JsonCollectionService<T, TOutput = EntityOutput<T>> implements IEntityService {
|
|
13
13
|
readonly resource: EntityResource;
|
|
14
14
|
private _status;
|
|
15
15
|
private _initError;
|
|
16
16
|
private _dbName;
|
|
17
17
|
private _initData?;
|
|
18
18
|
defaultLimit: number;
|
|
19
|
-
constructor(resource: EntityResource, options?:
|
|
20
|
-
get dataType():
|
|
19
|
+
constructor(resource: EntityResource, options?: JsonCollectionServiceOptions);
|
|
20
|
+
get dataType(): ComplexType;
|
|
21
21
|
get primaryKey(): string;
|
|
22
22
|
get resourceName(): string;
|
|
23
23
|
close(): Promise<void>;
|
|
24
24
|
processRequest(ctx: QueryContext): Promise<any>;
|
|
25
|
-
get(keyValue: any, options?:
|
|
26
|
-
count(options?:
|
|
27
|
-
search(options?:
|
|
28
|
-
create(data: EntityInput<T>, options?:
|
|
29
|
-
update(keyValue: any, data: EntityInput<T>, options?:
|
|
30
|
-
updateMany(data: EntityInput<T>, options?:
|
|
25
|
+
get(keyValue: any, options?: JsonCollectionService.GetOptions): Promise<Maybe<TOutput>>;
|
|
26
|
+
count(options?: JsonCollectionService.SearchOptions): Promise<number>;
|
|
27
|
+
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>;
|
|
31
31
|
delete(keyValue: any): Promise<boolean>;
|
|
32
|
-
deleteMany(options?:
|
|
32
|
+
deleteMany(options?: JsonCollectionService.DeleteManyOptions): Promise<number>;
|
|
33
33
|
private _waitInitializing;
|
|
34
34
|
protected _init(): Promise<void>;
|
|
35
35
|
protected _prepare(query: OpraAnyQuery): {
|
|
@@ -46,7 +46,7 @@ export declare class JsonDataService<T, TOutput = EntityOutput<T>> implements IE
|
|
|
46
46
|
}): string[];
|
|
47
47
|
protected _convertFilter(str: string | Expression | undefined | {}): any;
|
|
48
48
|
}
|
|
49
|
-
export declare namespace
|
|
49
|
+
export declare namespace JsonCollectionService {
|
|
50
50
|
type CountOptions = {
|
|
51
51
|
filter?: string | Expression | {};
|
|
52
52
|
};
|
|
@@ -6,7 +6,8 @@ import { ComplexType, EntityResource } 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
|
-
|
|
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.
|
|
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
|
-
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
159
|
+
const result = await nSQL(this.resourceName)
|
|
153
160
|
.query('delete')
|
|
154
161
|
.where(filter)
|
|
155
162
|
.exec();
|
|
@@ -178,14 +185,19 @@ export class JsonDataService {
|
|
|
178
185
|
this._status = 'initializing';
|
|
179
186
|
this._dbName = 'JsonDataService_DB_' + (dbId++);
|
|
180
187
|
try {
|
|
181
|
-
const
|
|
188
|
+
const table = {
|
|
182
189
|
name: this.resourceName,
|
|
183
|
-
model: {
|
|
184
|
-
|
|
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.owner.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
202
|
const searchMethod = this.resource.metadata.methods.search;
|
|
191
203
|
if (searchMethod) {
|
|
@@ -193,21 +205,25 @@ export class JsonDataService {
|
|
|
193
205
|
searchMethod.sortFields.forEach(fieldName => {
|
|
194
206
|
const f = this.dataType.getField(fieldName);
|
|
195
207
|
const fieldType = this.resource.owner.getDataType(f.type || 'string');
|
|
196
|
-
|
|
208
|
+
const t = dataTypeToSQLType(fieldType, !!f.isArray);
|
|
209
|
+
if (indexingTypes.includes(t))
|
|
210
|
+
indexes[fieldName + ':' + t] = {};
|
|
197
211
|
});
|
|
198
212
|
}
|
|
199
213
|
if (searchMethod.filters) {
|
|
200
214
|
searchMethod.filters.forEach(filter => {
|
|
201
215
|
const f = this.dataType.getField(filter.field);
|
|
202
216
|
const fieldType = this.resource.owner.getDataType(f.type || 'string');
|
|
203
|
-
|
|
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: [
|
|
226
|
+
tables: [table]
|
|
211
227
|
});
|
|
212
228
|
this._status = 'initialized';
|
|
213
229
|
if (this._initData) {
|
|
@@ -221,6 +237,7 @@ 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) {
|
|
@@ -459,7 +476,7 @@ function dataTypeToSQLType(dataType, isArray) {
|
|
|
459
476
|
out = 'object';
|
|
460
477
|
else {
|
|
461
478
|
switch (dataType.name) {
|
|
462
|
-
case '
|
|
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
|
-
|
|
473
|
-
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Opra schema package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"clean:cover": "rimraf ../../coverage/core"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@opra/exception": "^0.
|
|
31
|
-
"@opra/i18n": "^0.
|
|
32
|
-
"@opra/optionals": "^0.
|
|
33
|
-
"@opra/schema": "^0.
|
|
34
|
-
"@opra/url": "^0.
|
|
30
|
+
"@opra/exception": "^0.3.0",
|
|
31
|
+
"@opra/i18n": "^0.3.0",
|
|
32
|
+
"@opra/optionals": "^0.3.0",
|
|
33
|
+
"@opra/schema": "^0.3.0",
|
|
34
|
+
"@opra/url": "^0.3.0",
|
|
35
35
|
"@nano-sql/core": "^2.3.7",
|
|
36
36
|
"express": "^4.18.1",
|
|
37
37
|
"body-parser": "^1.20.1",
|
|
@@ -79,4 +79,4 @@
|
|
|
79
79
|
"http",
|
|
80
80
|
"web"
|
|
81
81
|
]
|
|
82
|
-
}
|
|
82
|
+
}
|