@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.
- package/cjs/adapter/adapter.js +319 -0
- package/cjs/{implementation → adapter}/express-adapter.js +3 -6
- package/cjs/adapter/http-adapter.js +242 -0
- package/cjs/adapter/metadata-resource.js +23 -0
- package/cjs/{implementation → adapter}/query-context.js +1 -1
- package/cjs/enums/http-headers.enum.js +1 -1
- package/cjs/{implementation → helpers}/headers-map.js +2 -2
- package/cjs/index.js +7 -6
- package/cjs/interfaces/resource.interface.js +2 -0
- package/cjs/services/{json-data-service.js → json-collection-service.js} +62 -45
- package/cjs/services/json-singleton-service.js +97 -0
- package/esm/{implementation → adapter}/adapter.d.ts +17 -9
- package/esm/adapter/adapter.js +315 -0
- package/esm/{implementation → adapter}/express-adapter.d.ts +2 -2
- package/esm/{implementation → adapter}/express-adapter.js +3 -6
- package/esm/{implementation → adapter}/http-adapter.d.ts +2 -3
- package/esm/adapter/http-adapter.js +238 -0
- package/esm/adapter/metadata-resource.d.ts +8 -0
- package/esm/adapter/metadata-resource.js +20 -0
- package/esm/{implementation → adapter}/query-context.d.ts +6 -6
- package/esm/{implementation → adapter}/query-context.js +1 -1
- package/esm/enums/http-headers.enum.d.ts +1 -1
- package/esm/enums/http-headers.enum.js +1 -1
- package/esm/{implementation → helpers}/headers-map.d.ts +1 -1
- package/esm/{implementation → helpers}/headers-map.js +1 -1
- package/esm/index.d.ts +7 -6
- package/esm/index.js +7 -6
- package/esm/interfaces/resource.interface.d.ts +22 -0
- package/esm/interfaces/resource.interface.js +1 -0
- package/esm/services/{json-data-service.d.ts → json-collection-service.d.ts} +18 -19
- package/esm/services/{json-data-service.js → json-collection-service.js} +61 -44
- package/esm/services/json-singleton-service.d.ts +39 -0
- package/esm/services/json-singleton-service.js +92 -0
- package/esm/types.d.ts +2 -8
- package/esm/utils/create-i18n.d.ts +1 -1
- package/package.json +16 -14
- package/cjs/implementation/adapter-utils/entity-resource-execute.util.js +0 -86
- package/cjs/implementation/adapter-utils/resource-execute.util.js +0 -11
- package/cjs/implementation/adapter-utils/resource-prepare.util.js +0 -11
- package/cjs/implementation/adapter.js +0 -130
- package/cjs/implementation/http-adapter.js +0 -253
- package/cjs/interfaces/entity-service.interface.js +0 -30
- package/esm/implementation/adapter-utils/entity-resource-execute.util.d.ts +0 -3
- package/esm/implementation/adapter-utils/entity-resource-execute.util.js +0 -82
- package/esm/implementation/adapter-utils/resource-execute.util.d.ts +0 -3
- package/esm/implementation/adapter-utils/resource-execute.util.js +0 -7
- package/esm/implementation/adapter-utils/resource-prepare.util.d.ts +0 -3
- package/esm/implementation/adapter-utils/resource-prepare.util.js +0 -7
- package/esm/implementation/adapter.js +0 -126
- package/esm/implementation/http-adapter.js +0 -249
- package/esm/interfaces/entity-service.interface.d.ts +0 -19
- 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["
|
|
9
|
+
HttpHeaders["X_Opra_DataType"] = "X-Opra-DataType";
|
|
10
10
|
HttpHeaders["X_Opra_Count"] = "X-Opra-Count";
|
|
11
11
|
/* *** Authentication *** */
|
|
12
12
|
/**
|
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/
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
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-
|
|
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/
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
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-
|
|
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 {
|
|
2
|
+
import { CollectionResourceInfo, ComplexType, OpraQuery, OpraSchema } from '@opra/schema';
|
|
3
3
|
import { Expression } from '@opra/url';
|
|
4
|
-
import { QueryContext } from '../
|
|
5
|
-
import {
|
|
6
|
-
|
|
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
|
|
13
|
-
readonly resource:
|
|
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:
|
|
20
|
-
get dataType():
|
|
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?:
|
|
26
|
-
count(options?:
|
|
27
|
-
search(options?:
|
|
28
|
-
create(data:
|
|
29
|
-
update(keyValue: any, data:
|
|
30
|
-
updateMany(data:
|
|
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?:
|
|
31
|
+
deleteMany(options?: JsonCollectionService.DeleteManyOptions): Promise<number>;
|
|
33
32
|
private _waitInitializing;
|
|
34
33
|
protected _init(): Promise<void>;
|
|
35
|
-
protected _prepare(query:
|
|
36
|
-
method: OpraSchema.
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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,36 +185,45 @@ 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.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
|
|
191
|
-
if (
|
|
192
|
-
if (
|
|
193
|
-
|
|
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.
|
|
196
|
-
|
|
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 (
|
|
200
|
-
|
|
213
|
+
if (searchResolver.filters) {
|
|
214
|
+
searchResolver.filters.forEach(filter => {
|
|
201
215
|
const f = this.dataType.getField(filter.field);
|
|
202
|
-
const fieldType = this.resource.
|
|
203
|
-
|
|
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: [
|
|
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
|
|
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
|
|
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 === '
|
|
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 === '
|
|
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.
|
|
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 '
|
|
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;
|
|
@@ -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 {
|
|
2
|
-
export
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/core",
|
|
3
|
-
"version": "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
|
-
"
|
|
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
|
-
"
|
|
43
|
-
"
|
|
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
|
-
"@
|
|
47
|
-
"@
|
|
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
|
+
}
|