@naiv/flazy-api 0.0.1
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/LICENSE +21 -0
- package/README.md +202 -0
- package/dist/build-from-api.d.ts +5 -0
- package/dist/build-from-api.js +110 -0
- package/dist/build-from-enum.d.ts +4 -0
- package/dist/build-from-enum.js +24 -0
- package/dist/build-from-schema.d.ts +24 -0
- package/dist/build-from-schema.js +207 -0
- package/dist/build-from-table.d.ts +10 -0
- package/dist/build-from-table.js +253 -0
- package/dist/cmd-generate.d.ts +1 -0
- package/dist/cmd-generate.js +46 -0
- package/dist/cmd-run.d.ts +1 -0
- package/dist/cmd-run.js +34 -0
- package/dist/compile-folter.d.ts +4 -0
- package/dist/compile-folter.js +70 -0
- package/dist/data-types.d.ts +11 -0
- package/dist/data-types.js +2 -0
- package/dist/exec.d.ts +2 -0
- package/dist/exec.js +16 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +37 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.js +192 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ADF Language. https://adf-lang.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
### How to test
|
|
2
|
+
|
|
3
|
+
0. Build project (on this project)
|
|
4
|
+
```bash
|
|
5
|
+
npm run build
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
build action will create `codegen-nodejs-typeorm` binary and accessible from terminal.
|
|
9
|
+
|
|
10
|
+
1. Create testing folder
|
|
11
|
+
```bash
|
|
12
|
+
mkdir naiv-test-server
|
|
13
|
+
cd naiv-test-server
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. Init Typescript Project
|
|
17
|
+
```bash
|
|
18
|
+
npm init -y
|
|
19
|
+
npm install --save-dev typescript
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
3. Modify `package.json` script
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
"scripts": {
|
|
26
|
+
"typeorm": "typeorm-ts-node-commonjs",
|
|
27
|
+
"generate-migration": "npm run typeorm migration:generate -- $1 -d ./data-source.ts",
|
|
28
|
+
"migrate": "npm run typeorm migration:run -- -d ./data-source.ts",
|
|
29
|
+
"codegen": "codegen-nodejs-typeorm -d design -o types",
|
|
30
|
+
"codegen-init": "npx ts-node ./generate-initial-api.ts",
|
|
31
|
+
"build": "rm -rf dist && tsc",
|
|
32
|
+
"start": "node dist",
|
|
33
|
+
"dev": "npm run build && npm start"
|
|
34
|
+
},
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
4. Create TS-Config file
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
// Visit https://aka.ms/tsconfig to read more about this file
|
|
41
|
+
"compilerOptions": {
|
|
42
|
+
|
|
43
|
+
// Environment Settings
|
|
44
|
+
// See also https://aka.ms/tsconfig/module
|
|
45
|
+
"module": "nodenext",
|
|
46
|
+
"target": "esnext",
|
|
47
|
+
"types": ["node"],
|
|
48
|
+
|
|
49
|
+
// Stricter Typechecking Options
|
|
50
|
+
"noUncheckedIndexedAccess": true,
|
|
51
|
+
"exactOptionalPropertyTypes": true,
|
|
52
|
+
|
|
53
|
+
// Recommended Options
|
|
54
|
+
"strict": true,
|
|
55
|
+
"jsx": "react-jsx",
|
|
56
|
+
"verbatimModuleSyntax": false,
|
|
57
|
+
"isolatedModules": true,
|
|
58
|
+
"noUncheckedSideEffectImports": true,
|
|
59
|
+
"moduleDetection": "force",
|
|
60
|
+
"skipLibCheck": true,
|
|
61
|
+
"experimentalDecorators": true,
|
|
62
|
+
"emitDecoratorMetadata": true,
|
|
63
|
+
"outDir": "dist"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
5. Install dependency
|
|
69
|
+
```bash
|
|
70
|
+
npm install --save express cors class-validator class-transformer
|
|
71
|
+
npm install --save-dev @types/express @types/cors
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
6. Create `generate-initial-api.ts`
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import * as fs from 'fs';
|
|
78
|
+
import * as path from 'path';
|
|
79
|
+
|
|
80
|
+
function getAllTsFiles(dir: string): string[] {
|
|
81
|
+
const files = fs.readdirSync(dir, { withFileTypes: true });
|
|
82
|
+
const tsFiles: string[] = [];
|
|
83
|
+
|
|
84
|
+
for (const file of files) {
|
|
85
|
+
if (file.isFile() && file.name.endsWith('.ts')) {
|
|
86
|
+
tsFiles.push(file.name);
|
|
87
|
+
const filePath = path.resolve(`./implementation/${file.name}`);
|
|
88
|
+
if (fs.existsSync(filePath)) {
|
|
89
|
+
console.log(`✅ File already exists: ${filePath}`);
|
|
90
|
+
} else {
|
|
91
|
+
const [fn] = file.name.split('.');
|
|
92
|
+
const prefix = fn?.slice(0, 2);
|
|
93
|
+
const only_name = fn?.slice(2);
|
|
94
|
+
const is_streaming = prefix == 'S_';
|
|
95
|
+
fs.writeFileSync(filePath, `\
|
|
96
|
+
import { ${prefix}${only_name} } from "../types/api/${prefix}${only_name}";
|
|
97
|
+
|
|
98
|
+
export const ${prefix?.toLowerCase()}${only_name}: ${prefix}${only_name} = async ${is_streaming ? '(req, stream, res)' : '(req, res)'} => {
|
|
99
|
+
throw new Error('Implement this');
|
|
100
|
+
}
|
|
101
|
+
`, 'utf8');
|
|
102
|
+
console.log(`📝 File created: ${filePath}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return tsFiles;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(getAllTsFiles('./types/api'));
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
7. Create simple api design `design/api.naiv`
|
|
114
|
+
```
|
|
115
|
+
schema Z {
|
|
116
|
+
data string required
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
api get /test-streaming {
|
|
120
|
+
alias testX
|
|
121
|
+
query {
|
|
122
|
+
q string
|
|
123
|
+
}
|
|
124
|
+
return stream of string required
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
api get /common-api {
|
|
128
|
+
alias getY
|
|
129
|
+
query {
|
|
130
|
+
limit number
|
|
131
|
+
offset number
|
|
132
|
+
}
|
|
133
|
+
return array string required
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
8. Generate code
|
|
138
|
+
```bash
|
|
139
|
+
npm run codegen
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
9. Generate code-stub
|
|
143
|
+
```bash
|
|
144
|
+
npm run codegen-init
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
10. Copy `server.ts` from this project to `naiv-test-server` project
|
|
148
|
+
|
|
149
|
+
11. Create `index.ts`
|
|
150
|
+
```typescript
|
|
151
|
+
import path from 'path';
|
|
152
|
+
import { Server } from './server';
|
|
153
|
+
|
|
154
|
+
const server = new Server();
|
|
155
|
+
server.run({
|
|
156
|
+
port: +(process.env.PORT ?? 9415),
|
|
157
|
+
types_path: path.resolve(__dirname, 'types'),
|
|
158
|
+
implementation_path: path.resolve(__dirname, 'implementation'),
|
|
159
|
+
async beforeStart() {
|
|
160
|
+
console.log('before start script.')
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
12. Implement logic
|
|
166
|
+
```typescript
|
|
167
|
+
import { S_testX } from "../types/api/S_testX";
|
|
168
|
+
|
|
169
|
+
export const s_testX: S_testX = async (req, stream, res) => {
|
|
170
|
+
stream(req.query.q ?? 'no query');
|
|
171
|
+
stream('\n');
|
|
172
|
+
stream('aaa\n');
|
|
173
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
174
|
+
stream('ccc\n');
|
|
175
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
176
|
+
stream('bbb\n');
|
|
177
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
178
|
+
stream('eee\n');
|
|
179
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
180
|
+
stream('ddd\n');
|
|
181
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
182
|
+
stream('fff\n');
|
|
183
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { T_getY } from "../types/api/T_getY";
|
|
189
|
+
|
|
190
|
+
export const t_getY: T_getY = async (req, res) => {
|
|
191
|
+
return ['nice'];
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
13. `curl` testing
|
|
196
|
+
```bash
|
|
197
|
+
curl localhost:9415/test-streaming?q=lorem-ipsum -N
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
curl localhost:9415/common-api
|
|
202
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { NVAPI } from "@naiv/core/build/semantic-checker/check_api";
|
|
2
|
+
import { ItemOutput } from "./data-types";
|
|
3
|
+
import { NVSchema } from "@naiv/core/build/semantic-checker/check_schema";
|
|
4
|
+
export declare function getAPIFileName(api_alias: string, api: NVAPI, extension?: string): string;
|
|
5
|
+
export declare function buildFromAPI(api: NVAPI, list_schema: NVSchema[]): ItemOutput;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAPIFileName = getAPIFileName;
|
|
7
|
+
exports.buildFromAPI = buildFromAPI;
|
|
8
|
+
const build_from_schema_1 = require("./build-from-schema");
|
|
9
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
10
|
+
function getAPIFileName(api_alias, api, extension) {
|
|
11
|
+
const is_streaming = api.data.return_type.kind === 'stream';
|
|
12
|
+
return `./api/${is_streaming ? 'S_' : 'T_'}${api_alias}${extension !== null && extension !== void 0 ? extension : ''}`;
|
|
13
|
+
}
|
|
14
|
+
function buildFromAPI(api, list_schema) {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
16
|
+
const is_streaming = api.data.return_type.kind === 'stream';
|
|
17
|
+
const prefix = is_streaming ? 'S_' : 'T_';
|
|
18
|
+
if (!api.data.alias) {
|
|
19
|
+
throw new Error(`no api alias`);
|
|
20
|
+
}
|
|
21
|
+
let header_schema;
|
|
22
|
+
if (((_b = (_a = api.data.headers) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
23
|
+
const s = {
|
|
24
|
+
name: `${prefix}${api.data.alias}_headers`,
|
|
25
|
+
items: (_c = api.data.headers) !== null && _c !== void 0 ? _c : []
|
|
26
|
+
};
|
|
27
|
+
header_schema = (0, build_from_schema_1.getSchemaContent)(s, list_schema);
|
|
28
|
+
}
|
|
29
|
+
let query_schema;
|
|
30
|
+
if (((_e = (_d = api.data.query) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0) > 0) {
|
|
31
|
+
const s = {
|
|
32
|
+
name: `${prefix}${api.data.alias}_query`,
|
|
33
|
+
items: (_f = api.data.query) !== null && _f !== void 0 ? _f : []
|
|
34
|
+
};
|
|
35
|
+
query_schema = (0, build_from_schema_1.getSchemaContent)(s, list_schema);
|
|
36
|
+
}
|
|
37
|
+
let path_schema;
|
|
38
|
+
if (((_h = (_g = api.data.path) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0) > 0) {
|
|
39
|
+
const s = {
|
|
40
|
+
name: `${prefix}${api.data.alias}_path`,
|
|
41
|
+
items: (_j = api.data.path) !== null && _j !== void 0 ? _j : []
|
|
42
|
+
};
|
|
43
|
+
path_schema = (0, build_from_schema_1.getSchemaContent)(s, list_schema);
|
|
44
|
+
}
|
|
45
|
+
let body_schema;
|
|
46
|
+
if (((_l = (_k = api.data.body) === null || _k === void 0 ? void 0 : _k.length) !== null && _l !== void 0 ? _l : 0) > 0) {
|
|
47
|
+
const s = {
|
|
48
|
+
name: `${prefix}${api.data.alias}_body`,
|
|
49
|
+
items: (_m = api.data.body) !== null && _m !== void 0 ? _m : []
|
|
50
|
+
};
|
|
51
|
+
body_schema = (0, build_from_schema_1.getSchemaContent)(s, list_schema);
|
|
52
|
+
}
|
|
53
|
+
const fake_return_type_schema = {
|
|
54
|
+
name: 'ReturnType',
|
|
55
|
+
items: [{
|
|
56
|
+
key: 'rrr',
|
|
57
|
+
type: api.data.return_type.type
|
|
58
|
+
}]
|
|
59
|
+
};
|
|
60
|
+
const fake_return_type_schema_result = (0, build_from_schema_1.getSchemaContent)(fake_return_type_schema, list_schema);
|
|
61
|
+
const fake_return_type = {
|
|
62
|
+
key: 'rrr',
|
|
63
|
+
type: api.data.return_type.type
|
|
64
|
+
};
|
|
65
|
+
const fake_return_type_field_result = (0, build_from_schema_1.buildField)(fake_return_type, 0, { name: 'ReturnType', items: [] }, list_schema);
|
|
66
|
+
return {
|
|
67
|
+
files: [{
|
|
68
|
+
filename: getAPIFileName(api.data.alias, api, '.ts'),
|
|
69
|
+
content: [
|
|
70
|
+
'import { Response } from "express";',
|
|
71
|
+
`${lodash_1.default.uniq([
|
|
72
|
+
...((_o = header_schema === null || header_schema === void 0 ? void 0 : header_schema.deps) !== null && _o !== void 0 ? _o : []),
|
|
73
|
+
...((_p = query_schema === null || query_schema === void 0 ? void 0 : query_schema.deps) !== null && _p !== void 0 ? _p : []),
|
|
74
|
+
...((_q = path_schema === null || path_schema === void 0 ? void 0 : path_schema.deps) !== null && _q !== void 0 ? _q : []),
|
|
75
|
+
...((_r = body_schema === null || body_schema === void 0 ? void 0 : body_schema.deps) !== null && _r !== void 0 ? _r : []),
|
|
76
|
+
...((_s = fake_return_type_schema_result.deps) !== null && _s !== void 0 ? _s : []),
|
|
77
|
+
...((_t = fake_return_type_field_result.new_deps_lines) !== null && _t !== void 0 ? _t : []),
|
|
78
|
+
].join('\n').split('\n')).join('\n')}
|
|
79
|
+
|
|
80
|
+
${[
|
|
81
|
+
...((_u = header_schema === null || header_schema === void 0 ? void 0 : header_schema.content) !== null && _u !== void 0 ? _u : []),
|
|
82
|
+
...((_v = query_schema === null || query_schema === void 0 ? void 0 : query_schema.content) !== null && _v !== void 0 ? _v : []),
|
|
83
|
+
...((_w = path_schema === null || path_schema === void 0 ? void 0 : path_schema.content) !== null && _w !== void 0 ? _w : []),
|
|
84
|
+
...((_x = body_schema === null || body_schema === void 0 ? void 0 : body_schema.content) !== null && _x !== void 0 ? _x : []),
|
|
85
|
+
...fake_return_type_field_result.new_class_lines,
|
|
86
|
+
].join('\n')}
|
|
87
|
+
|
|
88
|
+
export type ${prefix}${api.data.alias} = (request: {
|
|
89
|
+
${[
|
|
90
|
+
((_y = header_schema === null || header_schema === void 0 ? void 0 : header_schema.content.length) !== null && _y !== void 0 ? _y : 0) > 0 ? ` headers: ${prefix}${api.data.alias}_headers` : '',
|
|
91
|
+
((_z = query_schema === null || query_schema === void 0 ? void 0 : query_schema.content.length) !== null && _z !== void 0 ? _z : 0) > 0 ? ` query: ${prefix}${api.data.alias}_query` : '',
|
|
92
|
+
((_0 = path_schema === null || path_schema === void 0 ? void 0 : path_schema.content.length) !== null && _0 !== void 0 ? _0 : 0) > 0 ? ` path: ${prefix}${api.data.alias}_path` : '',
|
|
93
|
+
((_1 = body_schema === null || body_schema === void 0 ? void 0 : body_schema.content.length) !== null && _1 !== void 0 ? _1 : 0) > 0 ? ` body: ${prefix}${api.data.alias}_body` : '',
|
|
94
|
+
].filter(Boolean).join('\n')}
|
|
95
|
+
${is_streaming
|
|
96
|
+
? `}, stream: (chunk: ${fake_return_type_field_result.type_only}${api.data.return_type.type.required ? '' : ' | null'}) => void, response: Response) => Promise<void>;`
|
|
97
|
+
: `}, response: Response) => Promise<${fake_return_type_field_result.type_only}${api.data.return_type.type.required ? '' : ' | null'}>;`}
|
|
98
|
+
|
|
99
|
+
export const method = '${api.method.toLowerCase()}';
|
|
100
|
+
export const url_path = '${api.url_path}';
|
|
101
|
+
export const alias = '${prefix}${api.data.alias}';
|
|
102
|
+
export const is_streaming = ${is_streaming ? 'true' : 'false'};
|
|
103
|
+
`
|
|
104
|
+
].join('\n')
|
|
105
|
+
}],
|
|
106
|
+
map: {
|
|
107
|
+
[api.data.alias]: getAPIFileName(api.data.alias, api)
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEnumFileName = getEnumFileName;
|
|
4
|
+
exports.buildFromEnum = buildFromEnum;
|
|
5
|
+
function getEnumFileName(item, extension) {
|
|
6
|
+
return `./model/enum/${item.name}${extension !== null && extension !== void 0 ? extension : ''}`;
|
|
7
|
+
}
|
|
8
|
+
function buildFromEnum(enume) {
|
|
9
|
+
return {
|
|
10
|
+
files: [{
|
|
11
|
+
filename: getEnumFileName(enume, '.ts'),
|
|
12
|
+
content: [
|
|
13
|
+
`export enum ${enume.name} {`,
|
|
14
|
+
...enume.items
|
|
15
|
+
.map(s => `'${s}' = '${s}',`)
|
|
16
|
+
.map(line => ' ' + line),
|
|
17
|
+
`};`
|
|
18
|
+
].join('\n')
|
|
19
|
+
}],
|
|
20
|
+
map: {
|
|
21
|
+
[enume.name]: getEnumFileName(enume)
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NVSchema } from "@naiv/core/build/semantic-checker/check_schema";
|
|
2
|
+
import { ItemOutput } from "./data-types";
|
|
3
|
+
import { NVSchemaItem } from "@naiv/core/build/semantic-checker/check_schema_item";
|
|
4
|
+
export declare function getSchemaFileName(schema: NVSchema, extension?: string): string;
|
|
5
|
+
export declare function buildSchemaDependency(schema: NVSchema, list_schema: NVSchema[]): string[];
|
|
6
|
+
export declare function buildFromSchema(schema: NVSchema, list_schema: NVSchema[]): ItemOutput;
|
|
7
|
+
export interface SchemaContentResult {
|
|
8
|
+
deps: string[];
|
|
9
|
+
content: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function getSchemaContent(schema: NVSchema, list_schema: NVSchema[], no_export?: boolean): SchemaContentResult;
|
|
12
|
+
export declare function getDecorators(item: NVSchemaItem): string[];
|
|
13
|
+
export interface BuildFieldResult {
|
|
14
|
+
field_lines: string[];
|
|
15
|
+
type_only: string;
|
|
16
|
+
new_class_lines: string[];
|
|
17
|
+
new_deps_lines: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function buildField(item: NVSchemaItem, index: number, schema: NVSchema, list_schema: NVSchema[]): BuildFieldResult;
|
|
20
|
+
export declare function buildInlineSchemaClass(items: NVSchemaItem[], parent_schema_name: string, index: number, list_schema: NVSchema[]): {
|
|
21
|
+
new_class_deps: string[];
|
|
22
|
+
new_class_content: string[];
|
|
23
|
+
inline_schema_name: string;
|
|
24
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getSchemaFileName = getSchemaFileName;
|
|
7
|
+
exports.buildSchemaDependency = buildSchemaDependency;
|
|
8
|
+
exports.buildFromSchema = buildFromSchema;
|
|
9
|
+
exports.getSchemaContent = getSchemaContent;
|
|
10
|
+
exports.getDecorators = getDecorators;
|
|
11
|
+
exports.buildField = buildField;
|
|
12
|
+
exports.buildInlineSchemaClass = buildInlineSchemaClass;
|
|
13
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
14
|
+
function getSchemaFileName(schema, extension) {
|
|
15
|
+
return `./schema/${schema.name}${extension !== null && extension !== void 0 ? extension : ''}`;
|
|
16
|
+
}
|
|
17
|
+
function buildSchemaDependency(schema, list_schema) {
|
|
18
|
+
return schema.items
|
|
19
|
+
.filter((item) => item.type.type === 'schema' || item.type.type === 'table' || item.type.type === 'enum')
|
|
20
|
+
.map((item) => {
|
|
21
|
+
switch (item.type.type) {
|
|
22
|
+
case 'schema':
|
|
23
|
+
const schema_item = list_schema.find((s) => item.type.type === 'schema' && s.name === item.type.subtype_native);
|
|
24
|
+
if (!schema_item) {
|
|
25
|
+
throw new Error(`Schema "${item.type.subtype_native}" is not available`);
|
|
26
|
+
}
|
|
27
|
+
return `import { ${schema_item.name} } from '.${getSchemaFileName(schema_item)}'`;
|
|
28
|
+
case 'table':
|
|
29
|
+
return `import { ${item.type.subtype_native} } from '../model/table/${item.type.subtype_native}'`;
|
|
30
|
+
case 'enum':
|
|
31
|
+
return `import { ${item.type.subtype_native} } from '../model/enum/${item.type.subtype_native}'`;
|
|
32
|
+
default:
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function buildFromSchema(schema, list_schema) {
|
|
38
|
+
const { deps, content } = getSchemaContent(schema, list_schema);
|
|
39
|
+
return {
|
|
40
|
+
files: [{
|
|
41
|
+
filename: getSchemaFileName(schema, '.ts'),
|
|
42
|
+
content: [
|
|
43
|
+
...deps,
|
|
44
|
+
'',
|
|
45
|
+
...content,
|
|
46
|
+
].join('\n')
|
|
47
|
+
}],
|
|
48
|
+
map: {
|
|
49
|
+
[schema.name]: getSchemaFileName(schema)
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function getSchemaContent(schema, list_schema, no_export) {
|
|
54
|
+
const field_lines = [];
|
|
55
|
+
const new_class_lines = [];
|
|
56
|
+
const new_deps_lines = [];
|
|
57
|
+
let i = 0;
|
|
58
|
+
for (const c of schema.items) {
|
|
59
|
+
const field_result = buildField(c, i, schema, list_schema);
|
|
60
|
+
field_lines.push(...field_result.field_lines);
|
|
61
|
+
new_class_lines.push(...field_result.new_class_lines);
|
|
62
|
+
new_deps_lines.push(...field_result.new_deps_lines);
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
const complete_deps = lodash_1.default.uniq([
|
|
66
|
+
`import { ClassConstructor, Transform, Type, plainToInstance } from "class-transformer";`,
|
|
67
|
+
`import { IsNotEmpty, IsNumber, IsObject, IsBoolean, IsOptional, IsISO8601, IsString, IsEnum, ValidateNested, IsArray, ValidationError, validateOrReject } from "class-validator";`,
|
|
68
|
+
...buildSchemaDependency(schema, list_schema),
|
|
69
|
+
...new_deps_lines
|
|
70
|
+
].join('\n').split('\n'));
|
|
71
|
+
return {
|
|
72
|
+
deps: complete_deps,
|
|
73
|
+
content: [
|
|
74
|
+
...new_class_lines,
|
|
75
|
+
`${no_export ? '' : 'export '}class ${schema.name} {`,
|
|
76
|
+
...field_lines.map(line => ' ' + line),
|
|
77
|
+
`}`
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const transform_integer = `(param?: any): number | null => (param?.value === null || param?.value === undefined || param?.value === '') ? null : parseInt(param.value)`;
|
|
82
|
+
const transform_arrayinteger = `(param?: any): (number | null)[] | null => !Array.isArray(param?.value) ? null : param?.value.map((value: any) => (value === null || value === undefined || value === '') ? null : parseInt(value))`;
|
|
83
|
+
const transform_decimal = `(param?: any): number | null => (param?.value === null || param?.value === undefined || param?.value === '') ? null : parseFloat(param.value)`;
|
|
84
|
+
const transform_arraydecimal = `(param?: any): (number | null)[] | null => !Array.isArray(param?.value) ? null : param?.value.map((value: any) => (value === null || value === undefined || value === '') ? null : parseFloat(value))`;
|
|
85
|
+
const transform_boolean = `(param?: any): boolean | null => (param?.value === null || param?.value === undefined || param?.value === '') ? null : (param?.value === 'true' || ((typeof param?.value === 'boolean') && param?.value))`;
|
|
86
|
+
const transform_arrayboolean = `(param?: any): (boolean | null)[] | null => !Array.isArray(param?.value) ? null : param?.value.map((value: any) => (value === null || value === undefined || value === '') ? null : (value === 'true' || ((typeof value === 'boolean') && value)))`;
|
|
87
|
+
const transform_date = `(param?: any): Date | null => (param?.value === null || param?.value === undefined || param?.value === '') ? null : new Date(param?.value)`;
|
|
88
|
+
const transform_arraydate = `(param?: any): (Date | null)[] | null => !Array.isArray(param?.value) ? null : param?.value.map((value: any) => (value === null || value === undefined || value === '') ? null : new Date(value))`;
|
|
89
|
+
function getDecorators(item) {
|
|
90
|
+
const list_decorator = [];
|
|
91
|
+
if (item.type.required) {
|
|
92
|
+
list_decorator.push(`@IsNotEmpty({ message: '${item.key} cannot be empty' })`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
list_decorator.push(`@IsOptional()`);
|
|
96
|
+
}
|
|
97
|
+
const is_array = item.type.array_dimension > 0;
|
|
98
|
+
if (item.type.type === 'native') {
|
|
99
|
+
const array_property = is_array ? ', each: true' : '';
|
|
100
|
+
switch (item.type.type_native) {
|
|
101
|
+
case 'number':
|
|
102
|
+
list_decorator.push(`@Transform(${is_array ? transform_arraydecimal : transform_decimal})`);
|
|
103
|
+
list_decorator.push(`@IsNumber({}, { message: '${item.key} must be a number (decimal)'${array_property} })`);
|
|
104
|
+
break;
|
|
105
|
+
case 'boolean':
|
|
106
|
+
list_decorator.push(`@Transform(${is_array ? transform_arrayboolean : transform_boolean})`);
|
|
107
|
+
list_decorator.push(`@IsBoolean({ message: '${item.key} must be a boolean'${array_property} })`);
|
|
108
|
+
break;
|
|
109
|
+
case 'string':
|
|
110
|
+
list_decorator.push(`@IsString({ message: '${item.key} must be a string'${array_property} })`);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (item.type.type === 'enum') {
|
|
115
|
+
const array_property = is_array ? ', each: true' : '';
|
|
116
|
+
list_decorator.push(`@IsEnum(${item.type.subtype_native}, { message: '${item.key} must be enum ${item.type.subtype_native}'${array_property} })`);
|
|
117
|
+
}
|
|
118
|
+
if (item.type.type === 'schema') {
|
|
119
|
+
if (is_array) {
|
|
120
|
+
list_decorator.push(`@IsArray()`);
|
|
121
|
+
list_decorator.push(`@ValidateNested({ each: true })`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
list_decorator.push(`@IsObject()`);
|
|
125
|
+
list_decorator.push(`@ValidateNested()`);
|
|
126
|
+
}
|
|
127
|
+
list_decorator.push(`@Type(() => ${item.type.subtype_native})`);
|
|
128
|
+
}
|
|
129
|
+
if (item.type.type === 'table') {
|
|
130
|
+
if (is_array) {
|
|
131
|
+
list_decorator.push(`@IsArray()`);
|
|
132
|
+
list_decorator.push(`@ValidateNested({ each: true })`);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
list_decorator.push(`@IsObject()`);
|
|
136
|
+
list_decorator.push(`@ValidateNested()`);
|
|
137
|
+
}
|
|
138
|
+
list_decorator.push(`@Type(() => ${item.type.subtype_native})`);
|
|
139
|
+
}
|
|
140
|
+
return list_decorator;
|
|
141
|
+
}
|
|
142
|
+
function buildField(item, index, schema, list_schema) {
|
|
143
|
+
var _a;
|
|
144
|
+
const is_array = item.type.array_dimension > 0;
|
|
145
|
+
const array_token = Array(item.type.array_dimension).fill('[]').join('');
|
|
146
|
+
switch (item.type.type) {
|
|
147
|
+
case "native":
|
|
148
|
+
return {
|
|
149
|
+
field_lines: [
|
|
150
|
+
...getDecorators(item),
|
|
151
|
+
`${item.key}${item.type.required ? '!' : '?'}: ${item.type.type_native}${is_array ? array_token : ''}`
|
|
152
|
+
],
|
|
153
|
+
type_only: `${item.type.type_native}${is_array ? array_token : ''}`,
|
|
154
|
+
new_class_lines: [],
|
|
155
|
+
new_deps_lines: []
|
|
156
|
+
};
|
|
157
|
+
case "schema":
|
|
158
|
+
return {
|
|
159
|
+
field_lines: [
|
|
160
|
+
...getDecorators(item),
|
|
161
|
+
`${item.key}${item.type.required ? '!' : '?'}: ${item.type.subtype_native}${is_array ? array_token : ''}`
|
|
162
|
+
],
|
|
163
|
+
type_only: `${item.type.subtype_native}${is_array ? array_token : ''}`,
|
|
164
|
+
new_class_lines: [],
|
|
165
|
+
new_deps_lines: []
|
|
166
|
+
};
|
|
167
|
+
case "table":
|
|
168
|
+
return {
|
|
169
|
+
field_lines: [
|
|
170
|
+
...getDecorators(item),
|
|
171
|
+
`${item.key}${item.type.required ? '!' : '?'}: ${item.type.subtype_native}${is_array ? array_token : ''}`
|
|
172
|
+
],
|
|
173
|
+
type_only: `${item.type.subtype_native}${is_array ? array_token : ''}`,
|
|
174
|
+
new_class_lines: [],
|
|
175
|
+
new_deps_lines: []
|
|
176
|
+
};
|
|
177
|
+
case "enum":
|
|
178
|
+
return {
|
|
179
|
+
field_lines: [
|
|
180
|
+
...getDecorators(item),
|
|
181
|
+
`${item.key}${item.type.required ? '!' : '?'}: ${item.type.subtype_native}${is_array ? array_token : ''}`
|
|
182
|
+
],
|
|
183
|
+
type_only: `${item.type.subtype_native}${is_array ? array_token : ''}`,
|
|
184
|
+
new_class_lines: [],
|
|
185
|
+
new_deps_lines: []
|
|
186
|
+
};
|
|
187
|
+
case "inline-schema":
|
|
188
|
+
const { new_class_deps, new_class_content, inline_schema_name } = buildInlineSchemaClass(((_a = item.type.type_inline_schema) !== null && _a !== void 0 ? _a : []), schema.name, index, list_schema);
|
|
189
|
+
return {
|
|
190
|
+
field_lines: [
|
|
191
|
+
...getDecorators(Object.assign(Object.assign({}, item), { type: Object.assign(Object.assign({}, item.type), { subtype_native: inline_schema_name, type: 'schema' }) })),
|
|
192
|
+
`${item.key}${item.type.required ? '!' : '?'}: ${inline_schema_name}${is_array ? array_token : ''}`
|
|
193
|
+
],
|
|
194
|
+
type_only: `${inline_schema_name}${is_array ? array_token : ''}`,
|
|
195
|
+
new_class_lines: new_class_content,
|
|
196
|
+
new_deps_lines: new_class_deps
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function buildInlineSchemaClass(items, parent_schema_name, index, list_schema) {
|
|
201
|
+
const inline_schema = {
|
|
202
|
+
name: [parent_schema_name, index].join('_'),
|
|
203
|
+
items
|
|
204
|
+
};
|
|
205
|
+
const new_class = getSchemaContent(inline_schema, list_schema, true);
|
|
206
|
+
return { new_class_deps: new_class.deps, new_class_content: new_class.content, inline_schema_name: inline_schema.name };
|
|
207
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NVResult, NVTable, NVTableField, NVTableFieldType } from "@naiv/core";
|
|
2
|
+
import { ItemOutput } from "./data-types";
|
|
3
|
+
export declare function getTableFileName(item: NVTable, extension?: string): string;
|
|
4
|
+
export declare function buildTableDependency(table: NVTable, source: NVResult): string[];
|
|
5
|
+
export declare function mapSQLTypeToJSType(type: NVTableFieldType): string;
|
|
6
|
+
export declare function buildColumnNative(type: NVTableFieldType, column: NVTableField, source: NVResult): string[];
|
|
7
|
+
export declare function buildColumnEnum(type: NVTableFieldType, column: NVTableField): string[];
|
|
8
|
+
export declare function buildColumnRelation(type: NVTableFieldType, column: NVTableField, table: NVTable, source: NVResult): string[];
|
|
9
|
+
export declare function buildColumn(column: NVTableField, table: NVTable, source: NVResult): string[];
|
|
10
|
+
export declare function buildFromTable(table: NVTable, source: NVResult): ItemOutput;
|