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,15 @@
1
+ import { capitalize, fieldDefinitions } from '../../../utils/index.js';
2
+ /**
3
+ * @param schema
4
+ * @param config
5
+ * @returns
6
+ */
7
+ export function valibot(schema, comment) {
8
+ const res = fieldDefinitions(schema, comment);
9
+ const objectType = schema.objectType === 'strict'
10
+ ? 'strictObject'
11
+ : schema.objectType === 'loose'
12
+ ? 'looseObject'
13
+ : 'object';
14
+ return `export const ${capitalize(schema.name)}Schema = v.${objectType}({${res}})`;
15
+ }
@@ -0,0 +1,3 @@
1
+ import { Result } from 'neverthrow';
2
+ import type { ParsedSchema } from '../../shared/utils/types.js';
3
+ export declare const generateValibotSchemas: (schema: ParsedSchema) => Result<string, Error>;
@@ -0,0 +1,14 @@
1
+ import { Result, err, ok } from 'neverthrow';
2
+ import { generateValibotFile } from './core.js';
3
+ export const generateValibotSchemas = (schema) => {
4
+ try {
5
+ if (schema.tables.length === 0) {
6
+ return err(new Error('No tables found in schema'));
7
+ }
8
+ const valibotContent = generateValibotFile(schema.tables);
9
+ return ok(valibotContent);
10
+ }
11
+ catch (error) {
12
+ return err(new Error(`Failed to generate Valibot schemas: ${error instanceof Error ? error.message : String(error)}`));
13
+ }
14
+ };
@@ -1,3 +1,14 @@
1
- #!/usr/bin/env node
2
- import type { Config } from '../../common/config';
3
- export declare function main(dev?: boolean, config?: Config): Promise<boolean>;
1
+ /**
2
+ * Generate Valibot schema
3
+ * @param code - The code to generate Valibot schema from
4
+ * @param output - The output file path
5
+ * @param comment - Whether to include comments in the generated code
6
+ * @param type - Whether to include type information in the generated code
7
+ */
8
+ export declare function sizukuValibot(code: string[], output: `${string}.ts`, comment?: boolean, type?: boolean, relations?: boolean): Promise<{
9
+ ok: true;
10
+ value: undefined;
11
+ } | {
12
+ ok: false;
13
+ error: string;
14
+ }>;
@@ -1,77 +1,50 @@
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.main = main;
8
- const node_fs_1 = require("node:fs");
9
- const node_path_1 = __importDefault(require("node:path"));
10
- const extract_schema_1 = require("./core/extract-schema");
11
- const format_1 = require("../../common/format");
12
- const config_1 = require("./config");
13
- const node_process_1 = require("node:process");
14
- const generate_valibot_code_1 = require("./generator/generate-valibot-code");
15
- const IMPORT_VALIBOT = 'import * as v from "valibot"';
16
- async function main(dev = false, config = (0, config_1.getConfig)()) {
17
- // 1. argv ['**/bin/node', ''/workspaces/sizuku-test/packages/sizuku/dist/generator/zod/index.js',', 'db/schema.ts', '-o', 'zod/index.ts']
18
- if (config.output === undefined && !node_process_1.argv.includes('-o')) {
19
- console.error('Error: -o is not found');
20
- return false;
1
+ import path from 'node:path';
2
+ import { fmt } from '../../shared/format/index.js';
3
+ import { mkdir, writeFile } from '../../shared/fsp/index.js';
4
+ import { extractRelationSchemas, extractSchemas } from '../../shared/helper/extract-schemas.js';
5
+ import { relationValibotCode } from './generator/relation-valibot-code.js';
6
+ import { valibotCode } from './generator/valibot-code.js';
7
+ /**
8
+ * Generate Valibot schema
9
+ * @param code - The code to generate Valibot schema from
10
+ * @param output - The output file path
11
+ * @param comment - Whether to include comments in the generated code
12
+ * @param type - Whether to include type information in the generated code
13
+ */
14
+ export async function sizukuValibot(code, output, comment, type, relations) {
15
+ const baseSchemas = extractSchemas(code, 'valibot');
16
+ const relationSchemas = extractRelationSchemas(code, 'valibot');
17
+ const valibotGeneratedCode = [
18
+ "import * as v from 'valibot'",
19
+ '',
20
+ ...baseSchemas.map((schema) => valibotCode(schema, comment ?? false, type ?? false)),
21
+ ...(relations
22
+ ? relationSchemas.map((schema) => relationValibotCode(schema, type ?? false))
23
+ : []),
24
+ ].join('\n');
25
+ const mkdirResult = await mkdir(path.dirname(output));
26
+ if (!mkdirResult.ok) {
27
+ return {
28
+ ok: false,
29
+ error: mkdirResult.error,
30
+ };
21
31
  }
22
- // 2. slice ['db/schema.ts', '-o', 'zod/index.ts']
23
- const args = process.argv.slice(2);
24
- // 3. input = args[0] = 'db/schema.ts'
25
- const input = config.input ?? args[0];
26
- config.input = input;
27
- // 4. output = 'zod/index.ts'
28
- const output = config.output ?? args[args.indexOf('-o') + 1];
29
- config.output = output;
30
- try {
31
- // 5. read db/schema.ts
32
- const content = (0, node_fs_1.readFileSync)(input, 'utf-8');
33
- // 6. split lines
34
- const lines = content.split('\n');
35
- // 7. create output directory
36
- const outputDir = node_path_1.default.dirname(output);
37
- if (!(0, node_fs_1.existsSync)(outputDir)) {
38
- (0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
39
- }
40
- // 8. skip import section
41
- const codeStart = lines.findIndex((line) => !line.trim().startsWith('import') && line.trim() !== '');
42
- // 9. extract schemas
43
- const schemas = (0, extract_schema_1.extractSchemas)(lines.slice(codeStart));
44
- // 10. generate zod code
45
- const generatedCode = [
46
- IMPORT_VALIBOT,
47
- '',
48
- ...schemas.map((schema) => (0, generate_valibot_code_1.generateValibotCode)(schema, config)),
49
- ].join('\n');
50
- // 11. format code
51
- const code = await (0, format_1.formatCode)(generatedCode);
52
- // 12. write to output file
53
- (0, node_fs_1.writeFileSync)(output, code);
54
- console.log(`Generated Valibot schema at: ${output}`);
55
- return true;
32
+ const fmtResult = await fmt(valibotGeneratedCode);
33
+ if (!fmtResult.ok) {
34
+ return {
35
+ ok: false,
36
+ error: fmtResult.error,
37
+ };
56
38
  }
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;
39
+ const writeFileResult = await writeFile(output, fmtResult.value);
40
+ if (!writeFileResult.ok) {
41
+ return {
42
+ ok: false,
43
+ error: writeFileResult.error,
44
+ };
69
45
  }
70
- }
71
- if (require.main === module) {
72
- main().then((success) => {
73
- if (!success) {
74
- process.exit(1);
75
- }
76
- });
46
+ return {
47
+ ok: true,
48
+ value: undefined,
49
+ };
77
50
  }
@@ -1,8 +1,8 @@
1
- import type { Config } from '../../../common/config';
1
+ import type { Config } from '../../../shared/config/index.js'
2
2
  /**
3
3
  * Loads the configuration from the `sizuku.json` file or returns the default configuration.
4
4
  *
5
5
  * @function getConfig
6
6
  * @returns The configuration object.
7
7
  */
8
- export declare function getConfig(): Config;
8
+ export declare function getConfig(): Config
@@ -1,20 +1,14 @@
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"));
8
- const config_1 = require("../../../common/config");
1
+ import fs from 'node:fs';
2
+ import { DEFAULT_CONFIG } from '../../../shared/config/index.js';
9
3
  /**
10
4
  * Loads the configuration from the `sizuku.json` file or returns the default configuration.
11
5
  *
12
6
  * @function getConfig
13
7
  * @returns The configuration object.
14
8
  */
15
- function getConfig() {
16
- const config = node_fs_1.default.existsSync('sizuku-zod.json')
17
- ? { ...config_1.DEFAULT_CONFIG, ...JSON.parse(node_fs_1.default.readFileSync('sizuku-zod.json', 'utf-8')) }
18
- : config_1.DEFAULT_CONFIG;
9
+ export function getConfig() {
10
+ const config = fs.existsSync('sizuku-zod.json')
11
+ ? { ...DEFAULT_CONFIG, ...JSON.parse(fs.readFileSync('sizuku-zod.json', 'utf-8')) }
12
+ : DEFAULT_CONFIG;
19
13
  return config;
20
14
  }
@@ -1,7 +1,6 @@
1
- import type { Schema } from '../../../common/type';
1
+ import type { Schema } from '../../../shared/types.js';
2
2
  /**
3
3
  * Extract schemas from lines of code
4
- * @function extractSchemas
5
4
  * @param lines - Lines of code
6
5
  * @returns Schemas
7
6
  */
@@ -1,96 +1,243 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractSchemas = extractSchemas;
1
+ import { Node, Project } from 'ts-morph';
4
2
  /**
5
- * Check if line contains metadata
3
+ * Check if comment contains metadata
6
4
  */
7
- const isMetadataComment = (line) => {
8
- return line.includes('@z.') || line.includes('@v.') || line.includes('@relation.');
5
+ const isMetadataComment = (text) => {
6
+ return text.includes('@z.') || text.includes('@v.') || text.includes('@relation.');
9
7
  };
10
8
  /**
11
- * Check if line is a non-comment line
9
+ * Extract field comments that appear before a specific line position
12
10
  */
13
- const isNonCommentLine = (line) => {
14
- const trimmed = line.trim();
15
- return trimmed !== '' && !trimmed.startsWith('///');
11
+ const extractFieldComments = (sourceText, fieldStartPos) => {
12
+ const beforeField = sourceText.substring(0, fieldStartPos);
13
+ const lines = beforeField.split('\n');
14
+ const reverseIndex = lines
15
+ .map((line, index) => ({ line: line.trim(), index }))
16
+ .reverse()
17
+ .reduce((acc, { line }) => {
18
+ if (acc.shouldStop)
19
+ return acc;
20
+ if (line.startsWith('///')) {
21
+ return {
22
+ commentLines: [line, ...acc.commentLines],
23
+ shouldStop: false,
24
+ };
25
+ }
26
+ if (line === '') {
27
+ return acc;
28
+ }
29
+ return { commentLines: acc.commentLines, shouldStop: true };
30
+ }, { commentLines: [], shouldStop: false });
31
+ return reverseIndex.commentLines;
16
32
  };
17
33
  /**
18
- * Extract schemas from lines of code
19
- * @function extractSchemas
20
- * @param lines - Lines of code
21
- * @returns Schemas
34
+ * Parse comment lines and extract Zod definition and description
22
35
  */
23
- function extractSchemas(lines) {
24
- const process = (i, acc) => {
25
- if (i >= lines.length) {
26
- return acc;
36
+ const parseFieldComments = (commentLines) => {
37
+ const cleanLines = commentLines
38
+ .map((line) => line.replace(/^\/\/\/\s*/, '').trim())
39
+ .filter((line) => line.length > 0);
40
+ const zodDefinition = cleanLines.find((line) => line.startsWith('@z.'))?.replace(/^@/, '') ?? '';
41
+ const descriptionLines = cleanLines.filter((line) => !isMetadataComment(line));
42
+ const description = descriptionLines.length > 0 ? descriptionLines.join(' ') : undefined;
43
+ return { zodDefinition, description };
44
+ };
45
+ /**
46
+ * Extract field information from object property
47
+ */
48
+ const extractFieldFromProperty = (property, sourceText) => {
49
+ if (!Node.isPropertyAssignment(property))
50
+ return null;
51
+ const fieldName = property.getName();
52
+ if (!fieldName)
53
+ return null;
54
+ const fieldStartPos = property.getStart();
55
+ const commentLines = extractFieldComments(sourceText, fieldStartPos);
56
+ const { zodDefinition, description } = parseFieldComments(commentLines);
57
+ return {
58
+ name: fieldName,
59
+ definition: zodDefinition,
60
+ description,
61
+ };
62
+ };
63
+ /**
64
+ * Convert table name to Schema name (e.g., 'user' -> 'UserSchema', 'post' -> 'PostSchema')
65
+ */
66
+ const toSchemaName = (tableName) => `${tableName.charAt(0).toUpperCase() + tableName.slice(1)}Schema`;
67
+ /**
68
+ * Extract relation field with type inference
69
+ */
70
+ const extractRelationFieldFromProperty = (property, sourceText) => {
71
+ if (!Node.isPropertyAssignment(property))
72
+ return null;
73
+ const fieldName = property.getName();
74
+ if (!fieldName)
75
+ return null;
76
+ const initializer = property.getInitializer();
77
+ if (!Node.isCallExpression(initializer)) {
78
+ return {
79
+ name: fieldName,
80
+ definition: '',
81
+ description: undefined,
82
+ };
83
+ }
84
+ const expression = initializer.getExpression();
85
+ if (!Node.isIdentifier(expression)) {
86
+ return {
87
+ name: fieldName,
88
+ definition: '',
89
+ description: undefined,
90
+ };
91
+ }
92
+ const functionName = expression.getText();
93
+ const args = initializer.getArguments();
94
+ if (args.length === 0) {
95
+ return {
96
+ name: fieldName,
97
+ definition: '',
98
+ description: undefined,
99
+ };
100
+ }
101
+ const firstArg = args[0];
102
+ if (!Node.isIdentifier(firstArg)) {
103
+ return {
104
+ name: fieldName,
105
+ definition: '',
106
+ description: undefined,
107
+ };
108
+ }
109
+ const referencedTable = firstArg.getText();
110
+ const schemaName = toSchemaName(referencedTable);
111
+ const zodDefinition = functionName === 'many'
112
+ ? `z.array(${schemaName})` // many(post) -> z.array(PostSchema)
113
+ : functionName === 'one'
114
+ ? schemaName // one(user, {...}) -> UserSchema
115
+ : '';
116
+ const fieldStartPos = property.getStart();
117
+ const commentLines = extractFieldComments(sourceText, fieldStartPos);
118
+ const { description } = parseFieldComments(commentLines);
119
+ return {
120
+ name: fieldName,
121
+ definition: zodDefinition,
122
+ description,
123
+ };
124
+ };
125
+ /**
126
+ * Extract object literal from any expression
127
+ */
128
+ const extractObjectLiteralFromExpression = (expression) => {
129
+ // Direct object literal
130
+ if (Node.isObjectLiteralExpression(expression)) {
131
+ return expression;
132
+ }
133
+ if (Node.isParenthesizedExpression(expression)) {
134
+ const inner = expression.getExpression();
135
+ return Node.isObjectLiteralExpression(inner) ? inner : null;
136
+ }
137
+ if (Node.isArrowFunction(expression)) {
138
+ const body = expression.getBody();
139
+ if (Node.isObjectLiteralExpression(body)) {
140
+ return body;
27
141
  }
28
- const line = lines[i];
29
- // extract schema
30
- const schemaMatch = line.match(/export const (\w+)\s*=/);
31
- if (schemaMatch) {
32
- if (acc.currentSchema) {
33
- acc.schemas.push(acc.currentSchema);
34
- }
35
- acc.currentSchema = { name: schemaMatch[1], fields: [] };
36
- acc.pendingDescription = undefined;
37
- return process(i + 1, acc);
142
+ if (Node.isParenthesizedExpression(body)) {
143
+ const inner = body.getExpression();
144
+ return Node.isObjectLiteralExpression(inner) ? inner : null;
38
145
  }
39
- // process comment
40
- if (line.trim().startsWith('///')) {
41
- // zod comment
42
- const zodComment = line.match(/\/\/\/\s*(@z\.(?:[^()]+|\([^)]*\))+)/);
43
- if (zodComment && acc.currentSchema) {
44
- // find next field definition line
45
- const remainingCandidates = lines.slice(i + 1);
46
- const foundRelative = remainingCandidates.findIndex(isNonCommentLine);
47
- if (foundRelative !== -1) {
48
- const j = i + 1 + foundRelative;
49
- const candidate = lines[j].trim();
50
- const fieldMatch = candidate.match(/^(\w+)\s*:/);
51
- if (fieldMatch) {
52
- const newField = {
53
- name: fieldMatch[1],
54
- definition: zodComment[1].replace('@', ''),
55
- description: acc.pendingDescription,
56
- };
57
- acc.currentSchema.fields.push(newField);
58
- acc.pendingDescription = undefined;
59
- return process(i + 1, acc);
60
- }
61
- }
146
+ if (Node.isBlock(body)) {
147
+ const returnStatement = body.getStatements().find((stmt) => Node.isReturnStatement(stmt));
148
+ if (returnStatement && Node.isReturnStatement(returnStatement)) {
149
+ const returnExpression = returnStatement.getExpression();
150
+ return returnExpression && Node.isObjectLiteralExpression(returnExpression)
151
+ ? returnExpression
152
+ : null;
62
153
  }
63
- else {
64
- // comments other than metadata are pending
65
- if (!isMetadataComment(line)) {
66
- const commentText = line.replace('///', '').trim();
67
- acc.pendingDescription = acc.pendingDescription
68
- ? `${acc.pendingDescription} ${commentText}`
69
- : commentText;
70
- return process(i + 1, acc);
71
- }
72
- }
73
- return process(i + 1, acc);
74
154
  }
75
- // if there is a field definition other than comment, use the pending comment as field information
76
- if (acc.currentSchema && acc.pendingDescription) {
77
- const fieldMatch = line.match(/^(\w+)\s*:/);
78
- if (fieldMatch) {
79
- const newField = {
80
- name: fieldMatch[1],
81
- definition: '',
82
- description: acc.pendingDescription,
83
- };
84
- acc.currentSchema.fields.push(newField);
85
- acc.pendingDescription = undefined;
86
- return process(i + 1, acc);
87
- }
155
+ }
156
+ return null;
157
+ };
158
+ /**
159
+ * Find object literal in call expression arguments
160
+ */
161
+ const findObjectLiteralInArgs = (callExpr) => {
162
+ const args = callExpr.getArguments();
163
+ for (const arg of args) {
164
+ const objectLiteral = extractObjectLiteralFromExpression(arg);
165
+ if (objectLiteral) {
166
+ return objectLiteral;
88
167
  }
89
- return process(i + 1, acc);
90
- };
91
- const finalAcc = process(0, { currentSchema: null, pendingDescription: undefined, schemas: [] });
92
- if (finalAcc.currentSchema) {
93
- finalAcc.schemas.push(finalAcc.currentSchema);
94
168
  }
95
- return finalAcc.schemas;
169
+ return null;
170
+ };
171
+ /**
172
+ * Determine if this is a relation-like function call
173
+ */
174
+ const isRelationFunction = (callExpr) => {
175
+ const expression = callExpr.getExpression();
176
+ if (!Node.isIdentifier(expression))
177
+ return false;
178
+ const functionName = expression.getText();
179
+ return functionName === 'relations' || functionName.includes('relation');
180
+ };
181
+ /**
182
+ * Extract fields from any call expression
183
+ */
184
+ const extractFieldsFromCallExpression = (callExpr, sourceText) => {
185
+ const objectLiteral = findObjectLiteralInArgs(callExpr);
186
+ if (!objectLiteral)
187
+ return [];
188
+ const isRelation = isRelationFunction(callExpr);
189
+ return objectLiteral
190
+ .getProperties()
191
+ .map((prop) => isRelation
192
+ ? extractRelationFieldFromProperty(prop, sourceText)
193
+ : extractFieldFromProperty(prop, sourceText))
194
+ .filter((field) => field !== null);
195
+ };
196
+ /**
197
+ * Extract a single schema (variable declaration)
198
+ */
199
+ const extractSchemaFromDeclaration = (declaration, sourceText) => {
200
+ if (!Node.isVariableDeclaration(declaration))
201
+ return null;
202
+ const name = declaration.getName();
203
+ if (!name)
204
+ return null;
205
+ const initializer = declaration.getInitializer();
206
+ if (Node.isCallExpression(initializer)) {
207
+ if (isRelationFunction(initializer))
208
+ return null;
209
+ const fields = extractFieldsFromCallExpression(initializer, sourceText);
210
+ return { name, fields };
211
+ }
212
+ if (Node.isObjectLiteralExpression(initializer)) {
213
+ const fields = initializer
214
+ .getProperties()
215
+ .map((prop) => extractFieldFromProperty(prop, sourceText))
216
+ .filter((field) => field !== null);
217
+ return { name, fields };
218
+ }
219
+ return { name, fields: [] };
220
+ };
221
+ /**
222
+ * Extract schemas from lines of code
223
+ * @param lines - Lines of code
224
+ * @returns Schemas
225
+ */
226
+ export function extractSchemas(lines) {
227
+ const sourceCode = lines.join('\n');
228
+ const project = new Project({
229
+ useInMemoryFileSystem: true,
230
+ compilerOptions: {
231
+ allowJs: true,
232
+ skipLibCheck: true,
233
+ },
234
+ });
235
+ const sourceFile = project.createSourceFile('temp.ts', sourceCode);
236
+ const sourceText = sourceFile.getFullText();
237
+ return sourceFile
238
+ .getVariableStatements()
239
+ .filter((stmt) => stmt.hasExportKeyword())
240
+ .flatMap((stmt) => stmt.getDeclarations())
241
+ .map((decl) => extractSchemaFromDeclaration(decl, sourceText))
242
+ .filter((schema) => schema !== null);
96
243
  }
@@ -0,0 +1,5 @@
1
+ import type { TableInfo, ColumnInfo } from '../../shared/utils/types.js';
2
+ export declare const generateZodSchema: (table: TableInfo) => string;
3
+ export declare const generateZodProperty: (column: ColumnInfo) => string;
4
+ export declare const generateDefaultZodSchema: (column: ColumnInfo) => string;
5
+ export declare const generateZodFile: (tables: TableInfo[]) => string;
@@ -0,0 +1,39 @@
1
+ // 完全純粋なZodスキーマ生成ユーティリティ - 外部import禁止
2
+ import { toPascalCase } from '../../shared/utils/string-utils.js';
3
+ export const generateZodSchema = (table) => {
4
+ const schemaName = `${toPascalCase(table.name)}Schema`;
5
+ const typeName = toPascalCase(table.name);
6
+ const properties = table.columns.map(column => generateZodProperty(column)).join('\n ');
7
+ return `export const ${schemaName} = z.object({
8
+ ${properties}
9
+ })
10
+ export type ${typeName} = z.infer<typeof ${schemaName}>`;
11
+ };
12
+ export const generateZodProperty = (column) => {
13
+ const comment = column.comment ? `/** ${column.comment} */\n ` : '';
14
+ const schema = column.zodSchema || generateDefaultZodSchema(column);
15
+ return `${comment}${column.name}: ${schema},`;
16
+ };
17
+ export const generateDefaultZodSchema = (column) => {
18
+ if (column.type === 'varchar') {
19
+ if (column.length === 36) {
20
+ return 'z.uuid()';
21
+ }
22
+ if (column.length) {
23
+ return `z.string().max(${column.length})`;
24
+ }
25
+ return 'z.string()';
26
+ }
27
+ if (column.type === 'int') {
28
+ return 'z.number().int()';
29
+ }
30
+ if (column.type === 'text') {
31
+ return 'z.string()';
32
+ }
33
+ return 'z.unknown()';
34
+ };
35
+ export const generateZodFile = (tables) => {
36
+ const imports = 'import * as z from \'zod\'\n\n';
37
+ const schemas = tables.map(table => generateZodSchema(table)).join('\n\n');
38
+ return imports + schemas;
39
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param name
3
+ * @returns
4
+ */
5
+ export declare function infer(name: string): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @param name
3
+ * @returns
4
+ */
5
+ export function infer(name) {
6
+ const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
7
+ return `export type ${capitalizedName} = z.infer<typeof ${capitalizedName}Schema>`;
8
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Generates Zod relation schema code from a relation schema AST extraction.
3
+ */
4
+ export declare function relationZodCode(schema: {
5
+ name: string;
6
+ baseName: string;
7
+ fields: {
8
+ name: string;
9
+ definition: string;
10
+ description?: string;
11
+ }[];
12
+ objectType?: 'strict' | 'loose';
13
+ }, withType: boolean): string;
@@ -0,0 +1,19 @@
1
+ import { capitalize, infer } from '../../../utils/index.js';
2
+ /**
3
+ * Generates Zod relation schema code from a relation schema AST extraction.
4
+ */
5
+ export function relationZodCode(schema, withType) {
6
+ const base = schema.baseName;
7
+ const relName = `${schema.name}Schema`;
8
+ const baseSchema = `${capitalize(base)}Schema`;
9
+ const fields = schema.fields.map((f) => `${f.name}:${f.definition}`).join(',');
10
+ const objectType = schema.objectType === 'strict'
11
+ ? 'strictObject'
12
+ : schema.objectType === 'loose'
13
+ ? 'looseObject'
14
+ : 'object';
15
+ const obj = `\nexport const ${capitalize(relName)} = z.${objectType}({...${baseSchema}.shape,${fields}})`;
16
+ if (withType)
17
+ return `${obj}\n\n${infer(schema.name)}\n`;
18
+ return `${obj}`;
19
+ }