sizuku 0.3.2 → 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/README.md +103 -0
- package/dist/config/index.d.mts +58 -0
- package/dist/config/index.mjs +95 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +1615 -0
- package/package.json +31 -17
- package/dist/cli/main.d.ts +0 -10
- package/dist/cli/main.js +0 -61
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -51
- package/dist/config/index.d.ts +0 -27
- package/dist/config/index.js +0 -85
- package/dist/config/loader.d.ts +0 -19
- package/dist/config/loader.js +0 -30
- package/dist/generator/engine.d.ts +0 -3
- package/dist/generator/engine.js +0 -63
- package/dist/generator/mermaid-er/config/index.d.ts +0 -10
- package/dist/generator/mermaid-er/config/index.js +0 -12
- package/dist/generator/mermaid-er/core/extract-relations.d.ts +0 -8
- package/dist/generator/mermaid-er/core/extract-relations.js +0 -17
- package/dist/generator/mermaid-er/core.d.ts +0 -6
- package/dist/generator/mermaid-er/core.js +0 -54
- package/dist/generator/mermaid-er/generator/er-content.d.ts +0 -20
- package/dist/generator/mermaid-er/generator/er-content.js +0 -23
- package/dist/generator/mermaid-er/generator/index.d.ts +0 -2
- package/dist/generator/mermaid-er/generator/index.js +0 -2
- package/dist/generator/mermaid-er/generator/relation-line.d.ts +0 -12
- package/dist/generator/mermaid-er/generator/relation-line.js +0 -13
- package/dist/generator/mermaid-er/generator.d.ts +0 -3
- package/dist/generator/mermaid-er/generator.js +0 -14
- package/dist/generator/mermaid-er/index.d.ts +0 -12
- package/dist/generator/mermaid-er/index.js +0 -33
- package/dist/generator/mermaid-er/relationship/build-relation-line.d.ts +0 -14
- package/dist/generator/mermaid-er/relationship/build-relation-line.js +0 -34
- package/dist/generator/mermaid-er/types.d.ts +0 -21
- package/dist/generator/mermaid-er/types.js +0 -1
- package/dist/generator/mermaid-er/validator/index.d.ts +0 -8
- package/dist/generator/mermaid-er/validator/index.js +0 -74
- package/dist/generator/mermaid-er/validator/is-relationship.d.ts +0 -7
- package/dist/generator/mermaid-er/validator/is-relationship.js +0 -8
- package/dist/generator/mermaid-er/validator/parse-relation-line.d.ts +0 -12
- package/dist/generator/mermaid-er/validator/parse-relation-line.js +0 -20
- package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +0 -2
- package/dist/generator/mermaid-er/validator/parse-table-info.js +0 -71
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +0 -7
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +0 -9
- package/dist/generator/valibot/config/index.d.ts +0 -7
- package/dist/generator/valibot/config/index.js +0 -13
- package/dist/generator/valibot/core/extract-schema.d.ts +0 -5
- package/dist/generator/valibot/core/extract-schema.js +0 -173
- package/dist/generator/valibot/core.d.ts +0 -5
- package/dist/generator/valibot/core.js +0 -39
- package/dist/generator/valibot/generator/infer-input.d.ts +0 -5
- package/dist/generator/valibot/generator/infer-input.js +0 -8
- package/dist/generator/valibot/generator/relation-valibot-code.d.ts +0 -13
- package/dist/generator/valibot/generator/relation-valibot-code.js +0 -19
- package/dist/generator/valibot/generator/valibot-code.d.ts +0 -15
- package/dist/generator/valibot/generator/valibot-code.js +0 -16
- package/dist/generator/valibot/generator/valibot.d.ts +0 -14
- package/dist/generator/valibot/generator/valibot.js +0 -15
- package/dist/generator/valibot/generator.d.ts +0 -3
- package/dist/generator/valibot/generator.js +0 -14
- package/dist/generator/valibot/index.d.ts +0 -14
- package/dist/generator/valibot/index.js +0 -50
- package/dist/generator/zod/config/index.d.ts +0 -8
- package/dist/generator/zod/config/index.js +0 -14
- package/dist/generator/zod/core/extract-schema.d.ts +0 -7
- package/dist/generator/zod/core/extract-schema.js +0 -243
- package/dist/generator/zod/core.d.ts +0 -5
- package/dist/generator/zod/core.js +0 -39
- package/dist/generator/zod/generator/infer.d.ts +0 -5
- package/dist/generator/zod/generator/infer.js +0 -8
- package/dist/generator/zod/generator/relation-zod-code.d.ts +0 -13
- package/dist/generator/zod/generator/relation-zod-code.js +0 -19
- package/dist/generator/zod/generator/zod-code.d.ts +0 -17
- package/dist/generator/zod/generator/zod-code.js +0 -18
- package/dist/generator/zod/generator/zod.d.ts +0 -16
- package/dist/generator/zod/generator/zod.js +0 -16
- package/dist/generator/zod/generator.d.ts +0 -3
- package/dist/generator/zod/generator.js +0 -14
- package/dist/generator/zod/index.d.ts +0 -15
- package/dist/generator/zod/index.js +0 -54
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -73
- package/dist/shared/config/index.d.ts +0 -13
- package/dist/shared/config/index.js +0 -10
- package/dist/shared/format/index.d.ts +0 -13
- package/dist/shared/format/index.js +0 -24
- package/dist/shared/fs/index.d.ts +0 -7
- package/dist/shared/fs/index.js +0 -16
- package/dist/shared/fsp/index.d.ts +0 -27
- package/dist/shared/fsp/index.js +0 -38
- package/dist/shared/generator/field-definitions.d.ts +0 -12
- package/dist/shared/generator/field-definitions.js +0 -12
- package/dist/shared/helper/ast-parser.d.ts +0 -3
- package/dist/shared/helper/ast-parser.js +0 -202
- package/dist/shared/helper/build-schema-extractor.d.ts +0 -25
- package/dist/shared/helper/build-schema-extractor.js +0 -33
- package/dist/shared/helper/create-extract-field-from-property.d.ts +0 -15
- package/dist/shared/helper/create-extract-field-from-property.js +0 -20
- package/dist/shared/helper/create-extract-fields-from-call-expression.d.ts +0 -14
- package/dist/shared/helper/create-extract-fields-from-call-expression.js +0 -14
- package/dist/shared/helper/create-extract-relation-field-from-property.d.ts +0 -12
- package/dist/shared/helper/create-extract-relation-field-from-property.js +0 -27
- package/dist/shared/helper/extract-schemas.d.ts +0 -133
- package/dist/shared/helper/extract-schemas.js +0 -445
- package/dist/shared/helper/file-writer.d.ts +0 -3
- package/dist/shared/helper/file-writer.js +0 -25
- package/dist/shared/helper/find-object-literal-expression.d.ts +0 -12
- package/dist/shared/helper/find-object-literal-expression.js +0 -31
- package/dist/shared/helper/find-object-literalIn-args.d.ts +0 -2
- package/dist/shared/helper/find-object-literalIn-args.js +0 -8
- package/dist/shared/helper/is-relation-function.d.ts +0 -10
- package/dist/shared/helper/is-relation-function.js +0 -16
- package/dist/shared/types.d.ts +0 -9
- package/dist/shared/types.js +0 -1
- package/dist/shared/utils/capitalize.d.ts +0 -18
- package/dist/shared/utils/capitalize.js +0 -20
- package/dist/shared/utils/compose.d.ts +0 -101
- package/dist/shared/utils/compose.js +0 -124
- package/dist/shared/utils/file.d.ts +0 -92
- package/dist/shared/utils/file.js +0 -177
- package/dist/shared/utils/functional.d.ts +0 -118
- package/dist/shared/utils/functional.js +0 -96
- package/dist/shared/utils/index.d.ts +0 -20
- package/dist/shared/utils/index.js +0 -48
- package/dist/shared/utils/string-utils.d.ts +0 -8
- package/dist/shared/utils/string-utils.js +0 -28
- package/dist/shared/utils/types.d.ts +0 -32
- package/dist/shared/utils/types.js +0 -2
- package/dist/shared/utils/validation-utils.d.ts +0 -8
- package/dist/shared/utils/validation-utils.js +0 -25
- package/dist/src/config/index.d.ts +0 -18
- package/dist/src/config/index.js +0 -13
- package/dist/src/generator/mermaid-er/core/extract-relations.d.ts +0 -8
- package/dist/src/generator/mermaid-er/core/extract-relations.js +0 -12
- package/dist/src/generator/mermaid-er/generator/er-content.d.ts +0 -9
- package/dist/src/generator/mermaid-er/generator/er-content.js +0 -25
- package/dist/src/generator/mermaid-er/generator/index.d.ts +0 -2
- package/dist/src/generator/mermaid-er/generator/index.js +0 -2
- package/dist/src/generator/mermaid-er/generator/relation-line.d.ts +0 -8
- package/dist/src/generator/mermaid-er/generator/relation-line.js +0 -14
- package/dist/src/generator/mermaid-er/index.d.ts +0 -6
- package/dist/src/generator/mermaid-er/index.js +0 -16
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.d.ts +0 -15
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.js +0 -35
- package/dist/src/generator/mermaid-er/types.d.ts +0 -21
- package/dist/src/generator/mermaid-er/types.js +0 -1
- package/dist/src/generator/mermaid-er/validator/index.d.ts +0 -4
- package/dist/src/generator/mermaid-er/validator/index.js +0 -4
- package/dist/src/generator/mermaid-er/validator/is-relationship.d.ts +0 -8
- package/dist/src/generator/mermaid-er/validator/is-relationship.js +0 -9
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.d.ts +0 -13
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.js +0 -21
- package/dist/src/generator/mermaid-er/validator/parse-table-info.d.ts +0 -8
- package/dist/src/generator/mermaid-er/validator/parse-table-info.js +0 -91
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +0 -7
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.js +0 -9
- package/dist/src/generator/valibot/generator/infer-input.d.ts +0 -5
- package/dist/src/generator/valibot/generator/infer-input.js +0 -8
- package/dist/src/generator/valibot/generator/valibot-code.d.ts +0 -14
- package/dist/src/generator/valibot/generator/valibot-code.js +0 -16
- package/dist/src/generator/valibot/generator/valibot.d.ts +0 -13
- package/dist/src/generator/valibot/generator/valibot.js +0 -11
- package/dist/src/generator/valibot/index.d.ts +0 -9
- package/dist/src/generator/valibot/index.js +0 -34
- package/dist/src/generator/zod/generator/infer.d.ts +0 -5
- package/dist/src/generator/zod/generator/infer.js +0 -8
- package/dist/src/generator/zod/generator/zod-code.d.ts +0 -16
- package/dist/src/generator/zod/generator/zod-code.js +0 -18
- package/dist/src/generator/zod/generator/zod.d.ts +0 -15
- package/dist/src/generator/zod/generator/zod.js +0 -12
- package/dist/src/generator/zod/index.d.ts +0 -10
- package/dist/src/generator/zod/index.js +0 -40
- package/dist/src/index.d.ts +0 -10
- package/dist/src/index.js +0 -35
- package/dist/src/shared/format/index.d.ts +0 -2
- package/dist/src/shared/format/index.js +0 -10
- package/dist/src/shared/fs/index.d.ts +0 -2
- package/dist/src/shared/fs/index.js +0 -10
- package/dist/src/shared/fsp/index.d.ts +0 -3
- package/dist/src/shared/fsp/index.js +0 -8
- package/dist/src/shared/generator/field-definitions.d.ts +0 -12
- package/dist/src/shared/generator/field-definitions.js +0 -12
- package/dist/src/shared/helper/build-schema-extractor.d.ts +0 -25
- package/dist/src/shared/helper/build-schema-extractor.js +0 -33
- package/dist/src/shared/helper/create-extract-field-from-property.d.ts +0 -15
- package/dist/src/shared/helper/create-extract-field-from-property.js +0 -20
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.d.ts +0 -14
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.js +0 -14
- package/dist/src/shared/helper/create-extract-relation-field-from-property.d.ts +0 -12
- package/dist/src/shared/helper/create-extract-relation-field-from-property.js +0 -27
- package/dist/src/shared/helper/extract-schemas.d.ts +0 -16
- package/dist/src/shared/helper/extract-schemas.js +0 -19
- package/dist/src/shared/helper/find-object-literal-expression.d.ts +0 -12
- package/dist/src/shared/helper/find-object-literal-expression.js +0 -31
- package/dist/src/shared/helper/find-object-literalIn-args.d.ts +0 -2
- package/dist/src/shared/helper/find-object-literalIn-args.js +0 -8
- package/dist/src/shared/helper/is-relation-function.d.ts +0 -10
- package/dist/src/shared/helper/is-relation-function.js +0 -16
- package/dist/src/shared/utils/index.d.ts +0 -33
- package/dist/src/shared/utils/index.js +0 -61
- package/dist/utils/index.d.ts +0 -144
- package/dist/utils/index.js +0 -250
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { fmt } from '../../shared/format/index.js';
|
|
3
|
-
import { mkdir, writeFile } from '../../shared/fsp/index.js';
|
|
4
|
-
import { extractRelationSchemas, extractSchemas } from '../../shared/helper/extract-schemas.js';
|
|
5
|
-
import { relationZodCode } from './generator/relation-zod-code.js';
|
|
6
|
-
import { zodCode } from './generator/zod-code.js';
|
|
7
|
-
/**
|
|
8
|
-
* Generate Zod schema
|
|
9
|
-
* @param code - The code to generate Zod schema from
|
|
10
|
-
* @param output - The output file path
|
|
11
|
-
* @param comment - Whether to include comments in the generated code
|
|
12
|
-
* @param type - Whether to include type information in the generated code
|
|
13
|
-
* @param zod - The Zod version to use
|
|
14
|
-
*/
|
|
15
|
-
export async function sizukuZod(code, output, comment, type, zod, relation) {
|
|
16
|
-
const importLine = zod === 'mini'
|
|
17
|
-
? `import * as z from 'zod/mini'`
|
|
18
|
-
: zod === '@hono/zod-openapi'
|
|
19
|
-
? `import { z } from '@hono/zod-openapi'`
|
|
20
|
-
: `import * as z from 'zod'`;
|
|
21
|
-
const baseSchemas = extractSchemas(code, 'zod');
|
|
22
|
-
const relationSchemas = extractRelationSchemas(code, 'zod');
|
|
23
|
-
const zodGeneratedCode = [
|
|
24
|
-
importLine,
|
|
25
|
-
'',
|
|
26
|
-
...baseSchemas.map((schema) => zodCode(schema, comment ?? false, type ?? false)),
|
|
27
|
-
...(relation ? relationSchemas.map((schema) => relationZodCode(schema, type ?? false)) : []),
|
|
28
|
-
].join('\n');
|
|
29
|
-
const mkdirResult = await mkdir(path.dirname(output));
|
|
30
|
-
if (!mkdirResult.ok) {
|
|
31
|
-
return {
|
|
32
|
-
ok: false,
|
|
33
|
-
error: mkdirResult.error,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
const fmtResult = await fmt(zodGeneratedCode);
|
|
37
|
-
if (!fmtResult.ok) {
|
|
38
|
-
return {
|
|
39
|
-
ok: false,
|
|
40
|
-
error: fmtResult.error,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
const writeFileResult = await writeFile(output, fmtResult.value);
|
|
44
|
-
if (!writeFileResult.ok) {
|
|
45
|
-
return {
|
|
46
|
-
ok: false,
|
|
47
|
-
error: writeFileResult.error,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
ok: true,
|
|
52
|
-
value: undefined,
|
|
53
|
-
};
|
|
54
|
-
}
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// #!/usr/bin/env node
|
|
2
|
-
import { config } from './config/index.js';
|
|
3
|
-
import { sizukuMermaidER } from './generator/mermaid-er/index.js';
|
|
4
|
-
import { sizukuValibot } from './generator/valibot/index.js';
|
|
5
|
-
import { sizukuZod } from './generator/zod/index.js';
|
|
6
|
-
import { readFileSync } from './shared/fs/index.js';
|
|
7
|
-
export async function main() {
|
|
8
|
-
const configResult = await config();
|
|
9
|
-
if (!configResult.ok) {
|
|
10
|
-
return {
|
|
11
|
-
ok: false,
|
|
12
|
-
error: configResult.error,
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
const c = configResult.value;
|
|
16
|
-
const contentResult = readFileSync(c.input);
|
|
17
|
-
if (!contentResult.ok) {
|
|
18
|
-
return {
|
|
19
|
-
ok: false,
|
|
20
|
-
error: contentResult.error,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
const content = contentResult.value;
|
|
24
|
-
const lines = content.split('\n');
|
|
25
|
-
const codeStart = lines.findIndex((line) => !line.trim().startsWith('import') && line.trim() !== '');
|
|
26
|
-
const code = lines.slice(codeStart);
|
|
27
|
-
const results = [];
|
|
28
|
-
/* zod */
|
|
29
|
-
if (c.zod?.output) {
|
|
30
|
-
const zodResult = await sizukuZod(code, c.zod.output, c.zod.comment, c.zod.type, c.zod.zod, c.zod.relation);
|
|
31
|
-
if (!zodResult.ok) {
|
|
32
|
-
return {
|
|
33
|
-
ok: false,
|
|
34
|
-
error: zodResult.error,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
results.push(`Generated Zod schema at: ${c.zod?.output}`);
|
|
38
|
-
}
|
|
39
|
-
/* valibot */
|
|
40
|
-
if (c.valibot?.output) {
|
|
41
|
-
const valibotResult = await sizukuValibot(code, c.valibot.output, c.valibot.comment, c.valibot.type, c.valibot.relation);
|
|
42
|
-
if (!valibotResult.ok) {
|
|
43
|
-
return {
|
|
44
|
-
ok: false,
|
|
45
|
-
error: valibotResult.error,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
results.push(`Generated Valibot schema at: ${c.valibot?.output}`);
|
|
49
|
-
}
|
|
50
|
-
/* mermaid */
|
|
51
|
-
if (c.mermaid?.output) {
|
|
52
|
-
const mermaidResult = await sizukuMermaidER(code, c.mermaid.output);
|
|
53
|
-
if (!mermaidResult.ok) {
|
|
54
|
-
return {
|
|
55
|
-
ok: false,
|
|
56
|
-
error: mermaidResult.error,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
results.push(`Generated Mermaid ER at: ${c.mermaid?.output}`);
|
|
60
|
-
}
|
|
61
|
-
return {
|
|
62
|
-
ok: true,
|
|
63
|
-
value: results.join('\n'),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
main().then((result) => {
|
|
67
|
-
if (result?.ok) {
|
|
68
|
-
console.log(result.value);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
console.error(result?.error);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Formats TypeScript source with Prettier.
|
|
3
|
-
*
|
|
4
|
-
* @param code - Source code to format.
|
|
5
|
-
* @returns A `Result` containing the formatted code or an error message.
|
|
6
|
-
*/
|
|
7
|
-
export declare function fmt(code: string): Promise<{
|
|
8
|
-
readonly ok: true;
|
|
9
|
-
readonly value: string;
|
|
10
|
-
} | {
|
|
11
|
-
readonly ok: false;
|
|
12
|
-
readonly error: string;
|
|
13
|
-
}>;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { format } from 'prettier';
|
|
2
|
-
/**
|
|
3
|
-
* Formats TypeScript source with Prettier.
|
|
4
|
-
*
|
|
5
|
-
* @param code - Source code to format.
|
|
6
|
-
* @returns A `Result` containing the formatted code or an error message.
|
|
7
|
-
*/
|
|
8
|
-
export async function fmt(code) {
|
|
9
|
-
try {
|
|
10
|
-
const result = await format(code, {
|
|
11
|
-
parser: 'typescript',
|
|
12
|
-
printWidth: 100,
|
|
13
|
-
singleQuote: true,
|
|
14
|
-
semi: false,
|
|
15
|
-
});
|
|
16
|
-
return { ok: true, value: result };
|
|
17
|
-
}
|
|
18
|
-
catch (e) {
|
|
19
|
-
return {
|
|
20
|
-
ok: false,
|
|
21
|
-
error: e instanceof Error ? e.message : String(e),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
}
|
package/dist/shared/fs/index.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
export function readFileSync(path) {
|
|
3
|
-
try {
|
|
4
|
-
const result = fs.readFileSync(path, 'utf-8');
|
|
5
|
-
return {
|
|
6
|
-
ok: true,
|
|
7
|
-
value: result,
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
catch (e) {
|
|
11
|
-
return {
|
|
12
|
-
ok: false,
|
|
13
|
-
error: e instanceof Error ? e.message : String(e),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a directory if it does not already exist.
|
|
3
|
-
*
|
|
4
|
-
* @param dir - Directory path to create.
|
|
5
|
-
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
6
|
-
*/
|
|
7
|
-
export declare function mkdir(dir: string): Promise<{
|
|
8
|
-
readonly ok: false;
|
|
9
|
-
readonly error: string;
|
|
10
|
-
} | {
|
|
11
|
-
readonly ok: true;
|
|
12
|
-
readonly value: undefined;
|
|
13
|
-
}>;
|
|
14
|
-
/**
|
|
15
|
-
* Writes UTF-8 text to a file, creating it if necessary.
|
|
16
|
-
*
|
|
17
|
-
* @param path - File path to write.
|
|
18
|
-
* @param data - Text data to write.
|
|
19
|
-
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
20
|
-
*/
|
|
21
|
-
export declare function writeFile(path: string, data: string): Promise<{
|
|
22
|
-
ok: true;
|
|
23
|
-
value: undefined;
|
|
24
|
-
} | {
|
|
25
|
-
ok: false;
|
|
26
|
-
error: string;
|
|
27
|
-
}>;
|
package/dist/shared/fsp/index.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import fsp from 'node:fs/promises';
|
|
2
|
-
/**
|
|
3
|
-
* Creates a directory if it does not already exist.
|
|
4
|
-
*
|
|
5
|
-
* @param dir - Directory path to create.
|
|
6
|
-
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
7
|
-
*/
|
|
8
|
-
export async function mkdir(dir) {
|
|
9
|
-
try {
|
|
10
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
11
|
-
return {
|
|
12
|
-
ok: true,
|
|
13
|
-
value: undefined,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
catch (e) {
|
|
17
|
-
return {
|
|
18
|
-
ok: false,
|
|
19
|
-
error: e instanceof Error ? e.message : String(e),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Writes UTF-8 text to a file, creating it if necessary.
|
|
25
|
-
*
|
|
26
|
-
* @param path - File path to write.
|
|
27
|
-
* @param data - Text data to write.
|
|
28
|
-
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
29
|
-
*/
|
|
30
|
-
export async function writeFile(path, data) {
|
|
31
|
-
try {
|
|
32
|
-
await fsp.writeFile(path, data, 'utf-8');
|
|
33
|
-
return { ok: true, value: undefined };
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param schema
|
|
3
|
-
* @returns
|
|
4
|
-
*/
|
|
5
|
-
export function fieldDefinitions(schema, comment) {
|
|
6
|
-
return schema.fields
|
|
7
|
-
.map(({ name, definition, description }) => {
|
|
8
|
-
const commentCode = description && comment ? `/**\n* ${description}\n*/\n` : '';
|
|
9
|
-
return `${commentCode}${name}:${definition}`;
|
|
10
|
-
})
|
|
11
|
-
.join(',\n');
|
|
12
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { Project, SourceFile, Node, SyntaxKind, JSDocTagInfo } from 'ts-morph';
|
|
2
|
-
import { Result, err, ok } from 'neverthrow';
|
|
3
|
-
import { extractComment, parseZodTag, parseValibotTag, parseRelationTag, toPascalCase } from '../utils/string-utils.js';
|
|
4
|
-
import { validateTableName, validateColumnName, validateRelationType } from '../utils/validation-utils.js';
|
|
5
|
-
export const parseSchemaFile = (filePath) => {
|
|
6
|
-
try {
|
|
7
|
-
const project = new Project();
|
|
8
|
-
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
9
|
-
const tables = [];
|
|
10
|
-
const relations = [];
|
|
11
|
-
// テーブル定義を解析
|
|
12
|
-
const tableExports = sourceFile.getExportedDeclarations();
|
|
13
|
-
for (const [name, declarations] of tableExports) {
|
|
14
|
-
if (name === 'userRelations' || name === 'postRelations')
|
|
15
|
-
continue;
|
|
16
|
-
const declaration = declarations[0];
|
|
17
|
-
if (!declaration || !Node.isVariableDeclaration(declaration))
|
|
18
|
-
continue;
|
|
19
|
-
const initializer = declaration.getInitializer();
|
|
20
|
-
if (!initializer || !Node.isCallExpression(initializer))
|
|
21
|
-
continue;
|
|
22
|
-
const callName = initializer.getExpression().getText();
|
|
23
|
-
if (!callName.includes('Table'))
|
|
24
|
-
continue;
|
|
25
|
-
const tableName = initializer.getArguments()[0]?.getText().replace(/['"]/g, '');
|
|
26
|
-
if (!tableName || !validateTableName(tableName))
|
|
27
|
-
continue;
|
|
28
|
-
const columns = parseTableColumns(initializer);
|
|
29
|
-
if (columns.isErr())
|
|
30
|
-
return err(columns.error);
|
|
31
|
-
tables.push({
|
|
32
|
-
name: tableName,
|
|
33
|
-
columns: columns.value,
|
|
34
|
-
relations: []
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
// リレーション定義を解析
|
|
38
|
-
const relationExports = sourceFile.getExportedDeclarations();
|
|
39
|
-
for (const [name, declarations] of relationExports) {
|
|
40
|
-
if (!name.includes('Relations'))
|
|
41
|
-
continue;
|
|
42
|
-
const declaration = declarations[0];
|
|
43
|
-
if (!declaration || !Node.isVariableDeclaration(declaration))
|
|
44
|
-
continue;
|
|
45
|
-
const initializer = declaration.getInitializer();
|
|
46
|
-
if (!initializer || !Node.isCallExpression(initializer))
|
|
47
|
-
continue;
|
|
48
|
-
const relation = parseRelation(initializer, tables.map(t => t.name));
|
|
49
|
-
if (relation.isOk()) {
|
|
50
|
-
relations.push(relation.value);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// リレーションをテーブルに割り当て
|
|
54
|
-
for (const relation of relations) {
|
|
55
|
-
const sourceTable = tables.find(t => t.name === relation.sourceTable);
|
|
56
|
-
const targetTable = tables.find(t => t.name === relation.targetTable);
|
|
57
|
-
if (sourceTable) {
|
|
58
|
-
sourceTable.relations.push(relation);
|
|
59
|
-
}
|
|
60
|
-
if (targetTable) {
|
|
61
|
-
targetTable.relations.push(relation);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return ok({ tables });
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
return err(new Error(`Failed to parse schema file: ${error instanceof Error ? error.message : String(error)}`));
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
const parseTableColumns = (tableCall) => {
|
|
71
|
-
try {
|
|
72
|
-
const columns = [];
|
|
73
|
-
const objectLiteral = tableCall.getArguments()[1];
|
|
74
|
-
if (!objectLiteral || !Node.isObjectLiteralExpression(objectLiteral)) {
|
|
75
|
-
return err(new Error('Invalid table definition'));
|
|
76
|
-
}
|
|
77
|
-
const properties = objectLiteral.getProperties();
|
|
78
|
-
for (const property of properties) {
|
|
79
|
-
if (!Node.isPropertyAssignment(property))
|
|
80
|
-
continue;
|
|
81
|
-
const propertyName = property.getName();
|
|
82
|
-
if (!validateColumnName(propertyName))
|
|
83
|
-
continue;
|
|
84
|
-
const initializer = property.getInitializer();
|
|
85
|
-
if (!initializer || !Node.isCallExpression(initializer))
|
|
86
|
-
continue;
|
|
87
|
-
const column = parseColumnDefinition(propertyName, initializer, property);
|
|
88
|
-
if (column.isOk()) {
|
|
89
|
-
columns.push(column.value);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return ok(columns);
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
return err(new Error(`Failed to parse table columns: ${error instanceof Error ? error.message : String(error)}`));
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const parseColumnDefinition = (name, columnCall, property) => {
|
|
99
|
-
try {
|
|
100
|
-
const callName = columnCall.getExpression().getText();
|
|
101
|
-
const args = columnCall.getArguments();
|
|
102
|
-
let type = 'unknown';
|
|
103
|
-
let length;
|
|
104
|
-
let isPrimary = false;
|
|
105
|
-
let isNullable = true;
|
|
106
|
-
// 型と長さを解析
|
|
107
|
-
if (callName.includes('varchar')) {
|
|
108
|
-
type = 'varchar';
|
|
109
|
-
if (args[1] && Node.isObjectLiteralExpression(args[1])) {
|
|
110
|
-
const lengthProp = args[1].getProperty('length');
|
|
111
|
-
if (lengthProp && Node.isPropertyAssignment(lengthProp)) {
|
|
112
|
-
const lengthValue = lengthProp.getInitializer();
|
|
113
|
-
if (lengthValue && Node.isNumericLiteral(lengthValue)) {
|
|
114
|
-
length = parseInt(lengthValue.getText());
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else if (callName.includes('int')) {
|
|
120
|
-
type = 'int';
|
|
121
|
-
}
|
|
122
|
-
else if (callName.includes('text')) {
|
|
123
|
-
type = 'text';
|
|
124
|
-
}
|
|
125
|
-
// メソッドチェーンを解析
|
|
126
|
-
let currentCall = columnCall;
|
|
127
|
-
while (currentCall.getParent() && Node.isCallExpression(currentCall.getParent())) {
|
|
128
|
-
currentCall = currentCall.getParent();
|
|
129
|
-
const methodName = currentCall.getExpression().getText();
|
|
130
|
-
if (methodName.includes('primaryKey')) {
|
|
131
|
-
isPrimary = true;
|
|
132
|
-
}
|
|
133
|
-
else if (methodName.includes('notNull')) {
|
|
134
|
-
isNullable = false;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
// JSDocコメントを解析
|
|
138
|
-
const jsDoc = property.getJsDocs()[0];
|
|
139
|
-
const comment = jsDoc ? extractComment(jsDoc.getText()) : undefined;
|
|
140
|
-
let zodSchema;
|
|
141
|
-
let valibotSchema;
|
|
142
|
-
if (jsDoc) {
|
|
143
|
-
const tags = jsDoc.getTags();
|
|
144
|
-
for (const tag of tags) {
|
|
145
|
-
const tagName = tag.getTagName();
|
|
146
|
-
const tagText = tag.getText();
|
|
147
|
-
if (tagName === 'z') {
|
|
148
|
-
zodSchema = parseZodTag(tagText);
|
|
149
|
-
}
|
|
150
|
-
else if (tagName === 'v') {
|
|
151
|
-
valibotSchema = parseValibotTag(tagText);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return ok({
|
|
156
|
-
name,
|
|
157
|
-
type,
|
|
158
|
-
isPrimary,
|
|
159
|
-
isNullable,
|
|
160
|
-
length,
|
|
161
|
-
zodSchema,
|
|
162
|
-
valibotSchema,
|
|
163
|
-
comment
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
167
|
-
return err(new Error(`Failed to parse column definition: ${error instanceof Error ? error.message : String(error)}`));
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
const parseRelation = (relationCall, tableNames) => {
|
|
171
|
-
try {
|
|
172
|
-
// リレーションコメントを探す
|
|
173
|
-
const jsDoc = relationCall.getJsDocs()[0];
|
|
174
|
-
if (!jsDoc)
|
|
175
|
-
return err(new Error('No relation comment found'));
|
|
176
|
-
const relationText = parseRelationTag(jsDoc.getText());
|
|
177
|
-
const parts = relationText.split(' ');
|
|
178
|
-
if (parts.length < 4)
|
|
179
|
-
return err(new Error('Invalid relation format'));
|
|
180
|
-
const sourceTable = parts[0];
|
|
181
|
-
const sourceColumn = parts[1];
|
|
182
|
-
const targetTable = parts[2];
|
|
183
|
-
const targetColumn = parts[3];
|
|
184
|
-
const type = parts[4] || 'one-to-many';
|
|
185
|
-
if (!validateRelationType(type)) {
|
|
186
|
-
return err(new Error(`Invalid relation type: ${type}`));
|
|
187
|
-
}
|
|
188
|
-
if (!tableNames.includes(sourceTable) || !tableNames.includes(targetTable)) {
|
|
189
|
-
return err(new Error(`Table not found in relation: ${sourceTable} -> ${targetTable}`));
|
|
190
|
-
}
|
|
191
|
-
return ok({
|
|
192
|
-
sourceTable,
|
|
193
|
-
sourceColumn,
|
|
194
|
-
targetTable,
|
|
195
|
-
targetColumn,
|
|
196
|
-
type
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
return err(new Error(`Failed to parse relation: ${error instanceof Error ? error.message : String(error)}`));
|
|
201
|
-
}
|
|
202
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { CallExpression } from 'ts-morph';
|
|
2
|
-
import { Node } from 'ts-morph';
|
|
3
|
-
/**
|
|
4
|
-
* Creates a schema extractor from customizable strategies.
|
|
5
|
-
*
|
|
6
|
-
* @param extractFieldsFromCall - Function to extract fields from a call expression (e.g. mysqlTable(...)).
|
|
7
|
-
* @param extractFieldFromProperty - Function to extract a single field from an object literal property.
|
|
8
|
-
* @returns A function that extracts a schema from a variable declaration node.
|
|
9
|
-
*/
|
|
10
|
-
export declare function buildSchemaExtractor(extractFieldsFromCall: (call: CallExpression, sourceText: string) => {
|
|
11
|
-
name: string;
|
|
12
|
-
definition: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
}[], extractFieldFromProperty: (prop: Node, sourceText: string) => {
|
|
15
|
-
name: string;
|
|
16
|
-
definition: string;
|
|
17
|
-
description?: string;
|
|
18
|
-
} | null): (declaration: Node, sourceText: string) => {
|
|
19
|
-
name: string;
|
|
20
|
-
fields: {
|
|
21
|
-
name: string;
|
|
22
|
-
definition: string;
|
|
23
|
-
description?: string;
|
|
24
|
-
}[];
|
|
25
|
-
} | null;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
2
|
-
import { isRelationFunctionCall } from '../../shared/helper/is-relation-function.js';
|
|
3
|
-
/**
|
|
4
|
-
* Creates a schema extractor from customizable strategies.
|
|
5
|
-
*
|
|
6
|
-
* @param extractFieldsFromCall - Function to extract fields from a call expression (e.g. mysqlTable(...)).
|
|
7
|
-
* @param extractFieldFromProperty - Function to extract a single field from an object literal property.
|
|
8
|
-
* @returns A function that extracts a schema from a variable declaration node.
|
|
9
|
-
*/
|
|
10
|
-
export function buildSchemaExtractor(extractFieldsFromCall, extractFieldFromProperty) {
|
|
11
|
-
return (declaration, sourceText) => {
|
|
12
|
-
if (!Node.isVariableDeclaration(declaration))
|
|
13
|
-
return null;
|
|
14
|
-
const name = declaration.getName();
|
|
15
|
-
if (!name)
|
|
16
|
-
return null;
|
|
17
|
-
const initializer = declaration.getInitializer();
|
|
18
|
-
if (Node.isCallExpression(initializer)) {
|
|
19
|
-
if (isRelationFunctionCall(initializer))
|
|
20
|
-
return null;
|
|
21
|
-
const fields = extractFieldsFromCall(initializer, sourceText);
|
|
22
|
-
return { name, fields };
|
|
23
|
-
}
|
|
24
|
-
if (Node.isObjectLiteralExpression(initializer)) {
|
|
25
|
-
const fields = initializer
|
|
26
|
-
.getProperties()
|
|
27
|
-
.map((prop) => extractFieldFromProperty(prop, sourceText))
|
|
28
|
-
.filter((field) => field !== null);
|
|
29
|
-
return { name, fields };
|
|
30
|
-
}
|
|
31
|
-
return { name, fields: [] };
|
|
32
|
-
};
|
|
33
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
2
|
-
/**
|
|
3
|
-
* Creates a field extractor function using a custom parseFieldComments implementation.
|
|
4
|
-
*
|
|
5
|
-
* @param parseFieldComments - A function that parses comment lines into { definition, description }
|
|
6
|
-
* @returns A property node extractor function.
|
|
7
|
-
*/
|
|
8
|
-
export declare function createExtractFieldFromProperty(parseFieldComments: (commentLines: string[]) => {
|
|
9
|
-
definition: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
}): (property: Node, sourceText: string) => {
|
|
12
|
-
name: string;
|
|
13
|
-
definition: string;
|
|
14
|
-
description?: string;
|
|
15
|
-
} | null;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
2
|
-
import { extractFieldComments } from '../../shared/utils/index.js';
|
|
3
|
-
/**
|
|
4
|
-
* Creates a field extractor function using a custom parseFieldComments implementation.
|
|
5
|
-
*
|
|
6
|
-
* @param parseFieldComments - A function that parses comment lines into { definition, description }
|
|
7
|
-
* @returns A property node extractor function.
|
|
8
|
-
*/
|
|
9
|
-
export function createExtractFieldFromProperty(parseFieldComments) {
|
|
10
|
-
return (property, sourceText) => {
|
|
11
|
-
if (!Node.isPropertyAssignment(property))
|
|
12
|
-
return null;
|
|
13
|
-
const name = property.getName();
|
|
14
|
-
if (!name)
|
|
15
|
-
return null;
|
|
16
|
-
const commentLines = extractFieldComments(sourceText, property.getStart());
|
|
17
|
-
const { definition, description } = parseFieldComments(commentLines);
|
|
18
|
-
return { name, definition, description };
|
|
19
|
-
};
|
|
20
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { CallExpression, Node, ObjectLiteralExpression } from 'ts-morph';
|
|
2
|
-
export declare function createExtractFieldsFromCallExpression(extractFieldFromProperty: (property: Node, sourceText: string) => {
|
|
3
|
-
name: string;
|
|
4
|
-
definition: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
} | null, extractRelationFieldFromProperty: (property: Node, sourceText: string) => {
|
|
7
|
-
name: string;
|
|
8
|
-
definition: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
} | null, findObjectLiteralExpression: (expr: Node) => ObjectLiteralExpression | null, findObjectLiteralInArgs: (call: CallExpression, finder: (expr: Node) => ObjectLiteralExpression | null) => ObjectLiteralExpression | null, isRelationFunctionCall: (call: CallExpression) => boolean): (callExpr: CallExpression, sourceText: string) => {
|
|
11
|
-
name: string;
|
|
12
|
-
definition: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
}[];
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function createExtractFieldsFromCallExpression(extractFieldFromProperty, extractRelationFieldFromProperty, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall) {
|
|
2
|
-
return (callExpr, sourceText) => {
|
|
3
|
-
const objectLiteral = findObjectLiteralInArgs(callExpr, findObjectLiteralExpression);
|
|
4
|
-
if (!objectLiteral)
|
|
5
|
-
return [];
|
|
6
|
-
const isRelation = isRelationFunctionCall(callExpr);
|
|
7
|
-
return objectLiteral
|
|
8
|
-
.getProperties()
|
|
9
|
-
.map((prop) => isRelation
|
|
10
|
-
? extractRelationFieldFromProperty(prop, sourceText)
|
|
11
|
-
: extractFieldFromProperty(prop, sourceText))
|
|
12
|
-
.filter((field) => field !== null);
|
|
13
|
-
};
|
|
14
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
2
|
-
export declare const createExtractRelationFieldFromProperty: (parseFieldComments: (lines: string[]) => {
|
|
3
|
-
definition: string;
|
|
4
|
-
description?: string;
|
|
5
|
-
}, prefix: "v" | "z") => (property: Node, sourceText: string) => {
|
|
6
|
-
name: string;
|
|
7
|
-
fields: {
|
|
8
|
-
name: string;
|
|
9
|
-
definition: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
}[];
|
|
12
|
-
}["fields"][0] | null;
|