sizuku 0.0.7 → 0.2.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 +96 -344
- package/dist/cli/main.d.ts +10 -0
- package/dist/cli/main.js +61 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +51 -0
- package/dist/config/index.d.ts +18 -0
- package/dist/config/index.js +13 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +30 -0
- package/dist/generator/engine.d.ts +3 -0
- package/dist/generator/engine.js +63 -0
- package/dist/generator/mermaid-er/config/index.d.ts +4 -4
- package/dist/generator/mermaid-er/config/index.js +4 -10
- package/dist/generator/mermaid-er/core/extract-relations.d.ts +1 -1
- package/dist/generator/mermaid-er/core/extract-relations.js +3 -6
- package/dist/generator/mermaid-er/core.d.ts +6 -0
- package/dist/generator/mermaid-er/core.js +54 -0
- package/dist/generator/mermaid-er/generator/er-content.d.ts +20 -0
- package/dist/generator/mermaid-er/generator/{generate-er-content.js → er-content.js} +3 -7
- package/dist/generator/mermaid-er/generator/index.d.ts +2 -0
- package/dist/generator/mermaid-er/generator/index.js +2 -0
- package/dist/generator/mermaid-er/generator/relation-line.d.ts +12 -0
- package/dist/generator/mermaid-er/generator/{generate-relation-line.js → relation-line.js} +3 -6
- package/dist/generator/mermaid-er/generator.d.ts +3 -0
- package/dist/generator/mermaid-er/generator.js +14 -0
- package/dist/generator/mermaid-er/index.d.ts +12 -5
- package/dist/generator/mermaid-er/index.js +30 -74
- package/dist/generator/mermaid-er/relationship/build-relation-line.js +3 -6
- package/dist/generator/mermaid-er/types.js +1 -0
- package/dist/generator/mermaid-er/validator/index.d.ts +8 -0
- package/dist/generator/mermaid-er/validator/index.js +71 -0
- package/dist/generator/mermaid-er/validator/is-relationship.d.ts +1 -1
- package/dist/generator/mermaid-er/validator/is-relationship.js +1 -4
- package/dist/generator/mermaid-er/validator/parse-relation-line.js +1 -4
- package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +1 -7
- package/dist/generator/mermaid-er/validator/parse-table-info.js +69 -89
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +1 -4
- package/dist/generator/valibot/config/index.d.ts +2 -2
- package/dist/generator/valibot/config/index.js +6 -12
- package/dist/generator/valibot/core/extract-schema.d.ts +2 -5
- package/dist/generator/valibot/core/extract-schema.js +162 -81
- package/dist/generator/valibot/core.d.ts +5 -0
- package/dist/generator/valibot/core.js +39 -0
- package/dist/generator/valibot/generator/infer-input.d.ts +5 -0
- package/dist/generator/valibot/generator/infer-input.js +8 -0
- package/dist/generator/valibot/generator/relation-valibot-code.d.ts +13 -0
- package/dist/generator/valibot/generator/relation-valibot-code.js +19 -0
- package/dist/generator/valibot/generator/valibot-code.d.ts +15 -0
- package/dist/generator/valibot/generator/valibot-code.js +16 -0
- package/dist/generator/valibot/generator/valibot.d.ts +14 -0
- package/dist/generator/valibot/generator/valibot.js +15 -0
- package/dist/generator/valibot/generator.d.ts +3 -0
- package/dist/generator/valibot/generator.js +14 -0
- package/dist/generator/valibot/index.d.ts +14 -3
- package/dist/generator/valibot/index.js +46 -73
- package/dist/generator/zod/config/index.d.ts +2 -2
- package/dist/generator/zod/config/index.js +6 -12
- package/dist/generator/zod/core/extract-schema.d.ts +1 -2
- package/dist/generator/zod/core/extract-schema.js +228 -81
- package/dist/generator/zod/core.d.ts +5 -0
- package/dist/generator/zod/core.js +39 -0
- package/dist/generator/zod/generator/infer.d.ts +5 -0
- package/dist/generator/zod/generator/infer.js +8 -0
- package/dist/generator/zod/generator/relation-zod-code.d.ts +13 -0
- package/dist/generator/zod/generator/relation-zod-code.js +19 -0
- package/dist/generator/zod/generator/zod-code.d.ts +17 -0
- package/dist/generator/zod/generator/zod-code.js +18 -0
- package/dist/generator/zod/generator/zod.d.ts +16 -0
- package/dist/generator/zod/generator/zod.js +16 -0
- package/dist/generator/zod/generator.d.ts +3 -0
- package/dist/generator/zod/generator.js +14 -0
- package/dist/generator/zod/index.d.ts +15 -3
- package/dist/generator/zod/index.js +50 -73
- package/dist/index.d.ts +8 -0
- package/dist/index.js +71 -0
- package/dist/shared/config/index.d.ts +13 -0
- package/dist/{common → shared}/config/index.js +1 -4
- package/dist/shared/format/index.d.ts +15 -0
- package/dist/shared/format/index.js +24 -0
- package/dist/shared/fs/index.d.ts +7 -0
- package/dist/shared/fs/index.js +16 -0
- package/dist/shared/fsp/index.d.ts +27 -0
- package/dist/shared/fsp/index.js +38 -0
- package/dist/shared/generator/field-definitions.d.ts +12 -0
- package/dist/shared/generator/field-definitions.js +12 -0
- package/dist/shared/helper/ast-parser.d.ts +3 -0
- package/dist/shared/helper/ast-parser.js +202 -0
- package/dist/shared/helper/build-schema-extractor.d.ts +25 -0
- package/dist/shared/helper/build-schema-extractor.js +33 -0
- package/dist/shared/helper/create-extract-field-from-property.d.ts +15 -0
- package/dist/shared/helper/create-extract-field-from-property.js +20 -0
- package/dist/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
- package/dist/shared/helper/create-extract-fields-from-call-expression.js +14 -0
- package/dist/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
- package/dist/shared/helper/create-extract-relation-field-from-property.js +27 -0
- package/dist/shared/helper/extract-schemas.d.ts +133 -0
- package/dist/shared/helper/extract-schemas.js +445 -0
- package/dist/shared/helper/file-writer.d.ts +3 -0
- package/dist/shared/helper/file-writer.js +25 -0
- package/dist/shared/helper/find-object-literal-expression.d.ts +12 -0
- package/dist/shared/helper/find-object-literal-expression.js +31 -0
- package/dist/shared/helper/find-object-literalIn-args.d.ts +2 -0
- package/dist/shared/helper/find-object-literalIn-args.js +8 -0
- package/dist/shared/helper/is-relation-function.d.ts +10 -0
- package/dist/shared/helper/is-relation-function.js +16 -0
- package/dist/shared/types.js +1 -0
- package/dist/{common/text → shared/utils}/capitalize.js +1 -4
- package/dist/shared/utils/compose.d.ts +101 -0
- package/dist/shared/utils/compose.js +124 -0
- package/dist/shared/utils/file.d.ts +92 -0
- package/dist/shared/utils/file.js +177 -0
- package/dist/shared/utils/functional.d.ts +118 -0
- package/dist/shared/utils/functional.js +96 -0
- package/dist/shared/utils/index.d.ts +20 -0
- package/dist/shared/utils/index.js +48 -0
- package/dist/shared/utils/string-utils.d.ts +8 -0
- package/dist/shared/utils/string-utils.js +28 -0
- package/dist/shared/utils/types.d.ts +32 -0
- package/dist/shared/utils/types.js +2 -0
- package/dist/shared/utils/validation-utils.d.ts +8 -0
- package/dist/shared/utils/validation-utils.js +25 -0
- package/dist/src/config/index.d.ts +18 -0
- package/dist/src/config/index.js +13 -0
- package/dist/src/generator/mermaid-er/core/extract-relations.d.ts +8 -0
- package/dist/src/generator/mermaid-er/core/extract-relations.js +12 -0
- package/dist/src/generator/mermaid-er/generator/er-content.d.ts +9 -0
- package/dist/src/generator/mermaid-er/generator/er-content.js +25 -0
- package/dist/src/generator/mermaid-er/generator/index.d.ts +2 -0
- package/dist/src/generator/mermaid-er/generator/index.js +2 -0
- package/dist/src/generator/mermaid-er/generator/relation-line.d.ts +8 -0
- package/dist/src/generator/mermaid-er/generator/relation-line.js +14 -0
- package/dist/src/generator/mermaid-er/index.d.ts +6 -0
- package/dist/src/generator/mermaid-er/index.js +16 -0
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.d.ts +15 -0
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.js +35 -0
- package/dist/src/generator/mermaid-er/types.d.ts +21 -0
- package/dist/src/generator/mermaid-er/types.js +1 -0
- package/dist/src/generator/mermaid-er/validator/index.d.ts +4 -0
- package/dist/src/generator/mermaid-er/validator/index.js +4 -0
- package/dist/src/generator/mermaid-er/validator/is-relationship.d.ts +8 -0
- package/dist/src/generator/mermaid-er/validator/is-relationship.js +9 -0
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.d.ts +13 -0
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.js +21 -0
- package/dist/src/generator/mermaid-er/validator/parse-table-info.d.ts +8 -0
- package/dist/src/generator/mermaid-er/validator/parse-table-info.js +91 -0
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +7 -0
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.js +9 -0
- package/dist/src/generator/valibot/generator/infer-input.d.ts +5 -0
- package/dist/src/generator/valibot/generator/infer-input.js +8 -0
- package/dist/src/generator/valibot/generator/valibot-code.d.ts +14 -0
- package/dist/src/generator/valibot/generator/valibot-code.js +16 -0
- package/dist/src/generator/valibot/generator/valibot.d.ts +13 -0
- package/dist/src/generator/valibot/generator/valibot.js +11 -0
- package/dist/src/generator/valibot/index.d.ts +9 -0
- package/dist/src/generator/valibot/index.js +34 -0
- package/dist/src/generator/zod/generator/infer.d.ts +5 -0
- package/dist/src/generator/zod/generator/infer.js +8 -0
- package/dist/{generator/zod/generator/generate-zod-code.d.ts → src/generator/zod/generator/zod-code.d.ts} +8 -3
- package/dist/src/generator/zod/generator/zod-code.js +18 -0
- package/dist/{generator/zod/generator/generate-zod-schema.d.ts → src/generator/zod/generator/zod.d.ts} +8 -4
- package/dist/src/generator/zod/generator/zod.js +12 -0
- package/dist/src/generator/zod/index.d.ts +10 -0
- package/dist/src/generator/zod/index.js +40 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +35 -0
- package/dist/src/shared/format/index.d.ts +2 -0
- package/dist/src/shared/format/index.js +10 -0
- package/dist/src/shared/fs/index.d.ts +2 -0
- package/dist/src/shared/fs/index.js +10 -0
- package/dist/src/shared/fsp/index.d.ts +3 -0
- package/dist/src/shared/fsp/index.js +8 -0
- package/dist/src/shared/generator/field-definitions.d.ts +12 -0
- package/dist/src/shared/generator/field-definitions.js +12 -0
- package/dist/src/shared/helper/build-schema-extractor.d.ts +25 -0
- package/dist/src/shared/helper/build-schema-extractor.js +33 -0
- package/dist/src/shared/helper/create-extract-field-from-property.d.ts +15 -0
- package/dist/src/shared/helper/create-extract-field-from-property.js +20 -0
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.js +14 -0
- package/dist/src/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
- package/dist/src/shared/helper/create-extract-relation-field-from-property.js +27 -0
- package/dist/src/shared/helper/extract-schemas.d.ts +16 -0
- package/dist/src/shared/helper/extract-schemas.js +19 -0
- package/dist/src/shared/helper/find-object-literal-expression.d.ts +12 -0
- package/dist/src/shared/helper/find-object-literal-expression.js +31 -0
- package/dist/src/shared/helper/find-object-literalIn-args.d.ts +2 -0
- package/dist/src/shared/helper/find-object-literalIn-args.js +8 -0
- package/dist/src/shared/helper/is-relation-function.d.ts +10 -0
- package/dist/src/shared/helper/is-relation-function.js +16 -0
- package/dist/src/shared/utils/index.d.ts +33 -0
- package/dist/src/shared/utils/index.js +61 -0
- package/dist/utils/index.d.ts +144 -0
- package/dist/utils/index.js +301 -0
- package/package.json +10 -13
- package/dist/common/config/index.d.ts +0 -13
- package/dist/common/format/index.d.ts +0 -1
- package/dist/common/format/index.js +0 -12
- package/dist/common/generator/generate-field-definitions.d.ts +0 -8
- package/dist/common/generator/generate-field-definitions.js +0 -16
- package/dist/common/helper/get-camel-case-schema-name-helper.d.ts +0 -7
- package/dist/common/helper/get-camel-case-schema-name-helper.js +0 -14
- package/dist/common/helper/get-pascal-case-schema-name-helper.d.ts +0 -8
- package/dist/common/helper/get-pascal-case-schema-name-helper.js +0 -15
- package/dist/common/helper/get-variable-name-helper.d.ts +0 -9
- package/dist/common/helper/get-variable-name-helper.js +0 -15
- package/dist/common/helper/get-variable-schema-name-helper.d.ts +0 -9
- package/dist/common/helper/get-variable-schema-name-helper.js +0 -17
- package/dist/common/text/decapitalize.d.ts +0 -17
- package/dist/common/text/decapitalize.js +0 -22
- package/dist/common/type/index.js +0 -2
- package/dist/generator/mermaid-er/generator/generate-er-content.d.ts +0 -9
- package/dist/generator/mermaid-er/generator/generate-relation-line.d.ts +0 -7
- package/dist/generator/mermaid-er/type/index.js +0 -2
- package/dist/generator/mermaid-er/validator/is-relation.d.ts +0 -7
- package/dist/generator/mermaid-er/validator/is-relation.js +0 -40
- package/dist/generator/valibot/generator/generate-valibot-code.d.ts +0 -11
- package/dist/generator/valibot/generator/generate-valibot-code.js +0 -21
- package/dist/generator/valibot/generator/generate-valibot-infer-input.d.ts +0 -9
- package/dist/generator/valibot/generator/generate-valibot-infer-input.js +0 -16
- package/dist/generator/valibot/generator/generate-valibot-schema.d.ts +0 -9
- package/dist/generator/valibot/generator/generate-valibot-schema.js +0 -16
- package/dist/generator/zod/generator/generate-z-infer.d.ts +0 -11
- package/dist/generator/zod/generator/generate-z-infer.js +0 -18
- package/dist/generator/zod/generator/generate-zod-code.js +0 -21
- package/dist/generator/zod/generator/generate-zod-schema.js +0 -17
- /package/dist/generator/mermaid-er/{type/index.d.ts → types.d.ts} +0 -0
- /package/dist/{common/type/index.d.ts → shared/types.d.ts} +0 -0
- /package/dist/{common/text → shared/utils}/capitalize.d.ts +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
export function getConfig() {
|
|
3
|
+
if (!fs.existsSync('sizuku.json')) {
|
|
4
|
+
throw new Error('sizuku.json not found');
|
|
5
|
+
}
|
|
6
|
+
const parsed = JSON.parse(fs.readFileSync('sizuku.json', 'utf-8'));
|
|
7
|
+
return {
|
|
8
|
+
input: parsed.input,
|
|
9
|
+
zod: parsed.zod,
|
|
10
|
+
valibot: parsed.valibot,
|
|
11
|
+
mermaid: parsed.mermaid,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Result } from 'neverthrow';
|
|
2
|
+
export type SizukuConfig = {
|
|
3
|
+
input: string;
|
|
4
|
+
zod?: {
|
|
5
|
+
output: string;
|
|
6
|
+
comment?: boolean;
|
|
7
|
+
type?: boolean;
|
|
8
|
+
};
|
|
9
|
+
valibot?: {
|
|
10
|
+
output: string;
|
|
11
|
+
comment?: boolean;
|
|
12
|
+
type?: boolean;
|
|
13
|
+
};
|
|
14
|
+
mermaid?: {
|
|
15
|
+
output: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare const loadConfig: (configPath: string) => Promise<Result<SizukuConfig, Error>>;
|
|
19
|
+
export declare const validateConfig: (config: SizukuConfig) => Result<SizukuConfig, Error>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { Result, err, ok } from 'neverthrow';
|
|
3
|
+
export const loadConfig = async (configPath) => {
|
|
4
|
+
try {
|
|
5
|
+
const configContent = await readFile(configPath, 'utf-8');
|
|
6
|
+
const config = JSON.parse(configContent);
|
|
7
|
+
// 基本的なバリデーション
|
|
8
|
+
if (!config.input) {
|
|
9
|
+
return err(new Error('Config must specify input file path'));
|
|
10
|
+
}
|
|
11
|
+
return ok(config);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return err(new Error(`Failed to load config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`));
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const validateConfig = (config) => {
|
|
18
|
+
try {
|
|
19
|
+
if (!config.input) {
|
|
20
|
+
return err(new Error('Input file path is required'));
|
|
21
|
+
}
|
|
22
|
+
if (!config.zod && !config.valibot && !config.mermaid) {
|
|
23
|
+
return err(new Error('At least one output format must be specified (zod, valibot, or mermaid)'));
|
|
24
|
+
}
|
|
25
|
+
return ok(config);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return err(new Error(`Config validation failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Result, err, ok } from 'neverthrow';
|
|
2
|
+
import { parseSchemaFile } from '../shared/helper/ast-parser.js';
|
|
3
|
+
import { generateZodSchemas } from './zod/generator.js';
|
|
4
|
+
import { generateValibotSchemas } from './valibot/generator.js';
|
|
5
|
+
import { generateMermaidERDiagram } from './mermaid-er/generator.js';
|
|
6
|
+
import { writeFileSafely } from '../shared/helper/file-writer.js';
|
|
7
|
+
export const generateSchemas = async (config) => {
|
|
8
|
+
try {
|
|
9
|
+
// スキーマファイルを解析
|
|
10
|
+
const parseResult = await parseSchemaFile(config.input);
|
|
11
|
+
if (parseResult.isErr()) {
|
|
12
|
+
return err(parseResult.error);
|
|
13
|
+
}
|
|
14
|
+
const schema = parseResult.value;
|
|
15
|
+
// 各フォーマットを生成
|
|
16
|
+
const results = [];
|
|
17
|
+
if (config.zod) {
|
|
18
|
+
results.push(generateZodOutput(schema, config.zod.output));
|
|
19
|
+
}
|
|
20
|
+
if (config.valibot) {
|
|
21
|
+
results.push(generateValibotOutput(schema, config.valibot.output));
|
|
22
|
+
}
|
|
23
|
+
if (config.mermaid) {
|
|
24
|
+
results.push(generateMermaidOutput(schema, config.mermaid.output));
|
|
25
|
+
}
|
|
26
|
+
// すべての生成を待機
|
|
27
|
+
const generationResults = await Promise.all(results);
|
|
28
|
+
// エラーがあれば最初のエラーを返す
|
|
29
|
+
for (const result of generationResults) {
|
|
30
|
+
if (result.isErr()) {
|
|
31
|
+
return err(result.error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return ok(undefined);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return err(new Error(`Schema generation failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const generateZodOutput = async (schema, outputPath) => {
|
|
41
|
+
const zodResult = generateZodSchemas(schema);
|
|
42
|
+
if (zodResult.isErr()) {
|
|
43
|
+
return err(zodResult.error);
|
|
44
|
+
}
|
|
45
|
+
const writeResult = await writeFileSafely(outputPath, zodResult.value);
|
|
46
|
+
return writeResult;
|
|
47
|
+
};
|
|
48
|
+
const generateValibotOutput = async (schema, outputPath) => {
|
|
49
|
+
const valibotResult = generateValibotSchemas(schema);
|
|
50
|
+
if (valibotResult.isErr()) {
|
|
51
|
+
return err(valibotResult.error);
|
|
52
|
+
}
|
|
53
|
+
const writeResult = await writeFileSafely(outputPath, valibotResult.value);
|
|
54
|
+
return writeResult;
|
|
55
|
+
};
|
|
56
|
+
const generateMermaidOutput = async (schema, outputPath) => {
|
|
57
|
+
const mermaidResult = generateMermaidERDiagram(schema);
|
|
58
|
+
if (mermaidResult.isErr()) {
|
|
59
|
+
return err(mermaidResult.error);
|
|
60
|
+
}
|
|
61
|
+
const writeResult = await writeFileSafely(outputPath, mermaidResult.value);
|
|
62
|
+
return writeResult;
|
|
63
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export type Config = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
2
|
+
input?: string
|
|
3
|
+
output?: string
|
|
4
|
+
}
|
|
5
5
|
/**
|
|
6
6
|
* Loads the configuration from the `sizuku.json` file or returns the default configuration.
|
|
7
7
|
*
|
|
8
8
|
* @returns The configuration object.
|
|
9
9
|
*/
|
|
10
|
-
export declare function getConfig(): Config
|
|
10
|
+
export declare function getConfig(): Config
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
|
|
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"));
|
|
1
|
+
import fs from 'node:fs';
|
|
8
2
|
/**
|
|
9
3
|
* Loads the configuration from the `sizuku.json` file or returns the default configuration.
|
|
10
4
|
*
|
|
11
5
|
* @returns The configuration object.
|
|
12
6
|
*/
|
|
13
|
-
function getConfig() {
|
|
14
|
-
const config =
|
|
15
|
-
? { ...JSON.parse(
|
|
7
|
+
export function getConfig() {
|
|
8
|
+
const config = fs.existsSync('sizuku-mermaid-er.json')
|
|
9
|
+
? { ...JSON.parse(fs.readFileSync('sizuku-mermaid-er.json', 'utf-8')) }
|
|
16
10
|
: {};
|
|
17
11
|
return config;
|
|
18
12
|
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractRelations = extractRelations;
|
|
4
|
-
const parse_relation_line_1 = require("../validator/parse-relation-line");
|
|
1
|
+
import { parseRelationLine } from '../validator/parse-relation-line.js';
|
|
5
2
|
/**
|
|
6
3
|
* Extracts relations from the given code.
|
|
7
4
|
*
|
|
8
5
|
* @param code - The code to extract relations from.
|
|
9
6
|
* @returns The extracted relations.
|
|
10
7
|
*/
|
|
11
|
-
function extractRelations(code) {
|
|
8
|
+
export function extractRelations(code) {
|
|
12
9
|
const relations = [];
|
|
13
10
|
for (const line of code) {
|
|
14
|
-
const relation =
|
|
11
|
+
const relation = parseRelationLine(line);
|
|
15
12
|
if (relation) {
|
|
16
13
|
relations.push(relation);
|
|
17
14
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TableInfo, ColumnInfo, RelationInfo } from '../../shared/utils/types.js';
|
|
2
|
+
export declare const generateMermaidER: (tables: TableInfo[]) => string;
|
|
3
|
+
export declare const generateRelations: (tables: TableInfo[]) => string;
|
|
4
|
+
export declare const generateRelationLine: (relation: RelationInfo) => string;
|
|
5
|
+
export declare const generateEntity: (table: TableInfo) => string;
|
|
6
|
+
export declare const generateColumnDefinition: (column: ColumnInfo) => string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// 完全純粋なMermaid ER図生成ユーティリティ - 外部import禁止
|
|
2
|
+
export const generateMermaidER = (tables) => {
|
|
3
|
+
const header = 'erDiagram';
|
|
4
|
+
const relations = generateRelations(tables);
|
|
5
|
+
const entities = tables.map(table => generateEntity(table)).join('\n ');
|
|
6
|
+
return `${header}
|
|
7
|
+
${relations}
|
|
8
|
+
${entities}`;
|
|
9
|
+
};
|
|
10
|
+
export const generateRelations = (tables) => {
|
|
11
|
+
const relations = [];
|
|
12
|
+
for (const table of tables) {
|
|
13
|
+
for (const relation of table.relations) {
|
|
14
|
+
const relationLine = generateRelationLine(relation);
|
|
15
|
+
if (relationLine) {
|
|
16
|
+
relations.push(relationLine);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return relations.join('\n ');
|
|
21
|
+
};
|
|
22
|
+
export const generateRelationLine = (relation) => {
|
|
23
|
+
const sourceTable = relation.sourceTable;
|
|
24
|
+
const targetTable = relation.targetTable;
|
|
25
|
+
const sourceColumn = relation.sourceColumn;
|
|
26
|
+
const targetColumn = relation.targetColumn;
|
|
27
|
+
if (relation.type === 'one-to-many') {
|
|
28
|
+
return `${sourceTable} ||--}| ${targetTable} : "(${sourceColumn}) - (${targetColumn})"`;
|
|
29
|
+
}
|
|
30
|
+
else if (relation.type === 'many-to-one') {
|
|
31
|
+
return `${targetTable} ||--}| ${sourceTable} : "(${targetColumn}) - (${sourceColumn})"`;
|
|
32
|
+
}
|
|
33
|
+
else if (relation.type === 'one-to-one') {
|
|
34
|
+
return `${sourceTable} ||--|| ${targetTable} : "(${sourceColumn}) - (${targetColumn})"`;
|
|
35
|
+
}
|
|
36
|
+
else if (relation.type === 'many-to-many') {
|
|
37
|
+
return `${sourceTable} }|--|{ ${targetTable} : "(${sourceColumn}) - (${targetColumn})"`;
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
};
|
|
41
|
+
export const generateEntity = (table) => {
|
|
42
|
+
const columns = table.columns.map(column => generateColumnDefinition(column)).join('\n ');
|
|
43
|
+
return `${table.name} {
|
|
44
|
+
${columns}
|
|
45
|
+
}`;
|
|
46
|
+
};
|
|
47
|
+
export const generateColumnDefinition = (column) => {
|
|
48
|
+
const type = column.type;
|
|
49
|
+
const name = column.name;
|
|
50
|
+
const comment = column.comment || '';
|
|
51
|
+
const primaryKey = column.isPrimary ? ' (PK)' : '';
|
|
52
|
+
const nullable = column.isNullable ? '' : ' NOT NULL';
|
|
53
|
+
return `${type} ${name}${primaryKey}${nullable} "${comment}"`;
|
|
54
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate ER content
|
|
3
|
+
* @param relations - The relations to generate the ER content from
|
|
4
|
+
* @param tables - The tables to generate the ER content from
|
|
5
|
+
* @returns The generated ER content
|
|
6
|
+
*/
|
|
7
|
+
export declare function erContent(relations: {
|
|
8
|
+
fromModel: string;
|
|
9
|
+
toModel: string;
|
|
10
|
+
fromField: string;
|
|
11
|
+
toField: string;
|
|
12
|
+
type: string;
|
|
13
|
+
}[], tables: {
|
|
14
|
+
name: string;
|
|
15
|
+
fields: {
|
|
16
|
+
type: string;
|
|
17
|
+
name: string;
|
|
18
|
+
description: string | null;
|
|
19
|
+
}[];
|
|
20
|
+
}[]): string;
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateERContent = generateERContent;
|
|
4
|
-
const generate_relation_line_1 = require("./generate-relation-line");
|
|
1
|
+
import { relationLine } from './index.js';
|
|
5
2
|
const ER_HEADER = ['```mermaid', 'erDiagram'];
|
|
6
3
|
const ER_FOOTER = ['```'];
|
|
7
4
|
/**
|
|
8
5
|
* Generate ER content
|
|
9
|
-
* @function generateERContent
|
|
10
6
|
* @param relations - The relations to generate the ER content from
|
|
11
7
|
* @param tables - The tables to generate the ER content from
|
|
12
8
|
* @returns The generated ER content
|
|
13
9
|
*/
|
|
14
|
-
function
|
|
10
|
+
export function erContent(relations, tables) {
|
|
15
11
|
const erContent = [
|
|
16
12
|
...ER_HEADER,
|
|
17
|
-
...relations.map(
|
|
13
|
+
...relations.map(relationLine),
|
|
18
14
|
// Generate per-table definitions
|
|
19
15
|
...tables.flatMap((table) => [
|
|
20
16
|
` ${table.name} {`,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a relation line for a relation
|
|
3
|
+
* @param relation - The relation to generate a line for
|
|
4
|
+
* @returns The generated relation line
|
|
5
|
+
*/
|
|
6
|
+
export declare function relationLine(relation: {
|
|
7
|
+
fromModel: string;
|
|
8
|
+
toModel: string;
|
|
9
|
+
fromField: string;
|
|
10
|
+
toField: string;
|
|
11
|
+
type: string;
|
|
12
|
+
}): string;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateRelationLine = generateRelationLine;
|
|
4
|
-
const build_relation_line_1 = require("../relationship/build-relation-line");
|
|
1
|
+
import { buildRelationLine } from '../../../shared/helper/extract-schemas.js';
|
|
5
2
|
/**
|
|
6
3
|
* Generate a relation line for a relation
|
|
7
4
|
* @param relation - The relation to generate a line for
|
|
8
5
|
* @returns The generated relation line
|
|
9
6
|
*/
|
|
10
|
-
function
|
|
11
|
-
const cardinality =
|
|
7
|
+
export function relationLine(relation) {
|
|
8
|
+
const cardinality = buildRelationLine(relation.type);
|
|
12
9
|
if (!cardinality) {
|
|
13
10
|
throw new Error(`Unknown relation type: ${relation.type}`);
|
|
14
11
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Result, err, ok } from 'neverthrow';
|
|
2
|
+
import { generateMermaidER } from './core.js';
|
|
3
|
+
export const generateMermaidERDiagram = (schema) => {
|
|
4
|
+
try {
|
|
5
|
+
if (schema.tables.length === 0) {
|
|
6
|
+
return err(new Error('No tables found in schema'));
|
|
7
|
+
}
|
|
8
|
+
const mermaidContent = generateMermaidER(schema.tables);
|
|
9
|
+
return ok(mermaidContent);
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
return err(new Error(`Failed to generate Mermaid ER diagram: ${error instanceof Error ? error.message : String(error)}`));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Generate Mermaid ER diagram
|
|
3
|
+
* @param code - The code to generate Mermaid ER diagram from
|
|
4
|
+
* @param output - The output file path
|
|
5
|
+
*/
|
|
6
|
+
export declare function sizukuMermaidER(code: string[], output: string): Promise<{
|
|
7
|
+
ok: true;
|
|
8
|
+
value: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
@@ -1,77 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// 1. argv ['**/bin/node', '**/dist/src/generator/mermaid-er/index.js', 'db/schema.ts', '-o', 'mermaid-er/ER.md']
|
|
22
|
-
if (config.output === undefined && !node_process_1.argv.includes('-o')) {
|
|
23
|
-
console.error('Error: -o is not found');
|
|
24
|
-
return false;
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { mkdir, writeFile } from '../../shared/fsp/index.js';
|
|
3
|
+
import { extractRelations } from '../../shared/helper/extract-schemas.js';
|
|
4
|
+
import { erContent } from './generator/index.js';
|
|
5
|
+
import { parseTableInfo } from './validator/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generate Mermaid ER diagram
|
|
8
|
+
* @param code - The code to generate Mermaid ER diagram from
|
|
9
|
+
* @param output - The output file path
|
|
10
|
+
*/
|
|
11
|
+
export async function sizukuMermaidER(code, output) {
|
|
12
|
+
const tables = parseTableInfo(code);
|
|
13
|
+
const relations = extractRelations(code);
|
|
14
|
+
const ERContent = erContent(relations, tables);
|
|
15
|
+
const mkdirResult = await mkdir(path.dirname(output));
|
|
16
|
+
if (!mkdirResult.ok) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: mkdirResult.error,
|
|
20
|
+
};
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const output = config.output ?? args[args.indexOf('-o') + 1];
|
|
33
|
-
config.output = output;
|
|
34
|
-
try {
|
|
35
|
-
// 5. read db/schema.ts
|
|
36
|
-
const content = (0, node_fs_1.readFileSync)(input, 'utf-8');
|
|
37
|
-
// 6. split lines
|
|
38
|
-
const lines = content.split('\n');
|
|
39
|
-
// 7. create output directory
|
|
40
|
-
const outputDir = node_path_1.default.dirname(output);
|
|
41
|
-
if (!(0, node_fs_1.existsSync)(outputDir)) {
|
|
42
|
-
(0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
|
|
43
|
-
}
|
|
44
|
-
// 8. skip import section
|
|
45
|
-
const codeStart = lines.findIndex((line) => !line.trim().startsWith('import') && line.trim() !== '');
|
|
46
|
-
// 9. parse table info
|
|
47
|
-
const tables = (0, parse_table_info_1.parseTableInfo)(lines.slice(codeStart));
|
|
48
|
-
// 10. extract relations
|
|
49
|
-
const relations = (0, extract_relations_1.extractRelations)(lines.slice(codeStart));
|
|
50
|
-
// 11. generate ER content
|
|
51
|
-
const ERContent = (0, generate_er_content_1.generateERContent)(relations, tables);
|
|
52
|
-
// 12. write ER content to output file
|
|
53
|
-
(0, node_fs_1.writeFileSync)(output, ERContent);
|
|
54
|
-
console.log(`Generated ER at: ${output}`);
|
|
55
|
-
return true;
|
|
22
|
+
const writeFileResult = await writeFile(output, ERContent);
|
|
23
|
+
if (!writeFileResult.ok) {
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
error: writeFileResult.error,
|
|
27
|
+
};
|
|
56
28
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
});
|
|
29
|
+
return {
|
|
30
|
+
ok: true,
|
|
31
|
+
value: undefined,
|
|
32
|
+
};
|
|
77
33
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildRelationLine = buildRelationLine;
|
|
4
|
-
const is_relationship_1 = require("../validator/is-relationship");
|
|
1
|
+
import { isRelationship } from '../validator/is-relationship.js';
|
|
5
2
|
const RELATIONSHIPS = {
|
|
6
3
|
'zero-one': '|o',
|
|
7
4
|
one: '||',
|
|
@@ -13,7 +10,7 @@ const RELATIONSHIPS = {
|
|
|
13
10
|
* @param { string } input
|
|
14
11
|
* @returns { string }
|
|
15
12
|
*/
|
|
16
|
-
function buildRelationLine(input) {
|
|
13
|
+
export function buildRelationLine(input) {
|
|
17
14
|
const parts = input.split('-to-');
|
|
18
15
|
if (parts.length !== 2) {
|
|
19
16
|
throw new Error(`Invalid input format: ${input}`);
|
|
@@ -24,7 +21,7 @@ function buildRelationLine(input) {
|
|
|
24
21
|
const from = parts[0];
|
|
25
22
|
const to = toRaw;
|
|
26
23
|
const isOptional = optionalFlag === 'optional';
|
|
27
|
-
if (!(
|
|
24
|
+
if (!(isRelationship(from) && isRelationship(to))) {
|
|
28
25
|
throw new Error(`Invalid relationship string: ${input}`);
|
|
29
26
|
}
|
|
30
27
|
const fromSymbol = RELATIONSHIPS[from];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Node, Project } from 'ts-morph';
|
|
2
|
+
const baseBuilderName = (expr) => {
|
|
3
|
+
if (Node.isIdentifier(expr))
|
|
4
|
+
return expr.getText();
|
|
5
|
+
if (Node.isCallExpression(expr) || Node.isPropertyAccessExpression(expr))
|
|
6
|
+
return baseBuilderName(expr.getExpression());
|
|
7
|
+
return '';
|
|
8
|
+
};
|
|
9
|
+
const isFieldInfo = (v) => v !== null;
|
|
10
|
+
export function parseTableInfo(code) {
|
|
11
|
+
const source = code.join('\n');
|
|
12
|
+
const file = new Project({ useInMemoryFileSystem: true }).createSourceFile('temp.ts', source);
|
|
13
|
+
return file
|
|
14
|
+
.getVariableStatements()
|
|
15
|
+
.filter((stmt) => stmt.isExported())
|
|
16
|
+
.flatMap((stmt) => {
|
|
17
|
+
const decl = stmt.getDeclarations()[0];
|
|
18
|
+
if (!Node.isVariableDeclaration(decl))
|
|
19
|
+
return [];
|
|
20
|
+
const varName = decl.getName();
|
|
21
|
+
if (varName.toLowerCase().includes('relation'))
|
|
22
|
+
return [];
|
|
23
|
+
const init = decl.getInitializer();
|
|
24
|
+
if (!(init && Node.isCallExpression(init)))
|
|
25
|
+
return [];
|
|
26
|
+
const callee = init.getExpression().getText();
|
|
27
|
+
if (!callee.endsWith('Table') || callee === 'relations')
|
|
28
|
+
return [];
|
|
29
|
+
const objLit = init.getArguments()[1];
|
|
30
|
+
if (!(objLit && Node.isObjectLiteralExpression(objLit)))
|
|
31
|
+
return [];
|
|
32
|
+
const fields = objLit
|
|
33
|
+
.getProperties()
|
|
34
|
+
.filter(Node.isPropertyAssignment)
|
|
35
|
+
.map((prop) => {
|
|
36
|
+
const keyNode = prop.getNameNode();
|
|
37
|
+
if (!Node.isIdentifier(keyNode))
|
|
38
|
+
return null;
|
|
39
|
+
const fieldName = keyNode.getText();
|
|
40
|
+
const initExpr = prop.getInitializer();
|
|
41
|
+
if (!(initExpr && Node.isCallExpression(initExpr)))
|
|
42
|
+
return null;
|
|
43
|
+
const fieldType = baseBuilderName(initExpr);
|
|
44
|
+
const initText = initExpr.getText();
|
|
45
|
+
const lineIdx = prop.getStartLineNumber() - 1;
|
|
46
|
+
const baseDesc = code
|
|
47
|
+
.slice(0, lineIdx)
|
|
48
|
+
.reverse()
|
|
49
|
+
.find((line) => {
|
|
50
|
+
const t = line.trim();
|
|
51
|
+
return (t.startsWith('///') &&
|
|
52
|
+
!t.includes('@z.') &&
|
|
53
|
+
!t.includes('@v.') &&
|
|
54
|
+
!t.includes('@relation'));
|
|
55
|
+
})
|
|
56
|
+
?.replace(/^\s*\/\/\/\s*/, '') ?? '';
|
|
57
|
+
const prefix = initText.includes('.primaryKey()')
|
|
58
|
+
? '(PK) '
|
|
59
|
+
: initText.includes('.references(')
|
|
60
|
+
? '(FK) '
|
|
61
|
+
: '';
|
|
62
|
+
return {
|
|
63
|
+
name: fieldName,
|
|
64
|
+
type: fieldType,
|
|
65
|
+
description: `${prefix}${baseDesc}`.trim(),
|
|
66
|
+
};
|
|
67
|
+
})
|
|
68
|
+
.filter(isFieldInfo);
|
|
69
|
+
return [{ name: varName, fields }];
|
|
70
|
+
});
|
|
71
|
+
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isRelationship = isRelationship;
|
|
4
1
|
/**
|
|
5
2
|
* isRelationship
|
|
6
3
|
* @param { string } key
|
|
7
4
|
* @returns { key is Relationship }
|
|
8
5
|
*/
|
|
9
|
-
function isRelationship(key) {
|
|
6
|
+
export function isRelationship(key) {
|
|
10
7
|
return ['zero-one', 'one', 'zero-many', 'many'].includes(key);
|
|
11
8
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseRelationLine = parseRelationLine;
|
|
4
1
|
/**
|
|
5
2
|
* Parse a relation line
|
|
6
3
|
* @param line - The line to parse
|
|
7
4
|
* @returns The parsed relation
|
|
8
5
|
*/
|
|
9
|
-
function parseRelationLine(line) {
|
|
6
|
+
export function parseRelationLine(line) {
|
|
10
7
|
// @relation <fromModel>.<fromField> <toModel>.<toField> <relationType>
|
|
11
8
|
const relationMatch = line.match(/@relation\s+(\w+)\.(\w+)\s+(\w+)\.(\w+)\s+(\w+-to-\w+)/);
|
|
12
9
|
if (relationMatch) {
|