sizuku 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +103 -0
  2. package/dist/config/index.d.mts +58 -0
  3. package/dist/config/index.mjs +95 -0
  4. package/dist/index.d.mts +10 -0
  5. package/dist/index.mjs +1615 -0
  6. package/package.json +31 -17
  7. package/dist/cli/main.d.ts +0 -10
  8. package/dist/cli/main.js +0 -61
  9. package/dist/cli.d.ts +0 -2
  10. package/dist/cli.js +0 -51
  11. package/dist/config/index.d.ts +0 -27
  12. package/dist/config/index.js +0 -85
  13. package/dist/config/loader.d.ts +0 -19
  14. package/dist/config/loader.js +0 -30
  15. package/dist/generator/engine.d.ts +0 -3
  16. package/dist/generator/engine.js +0 -63
  17. package/dist/generator/mermaid-er/config/index.d.ts +0 -10
  18. package/dist/generator/mermaid-er/config/index.js +0 -12
  19. package/dist/generator/mermaid-er/core/extract-relations.d.ts +0 -8
  20. package/dist/generator/mermaid-er/core/extract-relations.js +0 -17
  21. package/dist/generator/mermaid-er/core.d.ts +0 -6
  22. package/dist/generator/mermaid-er/core.js +0 -54
  23. package/dist/generator/mermaid-er/generator/er-content.d.ts +0 -20
  24. package/dist/generator/mermaid-er/generator/er-content.js +0 -23
  25. package/dist/generator/mermaid-er/generator/index.d.ts +0 -2
  26. package/dist/generator/mermaid-er/generator/index.js +0 -2
  27. package/dist/generator/mermaid-er/generator/relation-line.d.ts +0 -12
  28. package/dist/generator/mermaid-er/generator/relation-line.js +0 -13
  29. package/dist/generator/mermaid-er/generator.d.ts +0 -3
  30. package/dist/generator/mermaid-er/generator.js +0 -14
  31. package/dist/generator/mermaid-er/index.d.ts +0 -12
  32. package/dist/generator/mermaid-er/index.js +0 -33
  33. package/dist/generator/mermaid-er/relationship/build-relation-line.d.ts +0 -14
  34. package/dist/generator/mermaid-er/relationship/build-relation-line.js +0 -34
  35. package/dist/generator/mermaid-er/types.d.ts +0 -21
  36. package/dist/generator/mermaid-er/types.js +0 -1
  37. package/dist/generator/mermaid-er/validator/index.d.ts +0 -8
  38. package/dist/generator/mermaid-er/validator/index.js +0 -74
  39. package/dist/generator/mermaid-er/validator/is-relationship.d.ts +0 -7
  40. package/dist/generator/mermaid-er/validator/is-relationship.js +0 -8
  41. package/dist/generator/mermaid-er/validator/parse-relation-line.d.ts +0 -12
  42. package/dist/generator/mermaid-er/validator/parse-relation-line.js +0 -20
  43. package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +0 -2
  44. package/dist/generator/mermaid-er/validator/parse-table-info.js +0 -71
  45. package/dist/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +0 -7
  46. package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +0 -9
  47. package/dist/generator/valibot/config/index.d.ts +0 -7
  48. package/dist/generator/valibot/config/index.js +0 -13
  49. package/dist/generator/valibot/core/extract-schema.d.ts +0 -5
  50. package/dist/generator/valibot/core/extract-schema.js +0 -173
  51. package/dist/generator/valibot/core.d.ts +0 -5
  52. package/dist/generator/valibot/core.js +0 -39
  53. package/dist/generator/valibot/generator/infer-input.d.ts +0 -5
  54. package/dist/generator/valibot/generator/infer-input.js +0 -8
  55. package/dist/generator/valibot/generator/relation-valibot-code.d.ts +0 -13
  56. package/dist/generator/valibot/generator/relation-valibot-code.js +0 -19
  57. package/dist/generator/valibot/generator/valibot-code.d.ts +0 -15
  58. package/dist/generator/valibot/generator/valibot-code.js +0 -16
  59. package/dist/generator/valibot/generator/valibot.d.ts +0 -14
  60. package/dist/generator/valibot/generator/valibot.js +0 -15
  61. package/dist/generator/valibot/generator.d.ts +0 -3
  62. package/dist/generator/valibot/generator.js +0 -14
  63. package/dist/generator/valibot/index.d.ts +0 -14
  64. package/dist/generator/valibot/index.js +0 -50
  65. package/dist/generator/zod/config/index.d.ts +0 -8
  66. package/dist/generator/zod/config/index.js +0 -14
  67. package/dist/generator/zod/core/extract-schema.d.ts +0 -7
  68. package/dist/generator/zod/core/extract-schema.js +0 -243
  69. package/dist/generator/zod/core.d.ts +0 -5
  70. package/dist/generator/zod/core.js +0 -39
  71. package/dist/generator/zod/generator/infer.d.ts +0 -5
  72. package/dist/generator/zod/generator/infer.js +0 -8
  73. package/dist/generator/zod/generator/relation-zod-code.d.ts +0 -13
  74. package/dist/generator/zod/generator/relation-zod-code.js +0 -19
  75. package/dist/generator/zod/generator/zod-code.d.ts +0 -17
  76. package/dist/generator/zod/generator/zod-code.js +0 -18
  77. package/dist/generator/zod/generator/zod.d.ts +0 -16
  78. package/dist/generator/zod/generator/zod.js +0 -16
  79. package/dist/generator/zod/generator.d.ts +0 -3
  80. package/dist/generator/zod/generator.js +0 -14
  81. package/dist/generator/zod/index.d.ts +0 -15
  82. package/dist/generator/zod/index.js +0 -54
  83. package/dist/index.d.ts +0 -7
  84. package/dist/index.js +0 -73
  85. package/dist/shared/config/index.d.ts +0 -13
  86. package/dist/shared/config/index.js +0 -10
  87. package/dist/shared/format/index.d.ts +0 -13
  88. package/dist/shared/format/index.js +0 -24
  89. package/dist/shared/fs/index.d.ts +0 -7
  90. package/dist/shared/fs/index.js +0 -16
  91. package/dist/shared/fsp/index.d.ts +0 -27
  92. package/dist/shared/fsp/index.js +0 -38
  93. package/dist/shared/generator/field-definitions.d.ts +0 -12
  94. package/dist/shared/generator/field-definitions.js +0 -12
  95. package/dist/shared/helper/ast-parser.d.ts +0 -3
  96. package/dist/shared/helper/ast-parser.js +0 -202
  97. package/dist/shared/helper/build-schema-extractor.d.ts +0 -25
  98. package/dist/shared/helper/build-schema-extractor.js +0 -33
  99. package/dist/shared/helper/create-extract-field-from-property.d.ts +0 -15
  100. package/dist/shared/helper/create-extract-field-from-property.js +0 -20
  101. package/dist/shared/helper/create-extract-fields-from-call-expression.d.ts +0 -14
  102. package/dist/shared/helper/create-extract-fields-from-call-expression.js +0 -14
  103. package/dist/shared/helper/create-extract-relation-field-from-property.d.ts +0 -12
  104. package/dist/shared/helper/create-extract-relation-field-from-property.js +0 -27
  105. package/dist/shared/helper/extract-schemas.d.ts +0 -133
  106. package/dist/shared/helper/extract-schemas.js +0 -445
  107. package/dist/shared/helper/file-writer.d.ts +0 -3
  108. package/dist/shared/helper/file-writer.js +0 -25
  109. package/dist/shared/helper/find-object-literal-expression.d.ts +0 -12
  110. package/dist/shared/helper/find-object-literal-expression.js +0 -31
  111. package/dist/shared/helper/find-object-literalIn-args.d.ts +0 -2
  112. package/dist/shared/helper/find-object-literalIn-args.js +0 -8
  113. package/dist/shared/helper/is-relation-function.d.ts +0 -10
  114. package/dist/shared/helper/is-relation-function.js +0 -16
  115. package/dist/shared/types.d.ts +0 -9
  116. package/dist/shared/types.js +0 -1
  117. package/dist/shared/utils/capitalize.d.ts +0 -18
  118. package/dist/shared/utils/capitalize.js +0 -20
  119. package/dist/shared/utils/compose.d.ts +0 -101
  120. package/dist/shared/utils/compose.js +0 -124
  121. package/dist/shared/utils/file.d.ts +0 -92
  122. package/dist/shared/utils/file.js +0 -177
  123. package/dist/shared/utils/functional.d.ts +0 -118
  124. package/dist/shared/utils/functional.js +0 -96
  125. package/dist/shared/utils/index.d.ts +0 -20
  126. package/dist/shared/utils/index.js +0 -48
  127. package/dist/shared/utils/string-utils.d.ts +0 -8
  128. package/dist/shared/utils/string-utils.js +0 -28
  129. package/dist/shared/utils/types.d.ts +0 -32
  130. package/dist/shared/utils/types.js +0 -2
  131. package/dist/shared/utils/validation-utils.d.ts +0 -8
  132. package/dist/shared/utils/validation-utils.js +0 -25
  133. package/dist/src/config/index.d.ts +0 -18
  134. package/dist/src/config/index.js +0 -13
  135. package/dist/src/generator/mermaid-er/core/extract-relations.d.ts +0 -8
  136. package/dist/src/generator/mermaid-er/core/extract-relations.js +0 -12
  137. package/dist/src/generator/mermaid-er/generator/er-content.d.ts +0 -9
  138. package/dist/src/generator/mermaid-er/generator/er-content.js +0 -25
  139. package/dist/src/generator/mermaid-er/generator/index.d.ts +0 -2
  140. package/dist/src/generator/mermaid-er/generator/index.js +0 -2
  141. package/dist/src/generator/mermaid-er/generator/relation-line.d.ts +0 -8
  142. package/dist/src/generator/mermaid-er/generator/relation-line.js +0 -14
  143. package/dist/src/generator/mermaid-er/index.d.ts +0 -6
  144. package/dist/src/generator/mermaid-er/index.js +0 -16
  145. package/dist/src/generator/mermaid-er/relationship/build-relation-line.d.ts +0 -15
  146. package/dist/src/generator/mermaid-er/relationship/build-relation-line.js +0 -35
  147. package/dist/src/generator/mermaid-er/types.d.ts +0 -21
  148. package/dist/src/generator/mermaid-er/types.js +0 -1
  149. package/dist/src/generator/mermaid-er/validator/index.d.ts +0 -4
  150. package/dist/src/generator/mermaid-er/validator/index.js +0 -4
  151. package/dist/src/generator/mermaid-er/validator/is-relationship.d.ts +0 -8
  152. package/dist/src/generator/mermaid-er/validator/is-relationship.js +0 -9
  153. package/dist/src/generator/mermaid-er/validator/parse-relation-line.d.ts +0 -13
  154. package/dist/src/generator/mermaid-er/validator/parse-relation-line.js +0 -21
  155. package/dist/src/generator/mermaid-er/validator/parse-table-info.d.ts +0 -8
  156. package/dist/src/generator/mermaid-er/validator/parse-table-info.js +0 -91
  157. package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +0 -7
  158. package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.js +0 -9
  159. package/dist/src/generator/valibot/generator/infer-input.d.ts +0 -5
  160. package/dist/src/generator/valibot/generator/infer-input.js +0 -8
  161. package/dist/src/generator/valibot/generator/valibot-code.d.ts +0 -14
  162. package/dist/src/generator/valibot/generator/valibot-code.js +0 -16
  163. package/dist/src/generator/valibot/generator/valibot.d.ts +0 -13
  164. package/dist/src/generator/valibot/generator/valibot.js +0 -11
  165. package/dist/src/generator/valibot/index.d.ts +0 -9
  166. package/dist/src/generator/valibot/index.js +0 -34
  167. package/dist/src/generator/zod/generator/infer.d.ts +0 -5
  168. package/dist/src/generator/zod/generator/infer.js +0 -8
  169. package/dist/src/generator/zod/generator/zod-code.d.ts +0 -16
  170. package/dist/src/generator/zod/generator/zod-code.js +0 -18
  171. package/dist/src/generator/zod/generator/zod.d.ts +0 -15
  172. package/dist/src/generator/zod/generator/zod.js +0 -12
  173. package/dist/src/generator/zod/index.d.ts +0 -10
  174. package/dist/src/generator/zod/index.js +0 -40
  175. package/dist/src/index.d.ts +0 -10
  176. package/dist/src/index.js +0 -35
  177. package/dist/src/shared/format/index.d.ts +0 -2
  178. package/dist/src/shared/format/index.js +0 -10
  179. package/dist/src/shared/fs/index.d.ts +0 -2
  180. package/dist/src/shared/fs/index.js +0 -10
  181. package/dist/src/shared/fsp/index.d.ts +0 -3
  182. package/dist/src/shared/fsp/index.js +0 -8
  183. package/dist/src/shared/generator/field-definitions.d.ts +0 -12
  184. package/dist/src/shared/generator/field-definitions.js +0 -12
  185. package/dist/src/shared/helper/build-schema-extractor.d.ts +0 -25
  186. package/dist/src/shared/helper/build-schema-extractor.js +0 -33
  187. package/dist/src/shared/helper/create-extract-field-from-property.d.ts +0 -15
  188. package/dist/src/shared/helper/create-extract-field-from-property.js +0 -20
  189. package/dist/src/shared/helper/create-extract-fields-from-call-expression.d.ts +0 -14
  190. package/dist/src/shared/helper/create-extract-fields-from-call-expression.js +0 -14
  191. package/dist/src/shared/helper/create-extract-relation-field-from-property.d.ts +0 -12
  192. package/dist/src/shared/helper/create-extract-relation-field-from-property.js +0 -27
  193. package/dist/src/shared/helper/extract-schemas.d.ts +0 -16
  194. package/dist/src/shared/helper/extract-schemas.js +0 -19
  195. package/dist/src/shared/helper/find-object-literal-expression.d.ts +0 -12
  196. package/dist/src/shared/helper/find-object-literal-expression.js +0 -31
  197. package/dist/src/shared/helper/find-object-literalIn-args.d.ts +0 -2
  198. package/dist/src/shared/helper/find-object-literalIn-args.js +0 -8
  199. package/dist/src/shared/helper/is-relation-function.d.ts +0 -10
  200. package/dist/src/shared/helper/is-relation-function.js +0 -16
  201. package/dist/src/shared/utils/index.d.ts +0 -33
  202. package/dist/src/shared/utils/index.js +0 -61
  203. package/dist/utils/index.d.ts +0 -144
  204. package/dist/utils/index.js +0 -250
@@ -1,27 +0,0 @@
1
- import { Node } from 'ts-morph';
2
- import { extractFieldComments, schemaName } from '../utils/index.js';
3
- export const createExtractRelationFieldFromProperty = (parseFieldComments, prefix) => {
4
- return (property, sourceText) => {
5
- if (!Node.isPropertyAssignment(property))
6
- return null;
7
- const name = property.getName();
8
- if (!name)
9
- return null;
10
- const init = property.getInitializer();
11
- if (!Node.isCallExpression(init))
12
- return { name, definition: '', description: undefined };
13
- const expr = init.getExpression();
14
- if (!Node.isIdentifier(expr))
15
- return { name, definition: '', description: undefined };
16
- const fnName = expr.getText();
17
- const args = init.getArguments();
18
- if (!(args.length && Node.isIdentifier(args[0]))) {
19
- return { name, definition: '', description: undefined };
20
- }
21
- const refTable = args[0].getText();
22
- const schema = schemaName(refTable);
23
- const definition = fnName === 'many' ? `${prefix}.array(${schema})` : fnName === 'one' ? schema : '';
24
- const { description } = parseFieldComments(extractFieldComments(sourceText, property.getStart()));
25
- return { name, definition, description };
26
- };
27
- };
@@ -1,133 +0,0 @@
1
- /**
2
- * Supported validation library types.
3
- */
4
- export type ValidationLibrary = 'zod' | 'valibot';
5
- /**
6
- * Schema extraction result type containing table name and field definitions.
7
- */
8
- export type SchemaExtractionResult = {
9
- /** The name of the table/schema */
10
- name: string;
11
- /** Optional base schema/table name (used for relations) */
12
- baseName?: string;
13
- /** Array of field definitions with name, validation definition, and description */
14
- fields: {
15
- /** Field name */
16
- name: string;
17
- /** Validation definition (e.g., 'z.uuid()', 'v.pipe(v.string(), v.uuid())') */
18
- definition: string;
19
- /** Optional field description from comments */
20
- description?: string;
21
- }[];
22
- /** Object type for schema generation ('strict' | 'loose' | undefined) */
23
- objectType?: 'strict' | 'loose';
24
- };
25
- /**
26
- * Relation schema extraction result with required base name.
27
- */
28
- export type RelationSchemaExtractionResult = {
29
- name: string;
30
- baseName: string;
31
- fields: {
32
- name: string;
33
- definition: string;
34
- description?: string;
35
- }[];
36
- /** Object type for schema generation ('strict' | 'loose' | undefined) */
37
- objectType?: 'strict' | 'loose';
38
- };
39
- /**
40
- * Extracts schemas from TypeScript source code using AST analysis.
41
- *
42
- * This function processes exported variable declarations to extract table schemas
43
- * with their field definitions and comments. It supports both Zod and Valibot schema extraction.
44
- *
45
- * @param lines - Array of source code lines to process
46
- * @param library - The validation library to extract schemas for ('zod' or 'valibot')
47
- * @returns Array of extracted schemas with field definitions
48
- *
49
- * @example
50
- * ```typescript
51
- * // For Zod schemas
52
- * const zodSchemas = extractSchemas(sourceLines, 'zod')
53
- *
54
- * // For Valibot schemas
55
- * const valibotSchemas = extractSchemas(sourceLines, 'valibot')
56
- * ```
57
- */
58
- export declare function extractSchemas(lines: string[], library: ValidationLibrary): SchemaExtractionResult[];
59
- /**
60
- * Extracts Zod schemas from TypeScript source code using AST analysis.
61
- *
62
- * This function processes exported variable declarations to extract table schemas
63
- * with their field definitions and comments. It automatically handles Zod schema extraction.
64
- *
65
- * @param lines - Array of source code lines to process
66
- * @returns Array of extracted schemas with field definitions
67
- *
68
- * @example
69
- * ```typescript
70
- * const schemas = extractZodSchemas(sourceLines)
71
- * // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'z.uuid()', description: 'Primary key' }] }]
72
- * ```
73
- */
74
- export declare function extractZodSchemas(lines: string[]): SchemaExtractionResult[];
75
- /**
76
- * Extracts Valibot schemas from TypeScript source code using AST analysis.
77
- *
78
- * This function processes exported variable declarations to extract table schemas
79
- * with their field definitions and comments. It automatically handles Valibot schema extraction.
80
- *
81
- * @param lines - Array of source code lines to process
82
- * @returns Array of extracted schemas with field definitions
83
- *
84
- * @example
85
- * ```typescript
86
- * const schemas = extractValibotSchemas(sourceLines)
87
- * // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'v.pipe(v.string(), v.uuid())', description: 'Primary key' }] }]
88
- * ```
89
- */
90
- export declare function extractValibotSchemas(lines: string[]): SchemaExtractionResult[];
91
- /**
92
- * Extracts relation schemas from `relations(...)` declarations using AST analysis.
93
- *
94
- * This returns entries like `userRelations` and `postRelations` with fields
95
- * resolved to either `z.array(OtherSchema)` / `v.array(OtherSchema)` or direct
96
- * `OtherSchema` based on `many`/`one`.
97
- *
98
- * Note: Base table schemas are not included here; use `extractSchemas` for those.
99
- */
100
- export declare function extractRelationSchemas(lines: string[], library: ValidationLibrary): RelationSchemaExtractionResult[];
101
- /**
102
- * Extracts relations from the given code.
103
- *
104
- * @param code - The code to extract relations from.
105
- * @returns The extracted relations.
106
- */
107
- export declare function extractRelations(code: string[]): {
108
- fromModel: string;
109
- toModel: string;
110
- fromField: string;
111
- toField: string;
112
- type: string;
113
- }[];
114
- /**
115
- * Parse relation line and extract components.
116
- *
117
- * @param line - The line to parse.
118
- * @returns Parsed relation or null if not a relation line.
119
- */
120
- export declare function parseRelationLine(line: string): {
121
- fromModel: string;
122
- toModel: string;
123
- fromField: string;
124
- toField: string;
125
- type: string;
126
- } | null;
127
- /**
128
- * Build a relation line from a string.
129
- *
130
- * @param input - The input string.
131
- * @returns The built relation line.
132
- */
133
- export declare function buildRelationLine(input: string): string;
@@ -1,445 +0,0 @@
1
- import { Node, Project } from 'ts-morph';
2
- import { capitalize, containsSubstring, extractFieldComments, parseFieldComments, removeOptionalSuffix, splitByDot, splitByTo, splitByWhitespace, startsWith, trimString, } from '../../utils/index.js';
3
- /**
4
- * Generates relation definition based on function name and reference table.
5
- *
6
- * @param fnName - The relation function name ('many' or 'one')
7
- * @param refTable - The referenced table name
8
- * @param prefix - Schema prefix ('v' or 'z') for validation library
9
- * @returns The generated relation definition string
10
- */
11
- function generateRelationDefinition(fnName, refTable, prefix) {
12
- const schema = `${capitalize(refTable)}Schema`;
13
- return fnName === 'many' ? `${prefix}.array(${schema})` : fnName === 'one' ? schema : '';
14
- }
15
- /**
16
- * Processes arrow function body to find object literal expression.
17
- *
18
- * @param body - The arrow function body node
19
- * @returns The found object literal expression, or null if not found
20
- */
21
- function processArrowFunctionBody(body) {
22
- if (Node.isObjectLiteralExpression(body))
23
- return body;
24
- if (Node.isParenthesizedExpression(body)) {
25
- return findObjectLiteralExpression(body.getExpression());
26
- }
27
- if (Node.isBlock(body)) {
28
- const ret = body.getStatements().find(Node.isReturnStatement);
29
- if (ret && Node.isReturnStatement(ret)) {
30
- const re = ret.getExpression();
31
- return re && Node.isObjectLiteralExpression(re) ? re : null;
32
- }
33
- }
34
- return null;
35
- }
36
- /**
37
- * Recursively extracts an `ObjectLiteralExpression` from a given AST node.
38
- *
39
- * @param expr - The root `Node` to search for object literals
40
- * @returns The found `ObjectLiteralExpression`, or `null` if not found
41
- */
42
- function findObjectLiteralExpression(expr) {
43
- if (Node.isObjectLiteralExpression(expr))
44
- return expr;
45
- if (Node.isParenthesizedExpression(expr)) {
46
- return findObjectLiteralExpression(expr.getExpression());
47
- }
48
- if (Node.isArrowFunction(expr)) {
49
- return processArrowFunctionBody(expr.getBody());
50
- }
51
- return null;
52
- }
53
- /**
54
- * Finds an object literal expression in call expression arguments.
55
- *
56
- * @param call - The call expression to search for object literals in its arguments
57
- * @param finder - Function to find object literal in a node
58
- * @returns The found object literal, or `null` if not found in any argument
59
- */
60
- function findObjectLiteralInArgs(call, finder) {
61
- for (const arg of call.getArguments()) {
62
- const obj = finder(arg);
63
- if (obj)
64
- return obj;
65
- }
66
- return null;
67
- }
68
- /**
69
- * Determines whether a given `CallExpression` is a relation-related function call.
70
- *
71
- * @param callExpr - The call expression node to check for relation functions
72
- * @returns `true` if the function is a relation function; otherwise, `false`
73
- */
74
- function isRelationFunctionCall(callExpr) {
75
- const expression = callExpr.getExpression();
76
- if (!Node.isIdentifier(expression))
77
- return false;
78
- const functionName = expression.getText();
79
- return functionName === 'relations' || functionName.includes('relation');
80
- }
81
- /**
82
- * Creates a field extractor function using a custom parseFieldComments implementation.
83
- *
84
- * @param parseFieldComments - A function that parses comment lines into { definition, description, objectType }
85
- * @returns A property node extractor function
86
- */
87
- function createExtractFieldFromProperty(parseFieldComments) {
88
- return (property, sourceText) => {
89
- if (!Node.isPropertyAssignment(property))
90
- return null;
91
- const name = property.getName();
92
- if (!name)
93
- return null;
94
- const commentLines = extractFieldComments(sourceText, property.getStart());
95
- const { definition, description } = parseFieldComments(commentLines);
96
- return { name, definition, description };
97
- };
98
- }
99
- /**
100
- * Creates a relation field extractor function.
101
- *
102
- * @param parseFieldComments - Function to parse field comments
103
- * @param prefix - Schema prefix ('v' or 'z') for validation library
104
- * @returns Function that extracts relation fields from property
105
- */
106
- function createExtractRelationFieldFromProperty(parseFieldComments, prefix) {
107
- return (property, sourceText) => {
108
- if (!Node.isPropertyAssignment(property))
109
- return null;
110
- const name = property.getName();
111
- if (!name)
112
- return null;
113
- const init = property.getInitializer();
114
- if (!Node.isCallExpression(init)) {
115
- return { name, definition: '', description: undefined };
116
- }
117
- const expr = init.getExpression();
118
- if (!Node.isIdentifier(expr)) {
119
- return { name, definition: '', description: undefined };
120
- }
121
- const fnName = expr.getText();
122
- const args = init.getArguments();
123
- if (!(args.length && Node.isIdentifier(args[0]))) {
124
- return { name, definition: '', description: undefined };
125
- }
126
- const refTable = args[0].getText();
127
- const definition = generateRelationDefinition(fnName, refTable, prefix);
128
- const { description } = parseFieldComments(extractFieldComments(sourceText, property.getStart()));
129
- return { name, definition, description };
130
- };
131
- }
132
- /**
133
- * Extracts fields from object literal properties using appropriate extractor.
134
- *
135
- * @param properties - Array of object literal properties
136
- * @param isRelation - Whether this is a relation function call
137
- * @param extractFieldFromProperty - Function to extract regular fields
138
- * @param extractRelationFieldFromProperty - Function to extract relation fields
139
- * @param sourceText - The source text for comment extraction
140
- * @returns Array of extracted field results
141
- */
142
- function extractFieldsFromProperties(properties, isRelation, extractFieldFromProperty, extractRelationFieldFromProperty, sourceText) {
143
- return properties
144
- .map((prop) => isRelation
145
- ? extractRelationFieldFromProperty(prop, sourceText)
146
- : extractFieldFromProperty(prop, sourceText))
147
- .filter((field) => field !== null);
148
- }
149
- /**
150
- * Creates a field extractor for call expressions with customizable strategies.
151
- *
152
- * @param extractFieldFromProperty - Function to extract field from property
153
- * @param extractRelationFieldFromProperty - Function to extract relation field from property
154
- * @param findObjectLiteralExpression - Function to find object literal expression
155
- * @param findObjectLiteralInArgs - Function to find object literal in call arguments
156
- * @param isRelationFunctionCall - Function to check if call is relation function
157
- * @returns Function that extracts fields from call expression
158
- */
159
- function createExtractFieldsFromCallExpression(extractFieldFromProperty, extractRelationFieldFromProperty, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall) {
160
- return (callExpr, sourceText) => {
161
- const objectLiteral = findObjectLiteralInArgs(callExpr, findObjectLiteralExpression);
162
- if (!objectLiteral)
163
- return [];
164
- const isRelation = isRelationFunctionCall(callExpr);
165
- const properties = objectLiteral.getProperties();
166
- return extractFieldsFromProperties(properties, isRelation, extractFieldFromProperty, extractRelationFieldFromProperty, sourceText);
167
- };
168
- }
169
- /**
170
- * Creates a schema extractor from customizable strategies.
171
- *
172
- * @param extractFieldsFromCall - Function to extract fields from a call expression
173
- * @param extractFieldFromProperty - Function to extract a single field from an object literal property
174
- * @param parseFieldComments - Function to parse field comments with object type support
175
- * @param commentPrefix - The comment prefix to use for parsing
176
- * @returns A function that extracts a schema from a variable declaration node
177
- */
178
- function buildSchemaExtractor(extractFieldsFromCall, extractFieldFromProperty, parseFieldComments, commentPrefix) {
179
- return (variableStatement, sourceText, originalSourceCode) => {
180
- if (!Node.isVariableStatement(variableStatement))
181
- return null;
182
- const declarations = variableStatement.getDeclarations();
183
- if (declarations.length === 0)
184
- return null;
185
- const declaration = declarations[0];
186
- const name = declaration.getName();
187
- if (!name)
188
- return null;
189
- // Extract object type from table-level comments
190
- // Since ts-morph doesn't capture all comments properly, we'll parse the original source
191
- const statementStart = variableStatement.getStart();
192
- const originalSourceLines = originalSourceCode.split('\n'); // Use original source, not AST sourceText
193
- const commentLines = [];
194
- // Find the line number where this statement starts
195
- let lineNumber = 0;
196
- let charCount = 0;
197
- for (let i = 0; i < originalSourceLines.length; i++) {
198
- if (charCount >= statementStart) {
199
- lineNumber = i;
200
- break;
201
- }
202
- charCount += originalSourceLines[i].length + 1; // +1 for newline
203
- }
204
- // Collect comments immediately before the statement
205
- for (let i = lineNumber - 1; i >= 0; i--) {
206
- const line = originalSourceLines[i];
207
- const trimmedLine = trimString(line);
208
- // Skip empty lines
209
- if (trimmedLine === '')
210
- continue;
211
- // If it's a comment line, add it to our collection
212
- if (startsWith(trimmedLine, '///')) {
213
- commentLines.unshift(line);
214
- }
215
- else {
216
- // If we hit a non-comment line, stop collecting
217
- break;
218
- }
219
- }
220
- const { objectType } = parseFieldComments(commentLines, commentPrefix);
221
- const initializer = declaration.getInitializer();
222
- if (Node.isCallExpression(initializer)) {
223
- if (isRelationFunctionCall(initializer))
224
- return null;
225
- const fields = extractFieldsFromCall(initializer, sourceText);
226
- return { name, fields, objectType };
227
- }
228
- if (Node.isObjectLiteralExpression(initializer)) {
229
- const fields = initializer
230
- .getProperties()
231
- .map((prop) => extractFieldFromProperty(prop, sourceText))
232
- .filter((field) => field !== null);
233
- return { name, fields, objectType };
234
- }
235
- return { name, fields: [], objectType };
236
- };
237
- }
238
- /**
239
- * Extracts schemas from TypeScript source code using AST analysis.
240
- *
241
- * This function processes exported variable declarations to extract table schemas
242
- * with their field definitions and comments. It supports both Zod and Valibot schema extraction.
243
- *
244
- * @param lines - Array of source code lines to process
245
- * @param library - The validation library to extract schemas for ('zod' or 'valibot')
246
- * @returns Array of extracted schemas with field definitions
247
- *
248
- * @example
249
- * ```typescript
250
- * // For Zod schemas
251
- * const zodSchemas = extractSchemas(sourceLines, 'zod')
252
- *
253
- * // For Valibot schemas
254
- * const valibotSchemas = extractSchemas(sourceLines, 'valibot')
255
- * ```
256
- */
257
- export function extractSchemas(lines, library) {
258
- const sourceCode = lines.join('\n');
259
- const project = new Project({
260
- useInMemoryFileSystem: true,
261
- compilerOptions: {
262
- allowJs: true,
263
- skipLibCheck: true,
264
- },
265
- });
266
- const sourceFile = project.createSourceFile('temp.ts', sourceCode);
267
- const sourceText = sourceFile.getFullText();
268
- const commentPrefix = library === 'zod' ? '@z.' : '@v.';
269
- const schemaPrefix = library === 'zod' ? 'z' : 'v';
270
- const extractField = createExtractFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix));
271
- const extractRelationField = createExtractRelationFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix), schemaPrefix);
272
- const extractFieldsFromCall = createExtractFieldsFromCallExpression(extractField, extractRelationField, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall);
273
- const extractSchema = buildSchemaExtractor(extractFieldsFromCall, extractField, parseFieldComments, commentPrefix);
274
- return sourceFile
275
- .getVariableStatements()
276
- .filter((stmt) => stmt.hasExportKeyword())
277
- .map((stmt) => extractSchema(stmt, sourceText, sourceCode))
278
- .filter((schema) => schema !== null);
279
- }
280
- /**
281
- * Extracts Zod schemas from TypeScript source code using AST analysis.
282
- *
283
- * This function processes exported variable declarations to extract table schemas
284
- * with their field definitions and comments. It automatically handles Zod schema extraction.
285
- *
286
- * @param lines - Array of source code lines to process
287
- * @returns Array of extracted schemas with field definitions
288
- *
289
- * @example
290
- * ```typescript
291
- * const schemas = extractZodSchemas(sourceLines)
292
- * // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'z.uuid()', description: 'Primary key' }] }]
293
- * ```
294
- */
295
- export function extractZodSchemas(lines) {
296
- return extractSchemas(lines, 'zod');
297
- }
298
- /**
299
- * Extracts Valibot schemas from TypeScript source code using AST analysis.
300
- *
301
- * This function processes exported variable declarations to extract table schemas
302
- * with their field definitions and comments. It automatically handles Valibot schema extraction.
303
- *
304
- * @param lines - Array of source code lines to process
305
- * @returns Array of extracted schemas with field definitions
306
- *
307
- * @example
308
- * ```typescript
309
- * const schemas = extractValibotSchemas(sourceLines)
310
- * // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'v.pipe(v.string(), v.uuid())', description: 'Primary key' }] }]
311
- * ```
312
- */
313
- export function extractValibotSchemas(lines) {
314
- return extractSchemas(lines, 'valibot');
315
- }
316
- /**
317
- * Extracts relation schemas from `relations(...)` declarations using AST analysis.
318
- *
319
- * This returns entries like `userRelations` and `postRelations` with fields
320
- * resolved to either `z.array(OtherSchema)` / `v.array(OtherSchema)` or direct
321
- * `OtherSchema` based on `many`/`one`.
322
- *
323
- * Note: Base table schemas are not included here; use `extractSchemas` for those.
324
- */
325
- export function extractRelationSchemas(lines, library) {
326
- const sourceCode = lines.join('\n');
327
- const project = new Project({
328
- useInMemoryFileSystem: true,
329
- compilerOptions: { allowJs: true, skipLibCheck: true },
330
- });
331
- const sourceFile = project.createSourceFile('temp.ts', sourceCode);
332
- const sourceText = sourceFile.getFullText();
333
- const commentPrefix = library === 'zod' ? '@z.' : '@v.';
334
- const schemaPrefix = library === 'zod' ? 'z' : 'v';
335
- // First, extract base schemas to get their objectType
336
- const baseSchemas = extractSchemas(lines, library);
337
- const baseSchemaMap = new Map(baseSchemas.map((schema) => [schema.name, schema.objectType]));
338
- const extractField = createExtractFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix));
339
- const extractRelationField = createExtractRelationFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix), schemaPrefix);
340
- const extractFieldsFromCall = createExtractFieldsFromCallExpression(extractField, extractRelationField, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall);
341
- function extract(declaration) {
342
- if (!Node.isVariableDeclaration(declaration))
343
- return null;
344
- const name = declaration.getName();
345
- if (!name)
346
- return null;
347
- const initializer = declaration.getInitializer();
348
- if (!Node.isCallExpression(initializer))
349
- return null;
350
- if (!isRelationFunctionCall(initializer))
351
- return null;
352
- const relArgs = initializer.getArguments();
353
- const baseIdentifier = relArgs.length && Node.isIdentifier(relArgs[0]) ? relArgs[0] : undefined;
354
- if (!baseIdentifier)
355
- return null;
356
- const baseName = baseIdentifier.getText();
357
- const fields = extractFieldsFromCall(initializer, sourceText);
358
- // Inherit objectType from the base schema
359
- const objectType = baseSchemaMap.get(baseName);
360
- return { name, baseName, fields, objectType };
361
- }
362
- return sourceFile
363
- .getVariableStatements()
364
- .filter((stmt) => stmt.hasExportKeyword())
365
- .flatMap((stmt) => stmt.getDeclarations())
366
- .map((decl) => extract(decl))
367
- .filter((schema) => schema !== null);
368
- }
369
- /**
370
- * Extracts relations from the given code.
371
- *
372
- * @param code - The code to extract relations from.
373
- * @returns The extracted relations.
374
- */
375
- export function extractRelations(code) {
376
- const relations = [];
377
- for (const line of code) {
378
- const relation = parseRelationLine(line);
379
- if (relation) {
380
- relations.push(relation);
381
- }
382
- }
383
- return relations;
384
- }
385
- /**
386
- * Parse relation line and extract components.
387
- *
388
- * @param line - The line to parse.
389
- * @returns Parsed relation or null if not a relation line.
390
- */
391
- export function parseRelationLine(line) {
392
- const trimmedLine = trimString(line);
393
- const cleanLine = startsWith(trimmedLine, '///') ? trimmedLine.substring(3) : trimmedLine;
394
- const finalLine = trimString(cleanLine);
395
- if (!startsWith(finalLine, '@relation'))
396
- return null;
397
- const parts = splitByWhitespace(finalLine);
398
- if (parts.length < 4)
399
- return null;
400
- const fromParts = splitByDot(parts[1]);
401
- const toParts = splitByDot(parts[2]);
402
- if (fromParts.length !== 2 || toParts.length !== 2)
403
- return null;
404
- return {
405
- fromModel: fromParts[0],
406
- fromField: fromParts[1],
407
- toModel: toParts[0],
408
- toField: toParts[1],
409
- type: parts[3],
410
- };
411
- }
412
- /**
413
- * Build a relation line from a string.
414
- *
415
- * @param input - The input string.
416
- * @returns The built relation line.
417
- */
418
- export function buildRelationLine(input) {
419
- const toSymbol = (r) => r === 'zero-one'
420
- ? '|o'
421
- : r === 'one'
422
- ? '||'
423
- : r === 'zero-many'
424
- ? '}o'
425
- : r === 'many'
426
- ? '}|'
427
- : (() => {
428
- throw new Error(`Invalid relationship: ${r}`);
429
- })();
430
- const isRelationship = (r) => ['zero-one', 'one', 'zero-many', 'many'].includes(r);
431
- const parts = splitByTo(input);
432
- if (!parts)
433
- throw new Error(`Invalid input format: ${input}`);
434
- const [fromRaw, toRawWithOptional] = parts;
435
- const [toRaw, isOptional] = containsSubstring(toRawWithOptional, '-optional')
436
- ? [removeOptionalSuffix(toRawWithOptional), true]
437
- : [toRawWithOptional, false];
438
- if (!(isRelationship(fromRaw) && isRelationship(toRaw))) {
439
- throw new Error(`Invalid relationship string: ${input}`);
440
- }
441
- const fromSymbol = toSymbol(fromRaw);
442
- const toSymbolStr = toSymbol(toRaw);
443
- const connector = isOptional ? '..' : '--';
444
- return `${fromSymbol}${connector}${toSymbolStr}`;
445
- }
@@ -1,3 +0,0 @@
1
- import { Result } from 'neverthrow';
2
- export declare const writeFileSafely: (filePath: string, content: string) => Promise<Result<void, Error>>;
3
- export declare const ensureDirectoryExists: (directory: string) => Promise<Result<void, Error>>;
@@ -1,25 +0,0 @@
1
- import { writeFile, mkdir } from 'fs/promises';
2
- import { dirname } from 'path';
3
- import { Result, err, ok } from 'neverthrow';
4
- export const writeFileSafely = async (filePath, content) => {
5
- try {
6
- // ディレクトリが存在しない場合は作成
7
- const directory = dirname(filePath);
8
- await mkdir(directory, { recursive: true });
9
- // ファイルを書き込み
10
- await writeFile(filePath, content, 'utf-8');
11
- return ok(undefined);
12
- }
13
- catch (error) {
14
- return err(new Error(`Failed to write file ${filePath}: ${error instanceof Error ? error.message : String(error)}`));
15
- }
16
- };
17
- export const ensureDirectoryExists = async (directory) => {
18
- try {
19
- await mkdir(directory, { recursive: true });
20
- return ok(undefined);
21
- }
22
- catch (error) {
23
- return err(new Error(`Failed to create directory ${directory}: ${error instanceof Error ? error.message : String(error)}`));
24
- }
25
- };
@@ -1,12 +0,0 @@
1
- import type { ObjectLiteralExpression } from 'ts-morph';
2
- import { Node } from 'ts-morph';
3
- /**
4
- * Recursively extracts an `ObjectLiteralExpression` from a given AST node.
5
- *
6
- * Supports direct object literals, parenthesized expressions,
7
- * arrow functions returning object literals (including wrapped and block bodies).
8
- *
9
- * @param expr - The root `Node` to search.
10
- * @returns The found `ObjectLiteralExpression`, or `null` if not found.
11
- */
12
- export declare function findObjectLiteralExpression(expr: Node): ObjectLiteralExpression | null;
@@ -1,31 +0,0 @@
1
- import { Node } from 'ts-morph';
2
- /**
3
- * Recursively extracts an `ObjectLiteralExpression` from a given AST node.
4
- *
5
- * Supports direct object literals, parenthesized expressions,
6
- * arrow functions returning object literals (including wrapped and block bodies).
7
- *
8
- * @param expr - The root `Node` to search.
9
- * @returns The found `ObjectLiteralExpression`, or `null` if not found.
10
- */
11
- export function findObjectLiteralExpression(expr) {
12
- if (Node.isObjectLiteralExpression(expr))
13
- return expr;
14
- if (Node.isParenthesizedExpression(expr))
15
- return findObjectLiteralExpression(expr.getExpression());
16
- if (Node.isArrowFunction(expr)) {
17
- const body = expr.getBody();
18
- if (Node.isObjectLiteralExpression(body))
19
- return body;
20
- if (Node.isParenthesizedExpression(body))
21
- return findObjectLiteralExpression(body.getExpression());
22
- if (Node.isBlock(body)) {
23
- const ret = body.getStatements().find(Node.isReturnStatement);
24
- if (ret && Node.isReturnStatement(ret)) {
25
- const re = ret.getExpression();
26
- return re && Node.isObjectLiteralExpression(re) ? re : null;
27
- }
28
- }
29
- }
30
- return null;
31
- }
@@ -1,2 +0,0 @@
1
- import type { CallExpression, Node, ObjectLiteralExpression } from 'ts-morph';
2
- export declare function findObjectLiteralInArgs(call: CallExpression, finder: (expr: Node) => ObjectLiteralExpression | null): ObjectLiteralExpression | null;