@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.
@@ -0,0 +1,253 @@
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.getTableFileName = getTableFileName;
7
+ exports.buildTableDependency = buildTableDependency;
8
+ exports.mapSQLTypeToJSType = mapSQLTypeToJSType;
9
+ exports.buildColumnNative = buildColumnNative;
10
+ exports.buildColumnEnum = buildColumnEnum;
11
+ exports.buildColumnRelation = buildColumnRelation;
12
+ exports.buildColumn = buildColumn;
13
+ exports.buildFromTable = buildFromTable;
14
+ const build_from_enum_1 = require("./build-from-enum");
15
+ const lodash_1 = __importDefault(require("lodash"));
16
+ function getTableFileName(item, extension) {
17
+ return `./model/table/${item.name}${extension !== null && extension !== void 0 ? extension : ''}`;
18
+ }
19
+ function buildTableDependency(table, source) {
20
+ return table.fields
21
+ .filter((tc) => tc.type.kind === 'relation' || tc.type.kind === 'enum') // only table relation or enum
22
+ .filter((tc) => !(tc.type.kind === 'relation' && tc.type.type == table.name)) // dont import yourself
23
+ .map((tc) => {
24
+ const type = tc.type;
25
+ switch (type.kind) {
26
+ case "native":
27
+ case "enum":
28
+ const enum_item = source.list_enum.find((m) => m.name === type.subtype);
29
+ if (!enum_item) {
30
+ throw new Error(`Enum "${type.subtype}" is not available on models`);
31
+ }
32
+ return `import { ${enum_item.name} } from '../.${(0, build_from_enum_1.getEnumFileName)(enum_item)}'`;
33
+ case 'relation':
34
+ const table_item = source.list_table.find((m) => m.name === type.type);
35
+ if (!table_item) {
36
+ throw new Error(`Table "${type.type}" is not available on models`);
37
+ }
38
+ return `import { ${table_item.name} } from '../.${getTableFileName(table_item)}'`;
39
+ }
40
+ });
41
+ }
42
+ function mapSQLTypeToJSType(type) {
43
+ switch (type.type) {
44
+ case 'bigint':
45
+ case 'int8':
46
+ case 'bigserial':
47
+ case 'serial8':
48
+ return 'number';
49
+ case 'boolean':
50
+ case 'bool':
51
+ return 'boolean';
52
+ case 'box':
53
+ case 'bytea':
54
+ case 'cidr':
55
+ case 'circle':
56
+ return 'number';
57
+ case 'date':
58
+ return 'Date';
59
+ case 'float':
60
+ case 'float8':
61
+ return 'number';
62
+ case 'inet':
63
+ return 'string';
64
+ case 'integer':
65
+ case 'int':
66
+ case 'int4':
67
+ return 'number';
68
+ case 'json':
69
+ case 'jsonb':
70
+ case 'line':
71
+ case 'lseg':
72
+ case 'macaddr':
73
+ case 'macaddr8':
74
+ return 'string';
75
+ case 'money':
76
+ return 'number';
77
+ case 'path':
78
+ return 'string';
79
+ case 'pg_lsn':
80
+ case 'pg_snapshot':
81
+ case 'point':
82
+ case 'polygon':
83
+ return 'string';
84
+ case 'real':
85
+ case 'float4':
86
+ case 'smallint':
87
+ case 'int2':
88
+ case 'smallserial':
89
+ case 'serial2':
90
+ case 'serial':
91
+ case 'serial4':
92
+ case 'tinyint':
93
+ return 'number';
94
+ case 'text':
95
+ return 'string';
96
+ case 'timetz':
97
+ case 'timestamptz':
98
+ return 'Date';
99
+ case 'tsquery':
100
+ case 'tsvector':
101
+ case 'txid_snapshot':
102
+ case 'uuid':
103
+ case 'xml':
104
+ case 'bit':
105
+ case 'varbit':
106
+ case 'char':
107
+ case 'varchar':
108
+ return 'string';
109
+ case 'numeric':
110
+ case 'decimal':
111
+ return 'number';
112
+ case 'time':
113
+ case 'timestamp':
114
+ case 'abstime':
115
+ case 'datetime':
116
+ case 'interval':
117
+ case 'reltime':
118
+ case 'timespan':
119
+ return 'Date';
120
+ }
121
+ throw new Error(`unsupported data type '${type.type}'`);
122
+ }
123
+ function buildDefaultValue(type, column) {
124
+ switch (typeof type.default_value) {
125
+ case "number":
126
+ case "boolean":
127
+ return String(type.default_value);
128
+ case "string":
129
+ if (column.type.kind === 'enum') {
130
+ return type.default_value;
131
+ }
132
+ if (type.default_value.startsWith("'") || type.default_value.startsWith('"')) {
133
+ return type.default_value;
134
+ }
135
+ return `() => "${type.default_value}"`;
136
+ }
137
+ return undefined;
138
+ }
139
+ function buildColumnNative(type, column, source) {
140
+ const default_value_attr = buildDefaultValue(type, column);
141
+ const is_required = !type.nullable;
142
+ const has_default_value = default_value_attr !== undefined;
143
+ const primary_key_attr = type.primary_key;
144
+ const unique_attr = type.unique;
145
+ const autoinc_attr = type.autoincrement;
146
+ const is_numeric_or_decimal = ['numeric', 'decimal'].includes(type.type);
147
+ const precision = is_numeric_or_decimal ? `precision: ${type.param1 || 'undefined'},` : '';
148
+ const scale = is_numeric_or_decimal ? `scale: ${type.param2 || 'undefined'},` : '';
149
+ const is_bit_varbit_char_varchar = ['bit', 'varbit', 'char', 'varchar'].includes(type.type);
150
+ const length = is_bit_varbit_char_varchar ? `length: ${type.param1 || 'undefined'},` : '';
151
+ const typeorm_decorator = [
152
+ `@Column({`,
153
+ ...[
154
+ `type: '${type.type}',`,
155
+ `nullable: ${is_required ? 'false' : 'true'},`,
156
+ precision,
157
+ scale,
158
+ length,
159
+ has_default_value ? `default: ${default_value_attr},` : ''
160
+ ].filter(Boolean).map(line => ' ' + line),
161
+ `})`,
162
+ ];
163
+ if (primary_key_attr) {
164
+ if (autoinc_attr) {
165
+ typeorm_decorator.push(`@PrimaryGeneratedColumn('increment')`);
166
+ }
167
+ else {
168
+ typeorm_decorator.push(`@PrimaryColumn()`);
169
+ }
170
+ }
171
+ if (unique_attr) {
172
+ // something to do with unique
173
+ }
174
+ return [
175
+ ...typeorm_decorator,
176
+ `${column.column_name}${is_required ? '!' : '?'}: ${mapSQLTypeToJSType(type)};`
177
+ ];
178
+ }
179
+ function buildColumnEnum(type, column) {
180
+ const default_value_attr = type.default_value;
181
+ const is_required = !type.nullable;
182
+ const has_default_value = default_value_attr !== undefined;
183
+ const typeorm_decorator = [
184
+ `@Column({`,
185
+ ...[
186
+ `type: 'enum',`,
187
+ `enum: ${type.subtype},`,
188
+ `nullable: ${is_required ? 'false' : 'true'},`,
189
+ has_default_value ? `default: '${default_value_attr}',` : ''
190
+ ].filter(Boolean).map(line => ' ' + line),
191
+ `})`,
192
+ ];
193
+ return [
194
+ ...typeorm_decorator,
195
+ `${column.column_name}${is_required ? '!' : '?'}: ${type.subtype};`
196
+ ];
197
+ }
198
+ function buildColumnRelation(type, column, table, source) {
199
+ const is_required = !type.nullable;
200
+ const foreign_table = source.list_table.find((item) => item.name === type.type);
201
+ if (!foreign_table) {
202
+ throw new Error(`Table "${type.type}" not found on relation "${table.name}.${column.column_name}"`);
203
+ }
204
+ const foreign_column = foreign_table.fields.find((fc) => fc.column_name === type.subtype);
205
+ if (!foreign_column) {
206
+ throw new Error(`Column "${type.subtype}" on table "${type.type}" not found on relation "${table.name}.${column.column_name}"`);
207
+ }
208
+ const one_to_many_field_name = `otm_${column.column_name}`;
209
+ const typeorm_decorator = [
210
+ `@ManyToOne(() => ${foreign_table.name}, x => x.${foreign_column.column_name}, { nullable: ${is_required ? 'false' : 'true'} })`,
211
+ `@JoinColumn({ name: '${column.column_name}' })`,
212
+ `${one_to_many_field_name}${(is_required && false /** relation object always optional */) ? '!' : '?'}: ${foreign_table.name};`,
213
+ `@Column({`,
214
+ ...[
215
+ `name: '${column.column_name}',`,
216
+ `type: '${foreign_column.type.type}',`,
217
+ `nullable: ${is_required ? 'false' : 'true'},`,
218
+ ].filter(Boolean).map(line => ' ' + line),
219
+ `})`,
220
+ ];
221
+ return [
222
+ ...typeorm_decorator,
223
+ `${column.column_name}${is_required ? '!' : '?'}: ${mapSQLTypeToJSType(foreign_column.type)};`
224
+ ];
225
+ }
226
+ function buildColumn(column, table, source) {
227
+ switch (column.type.kind) {
228
+ case "native": return buildColumnNative(column.type, column, source);
229
+ case "enum": return buildColumnEnum(column.type, column);
230
+ case "relation": return buildColumnRelation(column.type, column, table, source);
231
+ }
232
+ }
233
+ function buildFromTable(table, source) {
234
+ return {
235
+ files: [{
236
+ filename: getTableFileName(table, '.ts'),
237
+ content: [
238
+ 'import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryColumn, PrimaryGeneratedColumn, UpdateDateColumn, BaseEntity } from "typeorm";',
239
+ ...lodash_1.default.uniq(buildTableDependency(table, source)),
240
+ '',
241
+ `@Entity('${table.name}')`,
242
+ `export class ${table.name} extends BaseEntity {`,
243
+ ...table.fields
244
+ .reduce((acc, c) => [...acc, ...buildColumn(c, table, source)], [])
245
+ .map(line => ' ' + line),
246
+ `}`
247
+ ].join('\n')
248
+ }],
249
+ map: {
250
+ [table.name]: getTableFileName(table)
251
+ }
252
+ };
253
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdGenerate(design_file_abs_path: string, out_folder: string): Promise<void>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.cmdGenerate = cmdGenerate;
16
+ const naiv_parser_1 = require("@naiv/core/build/naiv_parser");
17
+ const fs_1 = __importDefault(require("fs"));
18
+ const _1 = require(".");
19
+ function cmdGenerate(design_file_abs_path, out_folder) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ const result = (0, naiv_parser_1.naiv_parser)(yield fs_1.default.promises.readFile(design_file_abs_path, 'utf-8'));
22
+ const typeorm_model = _1.TypeORMModel.compile(result);
23
+ for (const f of typeorm_model.enum.files) {
24
+ writeFiles(f, out_folder);
25
+ }
26
+ for (const f of typeorm_model.table.files) {
27
+ writeFiles(f, out_folder);
28
+ }
29
+ for (const f of typeorm_model.schema.files) {
30
+ writeFiles(f, out_folder);
31
+ }
32
+ for (const f of typeorm_model.api.files) {
33
+ writeFiles(f, out_folder);
34
+ }
35
+ });
36
+ }
37
+ function writeFiles(output_1) {
38
+ return __awaiter(this, arguments, void 0, function* (output, main_project_location = 'project') {
39
+ const folder = main_project_location + '/' + output.filename.split('/').slice(0, -1).join('/');
40
+ if (!fs_1.default.existsSync(folder)) {
41
+ fs_1.default.mkdirSync(folder, { recursive: true });
42
+ }
43
+ const filename = main_project_location + '/' + output.filename;
44
+ fs_1.default.writeFileSync(filename, output.content);
45
+ });
46
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdRun(design_file: string): Promise<void>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.cmdRun = cmdRun;
16
+ const cmd_generate_1 = require("./cmd-generate");
17
+ const compile_folter_1 = require("./compile-folter");
18
+ const server_1 = require("./server");
19
+ const path_1 = __importDefault(require("path"));
20
+ const fs_1 = __importDefault(require("fs"));
21
+ function cmdRun(design_file) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const types_path = path_1.default.resolve('./zzz-types');
24
+ const implementation_path = path_1.default.resolve('./zzz-impl');
25
+ yield fs_1.default.promises.rm(types_path, { force: true, recursive: true });
26
+ yield (0, cmd_generate_1.cmdGenerate)(path_1.default.resolve(design_file), types_path);
27
+ yield (0, compile_folter_1.compileAndClean)(types_path);
28
+ yield (new server_1.Server()).run({
29
+ port: 9000,
30
+ types_path,
31
+ implementation_path
32
+ });
33
+ });
34
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Compile a TS folder and remove .ts files
3
+ */
4
+ export declare function compileAndClean(absFolderPath: string): Promise<void>;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.compileAndClean = compileAndClean;
16
+ const typescript_1 = __importDefault(require("typescript"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const glob_1 = require("glob");
20
+ /**
21
+ * Compile a TS folder and remove .ts files
22
+ */
23
+ function compileAndClean(absFolderPath) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ if (!path_1.default.isAbsolute(absFolderPath)) {
26
+ throw new Error("Path must be absolute");
27
+ }
28
+ if (!fs_1.default.existsSync(absFolderPath)) {
29
+ throw new Error("Folder does not exist");
30
+ }
31
+ console.log("Compiling:", absFolderPath);
32
+ // Find all .ts files
33
+ const tsFiles = (0, glob_1.globSync)("**/*.ts", {
34
+ cwd: absFolderPath,
35
+ absolute: true,
36
+ ignore: ["**/node_modules/**"]
37
+ });
38
+ if (!tsFiles.length) {
39
+ console.log("No TypeScript files found.");
40
+ return;
41
+ }
42
+ // Create TS program
43
+ const program = typescript_1.default.createProgram(tsFiles, {
44
+ target: typescript_1.default.ScriptTarget.ES2020,
45
+ module: typescript_1.default.ModuleKind.CommonJS,
46
+ outDir: absFolderPath,
47
+ rootDir: absFolderPath,
48
+ experimentalDecorators: true,
49
+ emitDecoratorMetadata: true,
50
+ useDefineForClassFields: false,
51
+ strict: true,
52
+ noEmitOnError: false
53
+ });
54
+ // Compile
55
+ const emitResult = program.emit();
56
+ // const diagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
57
+ // diagnostics.forEach(d => {
58
+ // console.error(ts.flattenDiagnosticMessageText(d.messageText, "\n"));
59
+ // });
60
+ if (emitResult.emitSkipped) {
61
+ throw new Error("Compilation failed");
62
+ }
63
+ console.log("Compilation done.");
64
+ // Remove .ts files
65
+ for (const file of tsFiles) {
66
+ yield fs_1.default.promises.rm(file);
67
+ }
68
+ console.log("TS files removed.");
69
+ });
70
+ }
@@ -0,0 +1,11 @@
1
+ export type MapModelNameFilePath = {
2
+ [key: string]: string;
3
+ };
4
+ export interface CodegenFileOutput {
5
+ filename: string;
6
+ content: string;
7
+ }
8
+ export interface ItemOutput {
9
+ files: CodegenFileOutput[];
10
+ map: MapModelNameFilePath;
11
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/exec.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/exec.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const arg_1 = __importDefault(require("arg"));
8
+ const cmd_run_1 = require("./cmd-run");
9
+ const args = (0, arg_1.default)({
10
+ "--design": String,
11
+ "-d": "--design",
12
+ });
13
+ if (!args['--design']) {
14
+ throw new Error(`--design/-d argument is required`);
15
+ }
16
+ (0, cmd_run_1.cmdRun)(args['--design']).then(() => console.log('completed.')).catch(console.error);
@@ -0,0 +1,13 @@
1
+ import { NVResult } from "@naiv/core";
2
+ import { ItemOutput } from "./data-types";
3
+ import { Server } from './server';
4
+ export declare namespace TypeORMModel {
5
+ interface Output {
6
+ table: ItemOutput;
7
+ enum: ItemOutput;
8
+ schema: ItemOutput;
9
+ api: ItemOutput;
10
+ }
11
+ function compile(source: NVResult): Output;
12
+ }
13
+ export { Server };
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Server = exports.TypeORMModel = void 0;
4
+ const build_from_table_1 = require("./build-from-table");
5
+ const build_from_enum_1 = require("./build-from-enum");
6
+ const build_from_schema_1 = require("./build-from-schema");
7
+ const build_from_api_1 = require("./build-from-api");
8
+ const server_1 = require("./server");
9
+ Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return server_1.Server; } });
10
+ var TypeORMModel;
11
+ (function (TypeORMModel) {
12
+ function compile(source) {
13
+ const list_api_output = source.list_api.map((t) => (0, build_from_api_1.buildFromAPI)(t, source.list_schema));
14
+ const list_schema_output = source.list_schema.map((t) => (0, build_from_schema_1.buildFromSchema)(t, source.list_schema));
15
+ const list_table_output = source.list_table.map((t) => (0, build_from_table_1.buildFromTable)(t, source));
16
+ const list_enume_output = source.list_enum.map((t) => (0, build_from_enum_1.buildFromEnum)(t));
17
+ return {
18
+ api: {
19
+ files: list_api_output.reduce((accumulator, o) => [...accumulator, ...o.files], []),
20
+ map: list_api_output.reduce((accumulator, o) => (Object.assign(Object.assign({}, accumulator), o.map)), {})
21
+ },
22
+ schema: {
23
+ files: list_schema_output.reduce((accumulator, o) => [...accumulator, ...o.files], []),
24
+ map: list_schema_output.reduce((accumulator, o) => (Object.assign(Object.assign({}, accumulator), o.map)), {})
25
+ },
26
+ table: {
27
+ files: list_table_output.reduce((accumulator, o) => [...accumulator, ...o.files], []),
28
+ map: list_table_output.reduce((accumulator, o) => (Object.assign(Object.assign({}, accumulator), o.map)), {})
29
+ },
30
+ enum: {
31
+ files: list_enume_output.reduce((accumulator, o) => [...accumulator, ...o.files], []),
32
+ map: list_enume_output.reduce((accumulator, o) => (Object.assign(Object.assign({}, accumulator), o.map)), {})
33
+ }
34
+ };
35
+ }
36
+ TypeORMModel.compile = compile;
37
+ })(TypeORMModel || (exports.TypeORMModel = TypeORMModel = {}));
@@ -0,0 +1,21 @@
1
+ import 'reflect-metadata';
2
+ import { Express } from 'express';
3
+ export interface SystemParam {
4
+ api_prefix?: string;
5
+ port: number;
6
+ types_path: string;
7
+ implementation_path: string;
8
+ beforeStart?(): Promise<void>;
9
+ }
10
+ export interface ServerConstructorParam {
11
+ noCors?: boolean;
12
+ noTrustProxy?: boolean;
13
+ }
14
+ export declare class Server {
15
+ express: Express;
16
+ private constructor_param;
17
+ constructor(param?: ServerConstructorParam);
18
+ run(param: SystemParam): Promise<Server>;
19
+ private errorToString;
20
+ _run(types_folder_abs_path: string, implementation_folder: string, api_prefix?: string): Promise<void>;
21
+ }