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,28 @@
1
+ // 完全純粋な文字列操作ユーティリティ - 外部import禁止
2
+ export const capitalize = (str) => {
3
+ return str.charAt(0).toUpperCase() + str.slice(1);
4
+ };
5
+ export const toPascalCase = (str) => {
6
+ return str
7
+ .split(/[-_\s]+/)
8
+ .map(word => capitalize(word))
9
+ .join('');
10
+ };
11
+ export const extractComment = (commentText) => {
12
+ return commentText.replace(/^\/\/\/\s*/, '').trim();
13
+ };
14
+ export const parseZodTag = (tag) => {
15
+ return tag.replace(/^@z\./, '');
16
+ };
17
+ export const parseValibotTag = (tag) => {
18
+ return tag.replace(/^@v\./, '');
19
+ };
20
+ export const parseRelationTag = (tag) => {
21
+ return tag.replace(/^@relation\s+/, '');
22
+ };
23
+ export const splitLines = (text) => {
24
+ return text.split('\n').map(line => line.trim()).filter(line => line.length > 0);
25
+ };
26
+ export const joinLines = (lines) => {
27
+ return lines.join('\n');
28
+ };
@@ -0,0 +1,32 @@
1
+ export type TableInfo = {
2
+ name: string;
3
+ columns: ColumnInfo[];
4
+ relations: RelationInfo[];
5
+ };
6
+ export type ColumnInfo = {
7
+ name: string;
8
+ type: string;
9
+ isPrimary: boolean;
10
+ isNullable: boolean;
11
+ length?: number;
12
+ zodSchema?: string;
13
+ valibotSchema?: string;
14
+ comment?: string;
15
+ };
16
+ export type RelationInfo = {
17
+ sourceTable: string;
18
+ sourceColumn: string;
19
+ targetTable: string;
20
+ targetColumn: string;
21
+ type: 'one-to-many' | 'many-to-one' | 'one-to-one' | 'many-to-many';
22
+ };
23
+ export type ParsedSchema = {
24
+ tables: TableInfo[];
25
+ };
26
+ export type GenerationResult<T> = {
27
+ success: true;
28
+ data: T;
29
+ } | {
30
+ success: false;
31
+ error: string;
32
+ };
@@ -0,0 +1,2 @@
1
+ // 完全純粋な型定義 - 外部import禁止
2
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { ColumnInfo, RelationInfo } from './types.js';
2
+ export declare const validateTableName: (name: string) => boolean;
3
+ export declare const validateColumnName: (name: string) => boolean;
4
+ export declare const validateRelationType: (type: string) => type is "one-to-many" | "many-to-one" | "one-to-one" | "many-to-many";
5
+ export declare const validateSchema: (tables: ColumnInfo[][]) => boolean;
6
+ export declare const findPrimaryKey: (columns: ColumnInfo[]) => ColumnInfo | undefined;
7
+ export declare const findForeignKeys: (columns: ColumnInfo[]) => ColumnInfo[];
8
+ export declare const validateRelation: (relation: RelationInfo, tables: string[]) => boolean;
@@ -0,0 +1,25 @@
1
+ // 完全純粋なバリデーション関連ユーティリティ - 外部import禁止
2
+ export const validateTableName = (name) => {
3
+ return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name);
4
+ };
5
+ export const validateColumnName = (name) => {
6
+ return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name);
7
+ };
8
+ export const validateRelationType = (type) => {
9
+ return ['one-to-many', 'many-to-one', 'one-to-one', 'many-to-many'].includes(type);
10
+ };
11
+ export const validateSchema = (tables) => {
12
+ return tables.every(table => table.every(column => validateColumnName(column.name) &&
13
+ column.type.length > 0));
14
+ };
15
+ export const findPrimaryKey = (columns) => {
16
+ return columns.find(column => column.isPrimary);
17
+ };
18
+ export const findForeignKeys = (columns) => {
19
+ return columns.filter(column => column.name.toLowerCase().includes('id') &&
20
+ !column.isPrimary);
21
+ };
22
+ export const validateRelation = (relation, tables) => {
23
+ return tables.includes(relation.sourceTable) &&
24
+ tables.includes(relation.targetTable);
25
+ };
@@ -0,0 +1,18 @@
1
+ export type Config = {
2
+ input?: `${string}.ts`;
3
+ zod?: {
4
+ output?: `${string}.ts`;
5
+ comment?: boolean;
6
+ type?: boolean;
7
+ zod?: 'v4' | 'mini' | '@hono/zod-openapi';
8
+ };
9
+ valibot?: {
10
+ output?: `${string}.ts`;
11
+ comment?: boolean;
12
+ type?: boolean;
13
+ };
14
+ mermaid?: {
15
+ output?: string;
16
+ };
17
+ };
18
+ export declare function getConfig(): Config;
@@ -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,8 @@
1
+ import type { Relation } from '../types.js';
2
+ /**
3
+ * Extracts relations from the given code.
4
+ *
5
+ * @param code - The code to extract relations from.
6
+ * @returns The extracted relations.
7
+ */
8
+ export declare function extractRelations(code: string[]): Relation[];
@@ -0,0 +1,12 @@
1
+ import { parseRelationLine } from '../validator/parse-relation-line.js';
2
+ /**
3
+ * Extracts relations from the given code.
4
+ *
5
+ * @param code - The code to extract relations from.
6
+ * @returns The extracted relations.
7
+ */
8
+ export function extractRelations(code) {
9
+ return code
10
+ .map((line) => parseRelationLine(line))
11
+ .filter((relation) => relation !== null);
12
+ }
@@ -0,0 +1,9 @@
1
+ import type { Relation, TableInfo } from '../types.js';
2
+ /**
3
+ * Generate ER content.
4
+ *
5
+ * @param relations - The relations to generate the ER content from.
6
+ * @param tables - The tables to generate the ER content from.
7
+ * @returns The generated ER content.
8
+ */
9
+ export declare function erContent(relations: Relation[], tables: TableInfo[]): string;
@@ -0,0 +1,25 @@
1
+ import { relationLine } from './index.js';
2
+ const ER_HEADER = ['```mermaid', 'erDiagram'];
3
+ const ER_FOOTER = ['```'];
4
+ /**
5
+ * Generate ER content.
6
+ *
7
+ * @param relations - The relations to generate the ER content from.
8
+ * @param tables - The tables to generate the ER content from.
9
+ * @returns The generated ER content.
10
+ */
11
+ export function erContent(relations, tables) {
12
+ const relationLines = relations.map(relationLine);
13
+ const tableDefinitions = tables.flatMap((table) => [
14
+ ` ${table.name} {`,
15
+ ...table.fields.map((field) => ` ${field.type} ${field.name} ${field.description ? `"${field.description}"` : ''}`),
16
+ ' }',
17
+ ]);
18
+ const erContent = [
19
+ ...ER_HEADER,
20
+ ...relationLines,
21
+ ...tableDefinitions,
22
+ ...ER_FOOTER,
23
+ ];
24
+ return erContent.join('\n');
25
+ }
@@ -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,8 @@
1
+ import type { Relation } from '../types.js';
2
+ /**
3
+ * Generate a relation line for a relation.
4
+ *
5
+ * @param relation - The relation to generate a line for.
6
+ * @returns The generated relation line.
7
+ */
8
+ export declare function relationLine(relation: Relation): string;
@@ -0,0 +1,14 @@
1
+ import { buildRelationLine } from '../relationship/build-relation-line.js';
2
+ /**
3
+ * Generate a relation line for a relation.
4
+ *
5
+ * @param relation - The relation to generate a line for.
6
+ * @returns The generated relation line.
7
+ */
8
+ export function relationLine(relation) {
9
+ const cardinality = buildRelationLine(relation.type);
10
+ if (!cardinality) {
11
+ throw new Error(`Unknown relation type: ${relation.type}`);
12
+ }
13
+ return ` ${relation.fromModel} ${cardinality} ${relation.toModel} : "(${relation.fromField}) - (${relation.toField})"`;
14
+ }
@@ -0,0 +1,6 @@
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<import("neverthrow").Result<void, Error>>;
@@ -0,0 +1,16 @@
1
+ import path from 'node:path';
2
+ import { mkdir, writeFile } from '../../shared/fsp/index.js';
3
+ import { extractRelations } from './core/extract-relations.js';
4
+ import { erContent } from './generator/index.js';
5
+ import { parseTableInfo } from './validator/parse-table-info.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
+ return await mkdir(path.dirname(output)).andThen(() => writeFile(output, ERContent));
16
+ }
@@ -0,0 +1,15 @@
1
+ declare const RELATIONSHIPS: {
2
+ readonly 'zero-one': "|o";
3
+ readonly one: "||";
4
+ readonly 'zero-many': "}o";
5
+ readonly many: "}|";
6
+ };
7
+ export type Relationship = keyof typeof RELATIONSHIPS;
8
+ /**
9
+ * Builds a relationship line for mermaid from a string.
10
+ *
11
+ * @param input - The relationship string to parse.
12
+ * @returns The mermaid relationship line.
13
+ */
14
+ export declare function buildRelationLine(input: string): string;
15
+ export {};
@@ -0,0 +1,35 @@
1
+ import { isRelationship } from '../validator/is-relationship.js';
2
+ const RELATIONSHIPS = {
3
+ 'zero-one': '|o',
4
+ one: '||',
5
+ 'zero-many': '}o',
6
+ many: '}|',
7
+ };
8
+ /**
9
+ * Builds a relationship line for mermaid from a string.
10
+ *
11
+ * @param input - The relationship string to parse.
12
+ * @returns The mermaid relationship line.
13
+ */
14
+ export function buildRelationLine(input) {
15
+ const parts = input.split('-to-');
16
+ if (parts.length !== 2) {
17
+ throw new Error(`Invalid input format: ${input}`);
18
+ }
19
+ const [toRaw, optionalFlag] = parts[1].includes('-optional')
20
+ ? [parts[1].replace('-optional', ''), 'optional']
21
+ : [parts[1], ''];
22
+ const from = parts[0];
23
+ const to = toRaw;
24
+ const isOptional = optionalFlag === 'optional';
25
+ if (!(isRelationship(from) && isRelationship(to))) {
26
+ throw new Error(`Invalid relationship string: ${input}`);
27
+ }
28
+ const fromSymbol = RELATIONSHIPS[from];
29
+ const toSymbol = RELATIONSHIPS[to];
30
+ if (!(fromSymbol && toSymbol)) {
31
+ throw new Error(`Invalid relationship string: ${input}`);
32
+ }
33
+ const connector = isOptional ? '..' : '--';
34
+ return `${fromSymbol}${connector}${toSymbol}`;
35
+ }
@@ -0,0 +1,21 @@
1
+ export type Relation = {
2
+ fromModel: string;
3
+ toModel: string;
4
+ fromField: string;
5
+ toField: string;
6
+ type: string;
7
+ };
8
+ export type ERContent = readonly string[];
9
+ export type TableInfo = {
10
+ name: string;
11
+ fields: {
12
+ type: string;
13
+ name: string;
14
+ description: string | null;
15
+ }[];
16
+ };
17
+ export type AccumulatorType = {
18
+ tables: TableInfo[];
19
+ currentTable: TableInfo | null;
20
+ currentDescription: string;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export { isRelationship } from './is-relationship.js';
2
+ export { parseRelationLine } from './parse-relation-line.js';
3
+ export { parseTableInfo } from './parse-table-info.js';
4
+ export { removeDuplicateRelations } from './remove-duplicate-relations.js';
@@ -0,0 +1,4 @@
1
+ export { isRelationship } from './is-relationship.js';
2
+ export { parseRelationLine } from './parse-relation-line.js';
3
+ export { parseTableInfo } from './parse-table-info.js';
4
+ export { removeDuplicateRelations } from './remove-duplicate-relations.js';
@@ -0,0 +1,8 @@
1
+ import type { Relationship } from '../relationship/build-relation-line.js';
2
+ /**
3
+ * Check if a key is a valid relationship.
4
+ *
5
+ * @param key - The key to check.
6
+ * @returns True if the key is a valid relationship.
7
+ */
8
+ export declare function isRelationship(key: string): key is Relationship;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Check if a key is a valid relationship.
3
+ *
4
+ * @param key - The key to check.
5
+ * @returns True if the key is a valid relationship.
6
+ */
7
+ export function isRelationship(key) {
8
+ return ['zero-one', 'one', 'zero-many', 'many'].includes(key);
9
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Parse a relation line.
3
+ *
4
+ * @param line - The line to parse.
5
+ * @returns The parsed relation or null.
6
+ */
7
+ export declare function parseRelationLine(line: string): {
8
+ fromModel: string;
9
+ fromField: string;
10
+ toModel: string;
11
+ toField: string;
12
+ type: string;
13
+ } | null;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Parse a relation line.
3
+ *
4
+ * @param line - The line to parse.
5
+ * @returns The parsed relation or null.
6
+ */
7
+ export function parseRelationLine(line) {
8
+ // @relation <fromModel>.<fromField> <toModel>.<toField> <relationType>
9
+ const relationMatch = line.match(/@relation\s+(\w+)\.(\w+)\s+(\w+)\.(\w+)\s+(\w+-to-\w+)/);
10
+ if (relationMatch) {
11
+ const [_, fromModel, fromField, toModel, toField, type] = relationMatch;
12
+ return {
13
+ fromModel,
14
+ fromField,
15
+ toModel,
16
+ toField,
17
+ type,
18
+ };
19
+ }
20
+ return null;
21
+ }
@@ -0,0 +1,8 @@
1
+ import type { TableInfo } from '../types.js';
2
+ /**
3
+ * Parse table information from code.
4
+ *
5
+ * @param code - The code to parse.
6
+ * @returns Array of table information.
7
+ */
8
+ export declare function parseTableInfo(code: string[]): TableInfo[];
@@ -0,0 +1,91 @@
1
+ import { Node, Project } from 'ts-morph';
2
+ /**
3
+ * Get the base builder name from an expression.
4
+ *
5
+ * @param expr - The expression to get the builder name from.
6
+ * @returns The base builder name.
7
+ */
8
+ function baseBuilderName(expr) {
9
+ if (Node.isIdentifier(expr))
10
+ return expr.getText();
11
+ if (Node.isCallExpression(expr) || Node.isPropertyAccessExpression(expr))
12
+ return baseBuilderName(expr.getExpression());
13
+ return '';
14
+ }
15
+ /**
16
+ * Type guard for FieldInfo.
17
+ *
18
+ * @param v - The value to check.
19
+ * @returns True if the value is a FieldInfo.
20
+ */
21
+ function isFieldInfo(v) {
22
+ return v !== null;
23
+ }
24
+ /**
25
+ * Parse table information from code.
26
+ *
27
+ * @param code - The code to parse.
28
+ * @returns Array of table information.
29
+ */
30
+ export function parseTableInfo(code) {
31
+ const source = code.join('\n');
32
+ const file = new Project({ useInMemoryFileSystem: true }).createSourceFile('temp.ts', source);
33
+ return file
34
+ .getVariableStatements()
35
+ .filter((stmt) => stmt.isExported())
36
+ .flatMap((stmt) => {
37
+ const decl = stmt.getDeclarations()[0];
38
+ if (!Node.isVariableDeclaration(decl))
39
+ return [];
40
+ const varName = decl.getName();
41
+ if (varName.toLowerCase().includes('relation'))
42
+ return [];
43
+ const init = decl.getInitializer();
44
+ if (!(init && Node.isCallExpression(init)))
45
+ return [];
46
+ const callee = init.getExpression().getText();
47
+ if (!callee.endsWith('Table') || callee === 'relations')
48
+ return [];
49
+ const objLit = init.getArguments()[1];
50
+ if (!(objLit && Node.isObjectLiteralExpression(objLit)))
51
+ return [];
52
+ const fields = objLit
53
+ .getProperties()
54
+ .filter(Node.isPropertyAssignment)
55
+ .map((prop) => {
56
+ const keyNode = prop.getNameNode();
57
+ if (!Node.isIdentifier(keyNode))
58
+ return null;
59
+ const fieldName = keyNode.getText();
60
+ const initExpr = prop.getInitializer();
61
+ if (!(initExpr && Node.isCallExpression(initExpr)))
62
+ return null;
63
+ const fieldType = baseBuilderName(initExpr);
64
+ const initText = initExpr.getText();
65
+ const lineIdx = prop.getStartLineNumber() - 1;
66
+ const baseDesc = code
67
+ .slice(0, lineIdx)
68
+ .reverse()
69
+ .find((line) => {
70
+ const t = line.trim();
71
+ return (t.startsWith('///') &&
72
+ !t.includes('@z.') &&
73
+ !t.includes('@v.') &&
74
+ !t.includes('@relation'));
75
+ })
76
+ ?.replace(/^\s*\/\/\/\s*/, '') ?? '';
77
+ const prefix = initText.includes('.primaryKey()')
78
+ ? '(PK) '
79
+ : initText.includes('.references(')
80
+ ? '(FK) '
81
+ : '';
82
+ return {
83
+ name: fieldName,
84
+ type: fieldType,
85
+ description: `${prefix}${baseDesc}`.trim(),
86
+ };
87
+ })
88
+ .filter(isFieldInfo);
89
+ return [{ name: varName, fields }];
90
+ });
91
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Remove duplicate relations.
3
+ *
4
+ * @param relations - The relations to remove duplicates from.
5
+ * @returns The relations without duplicates.
6
+ */
7
+ export declare function removeDuplicateRelations(relations: readonly string[]): readonly string[];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Remove duplicate relations.
3
+ *
4
+ * @param relations - The relations to remove duplicates from.
5
+ * @returns The relations without duplicates.
6
+ */
7
+ export function removeDuplicateRelations(relations) {
8
+ return [...new Set(relations)];
9
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param name
3
+ * @returns
4
+ */
5
+ export declare function inferInput(name: string): string;
@@ -0,0 +1,8 @@
1
+ import { capitalize } from '../../../shared/utils/index.js';
2
+ /**
3
+ * @param name
4
+ * @returns
5
+ */
6
+ export function inferInput(name) {
7
+ return `export type ${capitalize(name)} = v.InferInput<typeof ${capitalize(name)}Schema>`;
8
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @param schema
3
+ * @param comment
4
+ * @param type
5
+ * @returns
6
+ */
7
+ export declare function valibotCode(schema: {
8
+ name: string;
9
+ fields: {
10
+ name: string;
11
+ definition: string;
12
+ description?: string;
13
+ }[];
14
+ }, comment: boolean, type: boolean): string;
@@ -0,0 +1,16 @@
1
+ import { inferInput } from './infer-input.js';
2
+ import { valibot } from './valibot.js';
3
+ /**
4
+ * @param schema
5
+ * @param comment
6
+ * @param type
7
+ * @returns
8
+ */
9
+ export function valibotCode(schema, comment, type) {
10
+ const valibotSchema = valibot(schema, comment);
11
+ if (type) {
12
+ const valibotInfer = inferInput(schema.name);
13
+ return `${valibotSchema}\n\n${valibotInfer}\n`;
14
+ }
15
+ return `${valibotSchema}\n`;
16
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @param schema
3
+ * @param config
4
+ * @returns
5
+ */
6
+ export declare function valibot(schema: {
7
+ name: string;
8
+ fields: {
9
+ name: string;
10
+ definition: string;
11
+ description?: string;
12
+ }[];
13
+ }, comment: boolean): string;
@@ -0,0 +1,11 @@
1
+ import { fieldDefinitions } from '../../../shared/generator/field-definitions.js';
2
+ import { schemaName } from '../../../shared/utils/index.js';
3
+ /**
4
+ * @param schema
5
+ * @param config
6
+ * @returns
7
+ */
8
+ export function valibot(schema, comment) {
9
+ const res = fieldDefinitions(schema, comment);
10
+ return `export const ${schemaName(schema.name)} = v.object({${res}})`;
11
+ }
@@ -0,0 +1,9 @@
1
+ import type { Result } from 'neverthrow';
2
+ /**
3
+ * Generate Valibot schema
4
+ * @param code - The code to generate Valibot schema from
5
+ * @param output - The output file path
6
+ * @param comment - Whether to include comments in the generated code
7
+ * @param type - Whether to include type information in the generated code
8
+ */
9
+ export declare function sizukuValibot(code: string[], output: `${string}.ts`, comment?: boolean, type?: boolean): Promise<Result<void, Error>>;
@@ -0,0 +1,34 @@
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 { buildSchemaExtractor } from '../../shared/helper/build-schema-extractor.js';
5
+ import { createExtractFieldFromProperty } from '../../shared/helper/create-extract-field-from-property.js';
6
+ import { createExtractFieldsFromCallExpression } from '../../shared/helper/create-extract-fields-from-call-expression.js';
7
+ import { createExtractRelationFieldFromProperty } from '../../shared/helper/create-extract-relation-field-from-property.js';
8
+ import { extractSchemas } from '../../shared/helper/extract-schemas.js';
9
+ import { findObjectLiteralExpression } from '../../shared/helper/find-object-literal-expression.js';
10
+ import { findObjectLiteralInArgs } from '../../shared/helper/find-object-literalIn-args.js';
11
+ import { isRelationFunctionCall } from '../../shared/helper/is-relation-function.js';
12
+ import { parseFieldComments } from '../../shared/utils/index.js';
13
+ import { valibotCode } from './generator/valibot-code.js';
14
+ /**
15
+ * Generate Valibot schema
16
+ * @param code - The code to generate Valibot schema from
17
+ * @param output - The output file path
18
+ * @param comment - Whether to include comments in the generated code
19
+ * @param type - Whether to include type information in the generated code
20
+ */
21
+ export async function sizukuValibot(code, output, comment, type) {
22
+ const extractField = createExtractFieldFromProperty((lines) => parseFieldComments(lines, '@v.'));
23
+ const extractRelationField = createExtractRelationFieldFromProperty((lines) => parseFieldComments(lines, '@v.'), 'v');
24
+ const extractFieldsFromCall = createExtractFieldsFromCallExpression(extractField, extractRelationField, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall);
25
+ const extractSchema = buildSchemaExtractor(extractFieldsFromCall, extractField);
26
+ const valibotGeneratedCode = [
27
+ 'import * as v from "valibot"',
28
+ '',
29
+ ...extractSchemas(code, extractSchema).map((schema) => valibotCode(schema, comment ?? false, type ?? false)),
30
+ ].join('\n');
31
+ return await mkdir(path.dirname(output))
32
+ .andThen(() => fmt(valibotGeneratedCode))
33
+ .andThen((formatted) => writeFile(output, formatted));
34
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param name
3
+ * @returns
4
+ */
5
+ export declare function infer(name: string): string;