sizuku 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/README.md +471 -0
- package/dist/common/config/index.d.ts +13 -0
- package/dist/common/config/index.js +13 -0
- package/dist/common/format/index.d.ts +1 -0
- package/dist/common/format/index.js +12 -0
- package/dist/common/generator/generate-field-definitions.d.ts +8 -0
- package/dist/common/generator/generate-field-definitions.js +16 -0
- package/dist/common/helper/get-camel-case-schema-name-helper.d.ts +7 -0
- package/dist/common/helper/get-camel-case-schema-name-helper.js +14 -0
- package/dist/common/helper/get-pascal-case-schema-name-helper.d.ts +8 -0
- package/dist/common/helper/get-pascal-case-schema-name-helper.js +15 -0
- package/dist/common/helper/get-variable-name-helper.d.ts +9 -0
- package/dist/common/helper/get-variable-name-helper.js +15 -0
- package/dist/common/helper/get-variable-schema-name-helper.d.ts +9 -0
- package/dist/common/helper/get-variable-schema-name-helper.js +17 -0
- package/dist/common/text/capitalize.d.ts +18 -0
- package/dist/common/text/capitalize.js +23 -0
- package/dist/common/text/decapitalize.d.ts +17 -0
- package/dist/common/text/decapitalize.js +22 -0
- package/dist/common/type/index.d.ts +9 -0
- package/dist/common/type/index.js +2 -0
- package/dist/generator/mermaid-er/config/index.d.ts +10 -0
- package/dist/generator/mermaid-er/config/index.js +18 -0
- package/dist/generator/mermaid-er/core/extract-relations.d.ts +8 -0
- package/dist/generator/mermaid-er/core/extract-relations.js +20 -0
- package/dist/generator/mermaid-er/generator/generate-er-content.d.ts +9 -0
- package/dist/generator/mermaid-er/generator/generate-er-content.js +27 -0
- package/dist/generator/mermaid-er/generator/generate-relation-line.d.ts +7 -0
- package/dist/generator/mermaid-er/generator/generate-relation-line.js +16 -0
- package/dist/generator/mermaid-er/index.d.ts +7 -0
- package/dist/generator/mermaid-er/index.js +102 -0
- package/dist/generator/mermaid-er/type/index.d.ts +40 -0
- package/dist/generator/mermaid-er/type/index.js +2 -0
- package/dist/generator/mermaid-er/validator/is-relation.d.ts +7 -0
- package/dist/generator/mermaid-er/validator/is-relation.js +40 -0
- package/dist/generator/mermaid-er/validator/parse-relation-line.d.ts +12 -0
- package/dist/generator/mermaid-er/validator/parse-relation-line.js +28 -0
- package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +8 -0
- package/dist/generator/mermaid-er/validator/parse-table-info.js +91 -0
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +7 -0
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +12 -0
- package/dist/generator/valibot/config/index.d.ts +7 -0
- package/dist/generator/valibot/config/index.js +19 -0
- package/dist/generator/valibot/core/extract-schema.d.ts +8 -0
- package/dist/generator/valibot/core/extract-schema.js +92 -0
- package/dist/generator/valibot/generator/generate-valibot-code.d.ts +11 -0
- package/dist/generator/valibot/generator/generate-valibot-code.js +21 -0
- package/dist/generator/valibot/generator/generate-valibot-infer-input.d.ts +9 -0
- package/dist/generator/valibot/generator/generate-valibot-infer-input.js +16 -0
- package/dist/generator/valibot/generator/generate-valibot-schema.d.ts +9 -0
- package/dist/generator/valibot/generator/generate-valibot-schema.js +16 -0
- package/dist/generator/valibot/index.d.ts +3 -0
- package/dist/generator/valibot/index.js +77 -0
- package/dist/generator/zod/config/index.d.ts +8 -0
- package/dist/generator/zod/config/index.js +20 -0
- package/dist/generator/zod/core/extract-schema.d.ts +8 -0
- package/dist/generator/zod/core/extract-schema.js +96 -0
- package/dist/generator/zod/generator/generate-z-infer.d.ts +11 -0
- package/dist/generator/zod/generator/generate-z-infer.js +18 -0
- package/dist/generator/zod/generator/generate-zod-code.d.ts +11 -0
- package/dist/generator/zod/generator/generate-zod-code.js +21 -0
- package/dist/generator/zod/generator/generate-zod-schema.d.ts +11 -0
- package/dist/generator/zod/generator/generate-zod-schema.js +17 -0
- package/dist/generator/zod/index.d.ts +3 -0
- package/dist/generator/zod/index.js +77 -0
- package/package.json +55 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractSchemas = extractSchemas;
|
|
4
|
+
/**
|
|
5
|
+
* Check if line contains metadata
|
|
6
|
+
*/
|
|
7
|
+
const isMetadataComment = (line) => {
|
|
8
|
+
return line.includes('@z.') || line.includes('@v.') || line.includes('@relation.');
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Extract schemas from lines of code
|
|
12
|
+
* @function extractSchemas
|
|
13
|
+
* @param lines - Lines of code
|
|
14
|
+
* @returns Schemas
|
|
15
|
+
*/
|
|
16
|
+
function extractSchemas(lines) {
|
|
17
|
+
const process = (i, acc) => {
|
|
18
|
+
if (i >= lines.length) {
|
|
19
|
+
return acc;
|
|
20
|
+
}
|
|
21
|
+
const line = lines[i];
|
|
22
|
+
// extract schema name
|
|
23
|
+
const schemaMatch = line.match(/export const (\w+)\s*=/);
|
|
24
|
+
if (schemaMatch) {
|
|
25
|
+
if (acc.currentSchema) {
|
|
26
|
+
acc.schemas.push(acc.currentSchema);
|
|
27
|
+
}
|
|
28
|
+
acc.currentSchema = { name: schemaMatch[1], fields: [] };
|
|
29
|
+
acc.pendingDescription = undefined;
|
|
30
|
+
return process(i + 1, acc);
|
|
31
|
+
}
|
|
32
|
+
// handle comment line
|
|
33
|
+
if (line.trim().startsWith('///')) {
|
|
34
|
+
// detect valibot comment
|
|
35
|
+
const valibotComment = line.match(/\/\/\/\s*@(v\.[^\n]+)/);
|
|
36
|
+
if (valibotComment && acc.currentSchema) {
|
|
37
|
+
// find next field definition line
|
|
38
|
+
const remainingCandidates = lines.slice(i + 1);
|
|
39
|
+
const foundRelative = remainingCandidates.findIndex((candidate) => {
|
|
40
|
+
const trimmed = candidate.trim();
|
|
41
|
+
return trimmed !== '' && !trimmed.startsWith('///');
|
|
42
|
+
});
|
|
43
|
+
if (foundRelative !== -1) {
|
|
44
|
+
const j = i + 1 + foundRelative;
|
|
45
|
+
const candidate = lines[j].trim();
|
|
46
|
+
const fieldMatch = candidate.match(/^(\w+)\s*:/);
|
|
47
|
+
if (fieldMatch) {
|
|
48
|
+
const newField = {
|
|
49
|
+
name: fieldMatch[1],
|
|
50
|
+
definition: valibotComment[1],
|
|
51
|
+
description: acc.pendingDescription,
|
|
52
|
+
};
|
|
53
|
+
acc.currentSchema.fields.push(newField);
|
|
54
|
+
acc.pendingDescription = undefined;
|
|
55
|
+
return process(i + 1, acc);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// ignore comment line except metadata
|
|
61
|
+
if (!isMetadataComment(line)) {
|
|
62
|
+
const commentText = line.replace('///', '').trim();
|
|
63
|
+
acc.pendingDescription = acc.pendingDescription
|
|
64
|
+
? `${acc.pendingDescription} ${commentText}`
|
|
65
|
+
: commentText;
|
|
66
|
+
return process(i + 1, acc);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return process(i + 1, acc);
|
|
70
|
+
}
|
|
71
|
+
// if field definition is found in non-comment line, use pending comment as field information
|
|
72
|
+
if (acc.currentSchema && acc.pendingDescription) {
|
|
73
|
+
const fieldMatch = line.match(/^(\w+)\s*:/);
|
|
74
|
+
if (fieldMatch) {
|
|
75
|
+
const newField = {
|
|
76
|
+
name: fieldMatch[1],
|
|
77
|
+
definition: '',
|
|
78
|
+
description: acc.pendingDescription,
|
|
79
|
+
};
|
|
80
|
+
acc.currentSchema.fields.push(newField);
|
|
81
|
+
acc.pendingDescription = undefined;
|
|
82
|
+
return process(i + 1, acc);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return process(i + 1, acc);
|
|
86
|
+
};
|
|
87
|
+
const finalAcc = process(0, { currentSchema: null, pendingDescription: undefined, schemas: [] });
|
|
88
|
+
if (finalAcc.currentSchema) {
|
|
89
|
+
finalAcc.schemas.push(finalAcc.currentSchema);
|
|
90
|
+
}
|
|
91
|
+
return finalAcc.schemas;
|
|
92
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* Generates Valibot code for a given schema and config.
|
|
5
|
+
*
|
|
6
|
+
* @function generateValibotCode
|
|
7
|
+
* @param schema - The schema to generate code for.
|
|
8
|
+
* @param config - The configuration for the code generation.
|
|
9
|
+
* @returns The generated Valibot code.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateValibotCode(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateValibotCode = generateValibotCode;
|
|
4
|
+
const generate_valibot_infer_input_1 = require("./generate-valibot-infer-input");
|
|
5
|
+
const generate_valibot_schema_1 = require("./generate-valibot-schema");
|
|
6
|
+
/**
|
|
7
|
+
* Generates Valibot code for a given schema and config.
|
|
8
|
+
*
|
|
9
|
+
* @function generateValibotCode
|
|
10
|
+
* @param schema - The schema to generate code for.
|
|
11
|
+
* @param config - The configuration for the code generation.
|
|
12
|
+
* @returns The generated Valibot code.
|
|
13
|
+
*/
|
|
14
|
+
function generateValibotCode(schema, config) {
|
|
15
|
+
const valibotSchema = (0, generate_valibot_schema_1.generateValibotSchema)(schema, config);
|
|
16
|
+
const valibotInfer = (0, generate_valibot_infer_input_1.generateValibotInferInput)(schema, config);
|
|
17
|
+
if (config.type.export) {
|
|
18
|
+
return `${valibotSchema}\n\n${valibotInfer}\n`;
|
|
19
|
+
}
|
|
20
|
+
return `${valibotSchema}\n`;
|
|
21
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* @function generateValibotInferInput
|
|
5
|
+
* @param schema
|
|
6
|
+
* @param config
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateValibotInferInput(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateValibotInferInput = generateValibotInferInput;
|
|
4
|
+
const get_variable_name_helper_1 = require("../../../common/helper/get-variable-name-helper");
|
|
5
|
+
const get_variable_schema_name_helper_1 = require("../../../common/helper/get-variable-schema-name-helper");
|
|
6
|
+
/**
|
|
7
|
+
* @function generateValibotInferInput
|
|
8
|
+
* @param schema
|
|
9
|
+
* @param config
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
function generateValibotInferInput(schema, config) {
|
|
13
|
+
const typeName = (0, get_variable_name_helper_1.getVariableNameHelper)(schema.name, config);
|
|
14
|
+
const schemaName = (0, get_variable_schema_name_helper_1.getVariableSchemaNameHelper)(schema.name, config);
|
|
15
|
+
return `export type ${typeName} = v.InferInput<typeof ${schemaName}>`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* @function generateValibotSchema
|
|
5
|
+
* @param schema
|
|
6
|
+
* @param config
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateValibotSchema(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateValibotSchema = generateValibotSchema;
|
|
4
|
+
const generate_field_definitions_1 = require("../../../common/generator/generate-field-definitions");
|
|
5
|
+
const get_variable_schema_name_helper_1 = require("../../../common/helper/get-variable-schema-name-helper");
|
|
6
|
+
/**
|
|
7
|
+
* @function generateValibotSchema
|
|
8
|
+
* @param schema
|
|
9
|
+
* @param config
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
function generateValibotSchema(schema, config) {
|
|
13
|
+
const schemaName = (0, get_variable_schema_name_helper_1.getVariableSchemaNameHelper)(schema.name, config);
|
|
14
|
+
const res = (0, generate_field_definitions_1.generateFieldDefinitions)(schema, config);
|
|
15
|
+
return `export const ${schemaName} = v.object({${res}})`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
exports.main = main;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const extract_schema_1 = require("./core/extract-schema");
|
|
11
|
+
const format_1 = require("../../common/format");
|
|
12
|
+
const config_1 = require("./config");
|
|
13
|
+
const node_process_1 = require("node:process");
|
|
14
|
+
const generate_valibot_code_1 = require("./generator/generate-valibot-code");
|
|
15
|
+
const IMPORT_VALIBOT = 'import * as v from "valibot"';
|
|
16
|
+
async function main(dev = false, config = (0, config_1.getConfig)()) {
|
|
17
|
+
// 1. argv ['**/bin/node', ''/workspaces/sizuku-test/packages/sizuku/dist/generator/zod/index.js',', 'db/schema.ts', '-o', 'zod/index.ts']
|
|
18
|
+
if (config.output === undefined && !node_process_1.argv.includes('-o')) {
|
|
19
|
+
console.error('Error: -o is not found');
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
// 2. slice ['db/schema.ts', '-o', 'zod/index.ts']
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
// 3. input = args[0] = 'db/schema.ts'
|
|
25
|
+
const input = config.input ?? args[0];
|
|
26
|
+
config.input = input;
|
|
27
|
+
// 4. output = 'zod/index.ts'
|
|
28
|
+
const output = config.output ?? args[args.indexOf('-o') + 1];
|
|
29
|
+
config.output = output;
|
|
30
|
+
try {
|
|
31
|
+
// 5. read db/schema.ts
|
|
32
|
+
const content = (0, node_fs_1.readFileSync)(input, 'utf-8');
|
|
33
|
+
// 6. split lines
|
|
34
|
+
const lines = content.split('\n');
|
|
35
|
+
// 7. create output directory
|
|
36
|
+
const outputDir = node_path_1.default.dirname(output);
|
|
37
|
+
if (!(0, node_fs_1.existsSync)(outputDir)) {
|
|
38
|
+
(0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
// 8. skip import section
|
|
41
|
+
const codeStart = lines.findIndex((line) => !line.trim().startsWith('import') && line.trim() !== '');
|
|
42
|
+
// 9. extract schemas
|
|
43
|
+
const schemas = (0, extract_schema_1.extractSchemas)(lines.slice(codeStart));
|
|
44
|
+
// 10. generate zod code
|
|
45
|
+
const generatedCode = [
|
|
46
|
+
IMPORT_VALIBOT,
|
|
47
|
+
'',
|
|
48
|
+
...schemas.map((schema) => (0, generate_valibot_code_1.generateValibotCode)(schema, config)),
|
|
49
|
+
].join('\n');
|
|
50
|
+
// 11. format code
|
|
51
|
+
const code = await (0, format_1.formatCode)(generatedCode);
|
|
52
|
+
// 12. write to output file
|
|
53
|
+
(0, node_fs_1.writeFileSync)(output, code);
|
|
54
|
+
console.log(`Generated Valibot schema at: ${output}`);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
if (e instanceof Error) {
|
|
59
|
+
console.error(e.message);
|
|
60
|
+
if (dev) {
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
if (dev) {
|
|
66
|
+
throw new Error('Unknown error occurred');
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (require.main === module) {
|
|
72
|
+
main().then((success) => {
|
|
73
|
+
if (!success) {
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Config } from '../../../common/config'
|
|
2
|
+
/**
|
|
3
|
+
* Loads the configuration from the `sizuku.json` file or returns the default configuration.
|
|
4
|
+
*
|
|
5
|
+
* @function getConfig
|
|
6
|
+
* @returns The configuration object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getConfig(): Config
|
|
@@ -0,0 +1,20 @@
|
|
|
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.getConfig = getConfig;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const config_1 = require("../../../common/config");
|
|
9
|
+
/**
|
|
10
|
+
* Loads the configuration from the `sizuku.json` file or returns the default configuration.
|
|
11
|
+
*
|
|
12
|
+
* @function getConfig
|
|
13
|
+
* @returns The configuration object.
|
|
14
|
+
*/
|
|
15
|
+
function getConfig() {
|
|
16
|
+
const config = node_fs_1.default.existsSync('sizuku-zod.json')
|
|
17
|
+
? { ...config_1.DEFAULT_CONFIG, ...JSON.parse(node_fs_1.default.readFileSync('sizuku-zod.json', 'utf-8')) }
|
|
18
|
+
: config_1.DEFAULT_CONFIG;
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractSchemas = extractSchemas;
|
|
4
|
+
/**
|
|
5
|
+
* Check if line contains metadata
|
|
6
|
+
*/
|
|
7
|
+
const isMetadataComment = (line) => {
|
|
8
|
+
return line.includes('@z.') || line.includes('@v.') || line.includes('@relation.');
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Check if line is a non-comment line
|
|
12
|
+
*/
|
|
13
|
+
const isNonCommentLine = (line) => {
|
|
14
|
+
const trimmed = line.trim();
|
|
15
|
+
return trimmed !== '' && !trimmed.startsWith('///');
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Extract schemas from lines of code
|
|
19
|
+
* @function extractSchemas
|
|
20
|
+
* @param lines - Lines of code
|
|
21
|
+
* @returns Schemas
|
|
22
|
+
*/
|
|
23
|
+
function extractSchemas(lines) {
|
|
24
|
+
const process = (i, acc) => {
|
|
25
|
+
if (i >= lines.length) {
|
|
26
|
+
return acc;
|
|
27
|
+
}
|
|
28
|
+
const line = lines[i];
|
|
29
|
+
// extract schema
|
|
30
|
+
const schemaMatch = line.match(/export const (\w+)\s*=/);
|
|
31
|
+
if (schemaMatch) {
|
|
32
|
+
if (acc.currentSchema) {
|
|
33
|
+
acc.schemas.push(acc.currentSchema);
|
|
34
|
+
}
|
|
35
|
+
acc.currentSchema = { name: schemaMatch[1], fields: [] };
|
|
36
|
+
acc.pendingDescription = undefined;
|
|
37
|
+
return process(i + 1, acc);
|
|
38
|
+
}
|
|
39
|
+
// process comment
|
|
40
|
+
if (line.trim().startsWith('///')) {
|
|
41
|
+
// zod comment
|
|
42
|
+
const zodComment = line.match(/\/\/\/\s*(@z\.(?:[^()]+|\([^)]*\))+)/);
|
|
43
|
+
if (zodComment && acc.currentSchema) {
|
|
44
|
+
// find next field definition line
|
|
45
|
+
const remainingCandidates = lines.slice(i + 1);
|
|
46
|
+
const foundRelative = remainingCandidates.findIndex(isNonCommentLine);
|
|
47
|
+
if (foundRelative !== -1) {
|
|
48
|
+
const j = i + 1 + foundRelative;
|
|
49
|
+
const candidate = lines[j].trim();
|
|
50
|
+
const fieldMatch = candidate.match(/^(\w+)\s*:/);
|
|
51
|
+
if (fieldMatch) {
|
|
52
|
+
const newField = {
|
|
53
|
+
name: fieldMatch[1],
|
|
54
|
+
definition: zodComment[1].replace('@', ''),
|
|
55
|
+
description: acc.pendingDescription,
|
|
56
|
+
};
|
|
57
|
+
acc.currentSchema.fields.push(newField);
|
|
58
|
+
acc.pendingDescription = undefined;
|
|
59
|
+
return process(i + 1, acc);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// comments other than metadata are pending
|
|
65
|
+
if (!isMetadataComment(line)) {
|
|
66
|
+
const commentText = line.replace('///', '').trim();
|
|
67
|
+
acc.pendingDescription = acc.pendingDescription
|
|
68
|
+
? `${acc.pendingDescription} ${commentText}`
|
|
69
|
+
: commentText;
|
|
70
|
+
return process(i + 1, acc);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return process(i + 1, acc);
|
|
74
|
+
}
|
|
75
|
+
// if there is a field definition other than comment, use the pending comment as field information
|
|
76
|
+
if (acc.currentSchema && acc.pendingDescription) {
|
|
77
|
+
const fieldMatch = line.match(/^(\w+)\s*:/);
|
|
78
|
+
if (fieldMatch) {
|
|
79
|
+
const newField = {
|
|
80
|
+
name: fieldMatch[1],
|
|
81
|
+
definition: '',
|
|
82
|
+
description: acc.pendingDescription,
|
|
83
|
+
};
|
|
84
|
+
acc.currentSchema.fields.push(newField);
|
|
85
|
+
acc.pendingDescription = undefined;
|
|
86
|
+
return process(i + 1, acc);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return process(i + 1, acc);
|
|
90
|
+
};
|
|
91
|
+
const finalAcc = process(0, { currentSchema: null, pendingDescription: undefined, schemas: [] });
|
|
92
|
+
if (finalAcc.currentSchema) {
|
|
93
|
+
finalAcc.schemas.push(finalAcc.currentSchema);
|
|
94
|
+
}
|
|
95
|
+
return finalAcc.schemas;
|
|
96
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* Generates a Zod infer type for a given schema and config.
|
|
5
|
+
*
|
|
6
|
+
* @function generateZInfer
|
|
7
|
+
* @param schema - The schema to generate code for.
|
|
8
|
+
* @param config - The configuration for the code generation.
|
|
9
|
+
* @returns The generated Zod infer type.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateZInfer(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateZInfer = generateZInfer;
|
|
4
|
+
const get_variable_name_helper_1 = require("../../../common/helper/get-variable-name-helper");
|
|
5
|
+
const get_variable_schema_name_helper_1 = require("../../../common/helper/get-variable-schema-name-helper");
|
|
6
|
+
/**
|
|
7
|
+
* Generates a Zod infer type for a given schema and config.
|
|
8
|
+
*
|
|
9
|
+
* @function generateZInfer
|
|
10
|
+
* @param schema - The schema to generate code for.
|
|
11
|
+
* @param config - The configuration for the code generation.
|
|
12
|
+
* @returns The generated Zod infer type.
|
|
13
|
+
*/
|
|
14
|
+
function generateZInfer(schema, config) {
|
|
15
|
+
const typeName = (0, get_variable_name_helper_1.getVariableNameHelper)(schema.name, config);
|
|
16
|
+
const schemaName = (0, get_variable_schema_name_helper_1.getVariableSchemaNameHelper)(schema.name, config);
|
|
17
|
+
return `export type ${typeName} = z.infer<typeof ${schemaName}>`;
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* Generates Zod code for a given schema and config.
|
|
5
|
+
*
|
|
6
|
+
* @function generateZodCode
|
|
7
|
+
* @param schema - The schema to generate code for.
|
|
8
|
+
* @param config - The configuration for the code generation.
|
|
9
|
+
* @returns The generated Zod code.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateZodCode(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateZodCode = generateZodCode;
|
|
4
|
+
const generate_z_infer_1 = require("./generate-z-infer");
|
|
5
|
+
const generate_zod_schema_1 = require("./generate-zod-schema");
|
|
6
|
+
/**
|
|
7
|
+
* Generates Zod code for a given schema and config.
|
|
8
|
+
*
|
|
9
|
+
* @function generateZodCode
|
|
10
|
+
* @param schema - The schema to generate code for.
|
|
11
|
+
* @param config - The configuration for the code generation.
|
|
12
|
+
* @returns The generated Zod code.
|
|
13
|
+
*/
|
|
14
|
+
function generateZodCode(schema, config) {
|
|
15
|
+
const zodSchema = (0, generate_zod_schema_1.generateZodSchema)(schema, config);
|
|
16
|
+
const zInfer = (0, generate_z_infer_1.generateZInfer)(schema, config);
|
|
17
|
+
if (config.type.export) {
|
|
18
|
+
return `${zodSchema}\n\n${zInfer}\n`;
|
|
19
|
+
}
|
|
20
|
+
return `${zodSchema}\n`;
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Schema } from '../../../common/type'
|
|
2
|
+
import type { Config } from '../../../common/config'
|
|
3
|
+
/**
|
|
4
|
+
* Generates a Zod schema for a given schema and config.
|
|
5
|
+
*
|
|
6
|
+
* @function generateZodSchema
|
|
7
|
+
* @param schema - The schema to generate code for.
|
|
8
|
+
* @param config - The configuration for the code generation.
|
|
9
|
+
* @returns The generated Zod schema.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateZodSchema(schema: Schema, config: Config): string
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateZodSchema = generateZodSchema;
|
|
4
|
+
const get_variable_schema_name_helper_1 = require("../../../common/helper/get-variable-schema-name-helper");
|
|
5
|
+
const generate_field_definitions_1 = require("../../../common/generator/generate-field-definitions");
|
|
6
|
+
/**
|
|
7
|
+
* Generates a Zod schema for a given schema and config.
|
|
8
|
+
*
|
|
9
|
+
* @function generateZodSchema
|
|
10
|
+
* @param schema - The schema to generate code for.
|
|
11
|
+
* @param config - The configuration for the code generation.
|
|
12
|
+
* @returns The generated Zod schema.
|
|
13
|
+
*/
|
|
14
|
+
function generateZodSchema(schema, config) {
|
|
15
|
+
const schemaName = (0, get_variable_schema_name_helper_1.getVariableSchemaNameHelper)(schema.name, config);
|
|
16
|
+
return `export const ${schemaName} = z.object({${(0, generate_field_definitions_1.generateFieldDefinitions)(schema, config)}})`;
|
|
17
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
exports.main = main;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const extract_schema_1 = require("./core/extract-schema");
|
|
11
|
+
const generate_zod_code_1 = require("./generator/generate-zod-code");
|
|
12
|
+
const format_1 = require("../../common/format");
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
const node_process_1 = require("node:process");
|
|
15
|
+
const IMPORT_ZOD = 'import { z } from "zod"';
|
|
16
|
+
async function main(dev = false, config = (0, config_1.getConfig)()) {
|
|
17
|
+
// 1. argv ['**/bin/node', ''/workspaces/sizuku-test/packages/sizuku/dist/generator/zod/index.js',', 'db/schema.ts', '-o', 'zod/index.ts']
|
|
18
|
+
if (config.output === undefined && !node_process_1.argv.includes('-o')) {
|
|
19
|
+
console.error('Error: -o is not found');
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
// 2. slice ['db/schema.ts', '-o', 'zod/index.ts']
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
// 3. input = args[0] = 'db/schema.ts'
|
|
25
|
+
const input = config.input ?? args[0];
|
|
26
|
+
config.input = input;
|
|
27
|
+
// 4. output = 'zod/index.ts'
|
|
28
|
+
const output = config.output ?? args[args.indexOf('-o') + 1];
|
|
29
|
+
config.output = output;
|
|
30
|
+
try {
|
|
31
|
+
// 5. read db/schema.ts
|
|
32
|
+
const content = (0, node_fs_1.readFileSync)(input, 'utf-8');
|
|
33
|
+
// 6. split lines
|
|
34
|
+
const lines = content.split('\n');
|
|
35
|
+
// 7. create output directory
|
|
36
|
+
const outputDir = node_path_1.default.dirname(output);
|
|
37
|
+
if (!(0, node_fs_1.existsSync)(outputDir)) {
|
|
38
|
+
(0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
// 8. skip import section
|
|
41
|
+
const codeStart = lines.findIndex((line) => !line.trim().startsWith('import') && line.trim() !== '');
|
|
42
|
+
// 9. extract schemas
|
|
43
|
+
const schemas = (0, extract_schema_1.extractSchemas)(lines.slice(codeStart));
|
|
44
|
+
// 10. generate zod code
|
|
45
|
+
const generatedCode = [
|
|
46
|
+
IMPORT_ZOD,
|
|
47
|
+
'',
|
|
48
|
+
...schemas.map((schema) => (0, generate_zod_code_1.generateZodCode)(schema, config)),
|
|
49
|
+
].join('\n');
|
|
50
|
+
// 11. format code
|
|
51
|
+
const code = await (0, format_1.formatCode)(generatedCode);
|
|
52
|
+
// 12. write to output file
|
|
53
|
+
(0, node_fs_1.writeFileSync)(output, code);
|
|
54
|
+
console.log(`Generated Zod schema at: ${output}`);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
if (e instanceof Error) {
|
|
59
|
+
console.error(e.message);
|
|
60
|
+
if (dev) {
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
if (dev) {
|
|
66
|
+
throw new Error('Unknown error occurred');
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (require.main === module) {
|
|
72
|
+
main().then((success) => {
|
|
73
|
+
if (!success) {
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sizuku",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"drizzle",
|
|
7
|
+
"zod",
|
|
8
|
+
"valibot",
|
|
9
|
+
"mermaid"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/nakita628/sizuku",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/nakita628/sizuku.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/nakita628/sizuku/issues"
|
|
21
|
+
},
|
|
22
|
+
"main": "dist/index.js",
|
|
23
|
+
"types": "dist/index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"bin": {
|
|
28
|
+
"sizuku-zod": "dist/generator/zod/index.js",
|
|
29
|
+
"sizuku-valibot": "dist/generator/valibot/index.js",
|
|
30
|
+
"sizuku-mermaid-er": "dist/generator/mermaid-er/index.js"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"deps": "rm -rf node_modules && pnpm install",
|
|
34
|
+
"demo-er": "sizuku-mermaid-er db/schema.ts -o mermaid-er/ER.md",
|
|
35
|
+
"demo-z": "sizuku-zod db/schema.ts -o zod/index.ts",
|
|
36
|
+
"demo-v": "sizuku-valibot db/schema.ts -o valibot/index.ts",
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"dev": "pnpm --filter sizuku-test dev",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"coverage": "vitest run --coverage",
|
|
42
|
+
"release": "npm pkg fix && npm publish"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.13.8",
|
|
46
|
+
"@vitest/coverage-v8": "^3.0.7",
|
|
47
|
+
"drizzle-orm": "^0.40.0",
|
|
48
|
+
"valibot": "1.0.0-rc.3",
|
|
49
|
+
"vitest": "^3.0.7",
|
|
50
|
+
"zod": "^3.24.2"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"prettier": "^3.5.3"
|
|
54
|
+
}
|
|
55
|
+
}
|