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.
Files changed (228) hide show
  1. package/README.md +96 -344
  2. package/dist/cli/main.d.ts +10 -0
  3. package/dist/cli/main.js +61 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +51 -0
  6. package/dist/config/index.d.ts +18 -0
  7. package/dist/config/index.js +13 -0
  8. package/dist/config/loader.d.ts +19 -0
  9. package/dist/config/loader.js +30 -0
  10. package/dist/generator/engine.d.ts +3 -0
  11. package/dist/generator/engine.js +63 -0
  12. package/dist/generator/mermaid-er/config/index.d.ts +4 -4
  13. package/dist/generator/mermaid-er/config/index.js +4 -10
  14. package/dist/generator/mermaid-er/core/extract-relations.d.ts +1 -1
  15. package/dist/generator/mermaid-er/core/extract-relations.js +3 -6
  16. package/dist/generator/mermaid-er/core.d.ts +6 -0
  17. package/dist/generator/mermaid-er/core.js +54 -0
  18. package/dist/generator/mermaid-er/generator/er-content.d.ts +20 -0
  19. package/dist/generator/mermaid-er/generator/{generate-er-content.js → er-content.js} +3 -7
  20. package/dist/generator/mermaid-er/generator/index.d.ts +2 -0
  21. package/dist/generator/mermaid-er/generator/index.js +2 -0
  22. package/dist/generator/mermaid-er/generator/relation-line.d.ts +12 -0
  23. package/dist/generator/mermaid-er/generator/{generate-relation-line.js → relation-line.js} +3 -6
  24. package/dist/generator/mermaid-er/generator.d.ts +3 -0
  25. package/dist/generator/mermaid-er/generator.js +14 -0
  26. package/dist/generator/mermaid-er/index.d.ts +12 -5
  27. package/dist/generator/mermaid-er/index.js +30 -74
  28. package/dist/generator/mermaid-er/relationship/build-relation-line.js +3 -6
  29. package/dist/generator/mermaid-er/types.js +1 -0
  30. package/dist/generator/mermaid-er/validator/index.d.ts +8 -0
  31. package/dist/generator/mermaid-er/validator/index.js +71 -0
  32. package/dist/generator/mermaid-er/validator/is-relationship.d.ts +1 -1
  33. package/dist/generator/mermaid-er/validator/is-relationship.js +1 -4
  34. package/dist/generator/mermaid-er/validator/parse-relation-line.js +1 -4
  35. package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +1 -7
  36. package/dist/generator/mermaid-er/validator/parse-table-info.js +69 -89
  37. package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +1 -4
  38. package/dist/generator/valibot/config/index.d.ts +2 -2
  39. package/dist/generator/valibot/config/index.js +6 -12
  40. package/dist/generator/valibot/core/extract-schema.d.ts +2 -5
  41. package/dist/generator/valibot/core/extract-schema.js +162 -81
  42. package/dist/generator/valibot/core.d.ts +5 -0
  43. package/dist/generator/valibot/core.js +39 -0
  44. package/dist/generator/valibot/generator/infer-input.d.ts +5 -0
  45. package/dist/generator/valibot/generator/infer-input.js +8 -0
  46. package/dist/generator/valibot/generator/relation-valibot-code.d.ts +13 -0
  47. package/dist/generator/valibot/generator/relation-valibot-code.js +19 -0
  48. package/dist/generator/valibot/generator/valibot-code.d.ts +15 -0
  49. package/dist/generator/valibot/generator/valibot-code.js +16 -0
  50. package/dist/generator/valibot/generator/valibot.d.ts +14 -0
  51. package/dist/generator/valibot/generator/valibot.js +15 -0
  52. package/dist/generator/valibot/generator.d.ts +3 -0
  53. package/dist/generator/valibot/generator.js +14 -0
  54. package/dist/generator/valibot/index.d.ts +14 -3
  55. package/dist/generator/valibot/index.js +46 -73
  56. package/dist/generator/zod/config/index.d.ts +2 -2
  57. package/dist/generator/zod/config/index.js +6 -12
  58. package/dist/generator/zod/core/extract-schema.d.ts +1 -2
  59. package/dist/generator/zod/core/extract-schema.js +228 -81
  60. package/dist/generator/zod/core.d.ts +5 -0
  61. package/dist/generator/zod/core.js +39 -0
  62. package/dist/generator/zod/generator/infer.d.ts +5 -0
  63. package/dist/generator/zod/generator/infer.js +8 -0
  64. package/dist/generator/zod/generator/relation-zod-code.d.ts +13 -0
  65. package/dist/generator/zod/generator/relation-zod-code.js +19 -0
  66. package/dist/generator/zod/generator/zod-code.d.ts +17 -0
  67. package/dist/generator/zod/generator/zod-code.js +18 -0
  68. package/dist/generator/zod/generator/zod.d.ts +16 -0
  69. package/dist/generator/zod/generator/zod.js +16 -0
  70. package/dist/generator/zod/generator.d.ts +3 -0
  71. package/dist/generator/zod/generator.js +14 -0
  72. package/dist/generator/zod/index.d.ts +15 -3
  73. package/dist/generator/zod/index.js +50 -73
  74. package/dist/index.d.ts +8 -0
  75. package/dist/index.js +71 -0
  76. package/dist/shared/config/index.d.ts +13 -0
  77. package/dist/{common → shared}/config/index.js +1 -4
  78. package/dist/shared/format/index.d.ts +15 -0
  79. package/dist/shared/format/index.js +24 -0
  80. package/dist/shared/fs/index.d.ts +7 -0
  81. package/dist/shared/fs/index.js +16 -0
  82. package/dist/shared/fsp/index.d.ts +27 -0
  83. package/dist/shared/fsp/index.js +38 -0
  84. package/dist/shared/generator/field-definitions.d.ts +12 -0
  85. package/dist/shared/generator/field-definitions.js +12 -0
  86. package/dist/shared/helper/ast-parser.d.ts +3 -0
  87. package/dist/shared/helper/ast-parser.js +202 -0
  88. package/dist/shared/helper/build-schema-extractor.d.ts +25 -0
  89. package/dist/shared/helper/build-schema-extractor.js +33 -0
  90. package/dist/shared/helper/create-extract-field-from-property.d.ts +15 -0
  91. package/dist/shared/helper/create-extract-field-from-property.js +20 -0
  92. package/dist/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
  93. package/dist/shared/helper/create-extract-fields-from-call-expression.js +14 -0
  94. package/dist/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
  95. package/dist/shared/helper/create-extract-relation-field-from-property.js +27 -0
  96. package/dist/shared/helper/extract-schemas.d.ts +133 -0
  97. package/dist/shared/helper/extract-schemas.js +445 -0
  98. package/dist/shared/helper/file-writer.d.ts +3 -0
  99. package/dist/shared/helper/file-writer.js +25 -0
  100. package/dist/shared/helper/find-object-literal-expression.d.ts +12 -0
  101. package/dist/shared/helper/find-object-literal-expression.js +31 -0
  102. package/dist/shared/helper/find-object-literalIn-args.d.ts +2 -0
  103. package/dist/shared/helper/find-object-literalIn-args.js +8 -0
  104. package/dist/shared/helper/is-relation-function.d.ts +10 -0
  105. package/dist/shared/helper/is-relation-function.js +16 -0
  106. package/dist/shared/types.js +1 -0
  107. package/dist/{common/text → shared/utils}/capitalize.js +1 -4
  108. package/dist/shared/utils/compose.d.ts +101 -0
  109. package/dist/shared/utils/compose.js +124 -0
  110. package/dist/shared/utils/file.d.ts +92 -0
  111. package/dist/shared/utils/file.js +177 -0
  112. package/dist/shared/utils/functional.d.ts +118 -0
  113. package/dist/shared/utils/functional.js +96 -0
  114. package/dist/shared/utils/index.d.ts +20 -0
  115. package/dist/shared/utils/index.js +48 -0
  116. package/dist/shared/utils/string-utils.d.ts +8 -0
  117. package/dist/shared/utils/string-utils.js +28 -0
  118. package/dist/shared/utils/types.d.ts +32 -0
  119. package/dist/shared/utils/types.js +2 -0
  120. package/dist/shared/utils/validation-utils.d.ts +8 -0
  121. package/dist/shared/utils/validation-utils.js +25 -0
  122. package/dist/src/config/index.d.ts +18 -0
  123. package/dist/src/config/index.js +13 -0
  124. package/dist/src/generator/mermaid-er/core/extract-relations.d.ts +8 -0
  125. package/dist/src/generator/mermaid-er/core/extract-relations.js +12 -0
  126. package/dist/src/generator/mermaid-er/generator/er-content.d.ts +9 -0
  127. package/dist/src/generator/mermaid-er/generator/er-content.js +25 -0
  128. package/dist/src/generator/mermaid-er/generator/index.d.ts +2 -0
  129. package/dist/src/generator/mermaid-er/generator/index.js +2 -0
  130. package/dist/src/generator/mermaid-er/generator/relation-line.d.ts +8 -0
  131. package/dist/src/generator/mermaid-er/generator/relation-line.js +14 -0
  132. package/dist/src/generator/mermaid-er/index.d.ts +6 -0
  133. package/dist/src/generator/mermaid-er/index.js +16 -0
  134. package/dist/src/generator/mermaid-er/relationship/build-relation-line.d.ts +15 -0
  135. package/dist/src/generator/mermaid-er/relationship/build-relation-line.js +35 -0
  136. package/dist/src/generator/mermaid-er/types.d.ts +21 -0
  137. package/dist/src/generator/mermaid-er/types.js +1 -0
  138. package/dist/src/generator/mermaid-er/validator/index.d.ts +4 -0
  139. package/dist/src/generator/mermaid-er/validator/index.js +4 -0
  140. package/dist/src/generator/mermaid-er/validator/is-relationship.d.ts +8 -0
  141. package/dist/src/generator/mermaid-er/validator/is-relationship.js +9 -0
  142. package/dist/src/generator/mermaid-er/validator/parse-relation-line.d.ts +13 -0
  143. package/dist/src/generator/mermaid-er/validator/parse-relation-line.js +21 -0
  144. package/dist/src/generator/mermaid-er/validator/parse-table-info.d.ts +8 -0
  145. package/dist/src/generator/mermaid-er/validator/parse-table-info.js +91 -0
  146. package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +7 -0
  147. package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.js +9 -0
  148. package/dist/src/generator/valibot/generator/infer-input.d.ts +5 -0
  149. package/dist/src/generator/valibot/generator/infer-input.js +8 -0
  150. package/dist/src/generator/valibot/generator/valibot-code.d.ts +14 -0
  151. package/dist/src/generator/valibot/generator/valibot-code.js +16 -0
  152. package/dist/src/generator/valibot/generator/valibot.d.ts +13 -0
  153. package/dist/src/generator/valibot/generator/valibot.js +11 -0
  154. package/dist/src/generator/valibot/index.d.ts +9 -0
  155. package/dist/src/generator/valibot/index.js +34 -0
  156. package/dist/src/generator/zod/generator/infer.d.ts +5 -0
  157. package/dist/src/generator/zod/generator/infer.js +8 -0
  158. package/dist/{generator/zod/generator/generate-zod-code.d.ts → src/generator/zod/generator/zod-code.d.ts} +8 -3
  159. package/dist/src/generator/zod/generator/zod-code.js +18 -0
  160. package/dist/{generator/zod/generator/generate-zod-schema.d.ts → src/generator/zod/generator/zod.d.ts} +8 -4
  161. package/dist/src/generator/zod/generator/zod.js +12 -0
  162. package/dist/src/generator/zod/index.d.ts +10 -0
  163. package/dist/src/generator/zod/index.js +40 -0
  164. package/dist/src/index.d.ts +10 -0
  165. package/dist/src/index.js +35 -0
  166. package/dist/src/shared/format/index.d.ts +2 -0
  167. package/dist/src/shared/format/index.js +10 -0
  168. package/dist/src/shared/fs/index.d.ts +2 -0
  169. package/dist/src/shared/fs/index.js +10 -0
  170. package/dist/src/shared/fsp/index.d.ts +3 -0
  171. package/dist/src/shared/fsp/index.js +8 -0
  172. package/dist/src/shared/generator/field-definitions.d.ts +12 -0
  173. package/dist/src/shared/generator/field-definitions.js +12 -0
  174. package/dist/src/shared/helper/build-schema-extractor.d.ts +25 -0
  175. package/dist/src/shared/helper/build-schema-extractor.js +33 -0
  176. package/dist/src/shared/helper/create-extract-field-from-property.d.ts +15 -0
  177. package/dist/src/shared/helper/create-extract-field-from-property.js +20 -0
  178. package/dist/src/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
  179. package/dist/src/shared/helper/create-extract-fields-from-call-expression.js +14 -0
  180. package/dist/src/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
  181. package/dist/src/shared/helper/create-extract-relation-field-from-property.js +27 -0
  182. package/dist/src/shared/helper/extract-schemas.d.ts +16 -0
  183. package/dist/src/shared/helper/extract-schemas.js +19 -0
  184. package/dist/src/shared/helper/find-object-literal-expression.d.ts +12 -0
  185. package/dist/src/shared/helper/find-object-literal-expression.js +31 -0
  186. package/dist/src/shared/helper/find-object-literalIn-args.d.ts +2 -0
  187. package/dist/src/shared/helper/find-object-literalIn-args.js +8 -0
  188. package/dist/src/shared/helper/is-relation-function.d.ts +10 -0
  189. package/dist/src/shared/helper/is-relation-function.js +16 -0
  190. package/dist/src/shared/utils/index.d.ts +33 -0
  191. package/dist/src/shared/utils/index.js +61 -0
  192. package/dist/utils/index.d.ts +144 -0
  193. package/dist/utils/index.js +301 -0
  194. package/package.json +10 -13
  195. package/dist/common/config/index.d.ts +0 -13
  196. package/dist/common/format/index.d.ts +0 -1
  197. package/dist/common/format/index.js +0 -12
  198. package/dist/common/generator/generate-field-definitions.d.ts +0 -8
  199. package/dist/common/generator/generate-field-definitions.js +0 -16
  200. package/dist/common/helper/get-camel-case-schema-name-helper.d.ts +0 -7
  201. package/dist/common/helper/get-camel-case-schema-name-helper.js +0 -14
  202. package/dist/common/helper/get-pascal-case-schema-name-helper.d.ts +0 -8
  203. package/dist/common/helper/get-pascal-case-schema-name-helper.js +0 -15
  204. package/dist/common/helper/get-variable-name-helper.d.ts +0 -9
  205. package/dist/common/helper/get-variable-name-helper.js +0 -15
  206. package/dist/common/helper/get-variable-schema-name-helper.d.ts +0 -9
  207. package/dist/common/helper/get-variable-schema-name-helper.js +0 -17
  208. package/dist/common/text/decapitalize.d.ts +0 -17
  209. package/dist/common/text/decapitalize.js +0 -22
  210. package/dist/common/type/index.js +0 -2
  211. package/dist/generator/mermaid-er/generator/generate-er-content.d.ts +0 -9
  212. package/dist/generator/mermaid-er/generator/generate-relation-line.d.ts +0 -7
  213. package/dist/generator/mermaid-er/type/index.js +0 -2
  214. package/dist/generator/mermaid-er/validator/is-relation.d.ts +0 -7
  215. package/dist/generator/mermaid-er/validator/is-relation.js +0 -40
  216. package/dist/generator/valibot/generator/generate-valibot-code.d.ts +0 -11
  217. package/dist/generator/valibot/generator/generate-valibot-code.js +0 -21
  218. package/dist/generator/valibot/generator/generate-valibot-infer-input.d.ts +0 -9
  219. package/dist/generator/valibot/generator/generate-valibot-infer-input.js +0 -16
  220. package/dist/generator/valibot/generator/generate-valibot-schema.d.ts +0 -9
  221. package/dist/generator/valibot/generator/generate-valibot-schema.js +0 -16
  222. package/dist/generator/zod/generator/generate-z-infer.d.ts +0 -11
  223. package/dist/generator/zod/generator/generate-z-infer.js +0 -18
  224. package/dist/generator/zod/generator/generate-zod-code.js +0 -21
  225. package/dist/generator/zod/generator/generate-zod-schema.js +0 -17
  226. /package/dist/generator/mermaid-er/{type/index.d.ts → types.d.ts} +0 -0
  227. /package/dist/{common/type/index.d.ts → shared/types.d.ts} +0 -0
  228. /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,3 @@
1
+ import { Result } from 'neverthrow';
2
+ import type { SizukuConfig } from '../config/loader.js';
3
+ export declare const generateSchemas: (config: SizukuConfig) => Promise<Result<void, Error>>;
@@ -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
- input?: string;
3
- output?: string;
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
- "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"));
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 = node_fs_1.default.existsSync('sizuku-mermaid-er.json')
15
- ? { ...JSON.parse(node_fs_1.default.readFileSync('sizuku-mermaid-er.json', 'utf-8')) }
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,4 +1,4 @@
1
- import type { Relation } from '../type';
1
+ import type { Relation } from '../types.js';
2
2
  /**
3
3
  * Extracts relations from the given code.
4
4
  *
@@ -1,17 +1,14 @@
1
- "use strict";
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 = (0, parse_relation_line_1.parseRelationLine)(line);
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
- "use strict";
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 generateERContent(relations, tables) {
10
+ export function erContent(relations, tables) {
15
11
  const erContent = [
16
12
  ...ER_HEADER,
17
- ...relations.map(generate_relation_line_1.generateRelationLine),
13
+ ...relations.map(relationLine),
18
14
  // Generate per-table definitions
19
15
  ...tables.flatMap((table) => [
20
16
  ` ${table.name} {`,
@@ -0,0 +1,2 @@
1
+ export { erContent } from './er-content.js';
2
+ export { relationLine } from './relation-line.js';
@@ -0,0 +1,2 @@
1
+ export { erContent } from './er-content.js';
2
+ export { relationLine } from './relation-line.js';
@@ -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
- "use strict";
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 generateRelationLine(relation) {
11
- const cardinality = (0, build_relation_line_1.buildRelationLine)(relation.type);
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,3 @@
1
+ import { Result } from 'neverthrow';
2
+ import type { ParsedSchema } from '../../shared/utils/types.js';
3
+ export declare const generateMermaidERDiagram: (schema: ParsedSchema) => Result<string, Error>;
@@ -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
- #!/usr/bin/env node
2
- import type { Config } from './config';
3
- export declare const ER_HEADER: readonly ["```mermaid", "erDiagram"];
4
- export declare const ER_FOOTER: readonly ["```"];
5
- export declare function main(dev?: boolean, config?: Config): Promise<boolean>;
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
- #!/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.ER_FOOTER = exports.ER_HEADER = void 0;
8
- exports.main = main;
9
- const node_fs_1 = require("node:fs");
10
- const node_path_1 = __importDefault(require("node:path"));
11
- const generate_er_content_1 = require("./generator/generate-er-content");
12
- const parse_table_info_1 = require("./validator/parse-table-info");
13
- const extract_relations_1 = require("./core/extract-relations");
14
- const config_1 = require("./config");
15
- const node_process_1 = require("node:process");
16
- // ER diagram header
17
- exports.ER_HEADER = ['```mermaid', 'erDiagram'];
18
- // ER diagram footer
19
- exports.ER_FOOTER = ['```'];
20
- async function main(dev = false, config = (0, config_1.getConfig)()) {
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
- // 2. slice [ 'db/schema.ts', '-o', 'mermaid-er/ER.md']
27
- const args = process.argv.slice(2);
28
- // 3. input = args[0] = 'db/schema.ts'
29
- const input = config.input ?? args[0];
30
- config.input = input;
31
- // 4. output = 'mermaid-er/ER.md'
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
- 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
- });
29
+ return {
30
+ ok: true,
31
+ value: undefined,
32
+ };
77
33
  }
@@ -1,7 +1,4 @@
1
- "use strict";
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 (!((0, is_relationship_1.isRelationship)(from) && (0, is_relationship_1.isRelationship)(to))) {
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,8 @@
1
+ export declare function parseTableInfo(code: string[]): {
2
+ name: string;
3
+ fields: {
4
+ type: string;
5
+ name: string;
6
+ description: string | null;
7
+ }[];
8
+ }[];
@@ -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,4 +1,4 @@
1
- import type { Relationship } from '../relationship/build-relation-line';
1
+ import type { Relationship } from '../relationship/build-relation-line.js';
2
2
  /**
3
3
  * isRelationship
4
4
  * @param { string } key
@@ -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) {