supatool 0.3.7 → 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.
@@ -1,8 +1,38 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
6
36
  Object.defineProperty(exports, "__esModule", { value: true });
7
37
  // CLI entry point
8
38
  // Subcommand support with commander
@@ -19,8 +49,8 @@ const rlsGenerator_1 = require("../generator/rlsGenerator");
19
49
  const sync_1 = require("../sync");
20
50
  const definitionExtractor_1 = require("../sync/definitionExtractor");
21
51
  const seedGenerator_1 = require("../sync/seedGenerator");
22
- const fs_1 = __importDefault(require("fs"));
23
- const path_1 = __importDefault(require("path"));
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
24
54
  const program = new commander_1.Command();
25
55
  program
26
56
  .name('supatool')
@@ -53,8 +83,8 @@ program
53
83
  process.exit(1);
54
84
  }
55
85
  try {
56
- // --schema オプションの処理
57
- let schemas = ['public']; // デフォルト
86
+ // Handle --schema option
87
+ let schemas = ['public']; // default
58
88
  if (options.schema) {
59
89
  schemas = options.schema.split(',').map((s) => s.trim());
60
90
  }
@@ -67,7 +97,8 @@ program
67
97
  all: options.all,
68
98
  tablePattern: options.tables,
69
99
  force: options.force,
70
- schemas: schemas
100
+ schemas: schemas,
101
+ version: package_json_1.version
71
102
  });
72
103
  }
73
104
  catch (error) {
@@ -75,135 +106,142 @@ program
75
106
  process.exit(1);
76
107
  }
77
108
  });
78
- // config:init サブコマンド
109
+ // config:init subcommand
79
110
  program
80
111
  .command('config:init')
81
- .description('設定ファイル雛形を生成')
82
- .option('-o, --out <path>', '出力先パス', 'supatool.config.json')
112
+ .description('Generate config file template')
113
+ .option('-o, --out <path>', 'Output path', 'supatool.config.json')
83
114
  .action((options) => {
84
115
  (0, sync_1.createConfigTemplate)(options.out);
85
116
  });
86
- // gen:types サブコマンド
117
+ // gen:types subcommand
87
118
  program
88
119
  .command('gen:types <modelPath>')
89
- .description('モデルYAMLからTypeScript型定義を生成')
90
- .option('-o, --out <path>', '出力先パス', 'docs/generated/types.ts')
120
+ .description('Generate TypeScript types from model YAML')
121
+ .option('-o, --out <path>', 'Output path', 'docs/generated/types.ts')
91
122
  .action((modelPath, options) => {
92
123
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
93
124
  (0, typeGenerator_1.generateTypesFromModel)(model, options.out);
94
- console.log('TypeScript型定義を出力:', options.out);
125
+ console.log('TypeScript types output:', options.out);
95
126
  });
96
- // gen:crud サブコマンド
127
+ // gen:crud subcommand
97
128
  program
98
129
  .command('gen:crud <modelPath>')
99
- .description('Generate CRUD TypeScript code from model YAML')
100
- .option('-o, --out <dir>', '出力先ディレクトリ', 'docs/generated/crud')
130
+ .description('Generate CRUD TypeScript code from model YAML [deprecated - prefer writing code with LLM]')
131
+ .option('-o, --out <dir>', 'Output directory', 'docs/generated/crud')
101
132
  .action((modelPath, options) => {
133
+ console.warn('⚠️ gen:crud is deprecated. With LLM development, writing code as needed is often more efficient.');
102
134
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
103
135
  (0, crudGenerator_1.generateCrudFromModel)(model, options.out);
104
136
  console.log('Generated CRUD TypeScript code:', options.out);
105
137
  });
106
- // gen:docs サブコマンド
138
+ // gen:docs subcommand
107
139
  program
108
140
  .command('gen:docs <modelPath>')
109
- .description('モデルYAMLからドキュメント(Markdown)を生成')
110
- .option('-o, --out <path>', 'テーブル定義書出力先', 'docs/generated/table-doc.md')
141
+ .description('Generate documentation (Markdown) from model YAML')
142
+ .option('-o, --out <path>', 'Table doc output path', 'docs/generated/table-doc.md')
111
143
  .action((modelPath, options) => {
112
144
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
113
145
  (0, docGenerator_1.generateTableDocMarkdown)(model, options.out);
114
146
  (0, docGenerator_1.generateRelationsMarkdown)(model, 'docs/generated/relations.md');
115
- console.log('テーブル定義書を出力:', options.out);
116
- console.log('リレーション一覧を出力: docs/generated/relations.md');
147
+ console.log('Table doc output:', options.out);
148
+ console.log('Relations list output: docs/generated/relations.md');
117
149
  });
118
- // gen:sql サブコマンド
150
+ // gen:sql subcommand
119
151
  program
120
152
  .command('gen:sql <modelPath>')
121
- .description('モデルYAMLからテーブル・リレーション・RLS/セキュリティSQLを一括生成')
122
- .option('-o, --out <path>', '出力先パス', 'docs/generated/schema.sql')
153
+ .description('Generate table, relation, RLS/security SQL from model YAML')
154
+ .option('-o, --out <path>', 'Output path', 'docs/generated/schema.sql')
123
155
  .action((modelPath, options) => {
124
156
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
125
- // 一時ファイルに個別出力
157
+ // Write to temp files first
126
158
  const tmpSchema = 'docs/generated/.tmp_schema.sql';
127
159
  const tmpRls = 'docs/generated/.tmp_rls.sql';
128
160
  (0, sqlGenerator_1.generateSqlFromModel)(model, tmpSchema);
129
161
  (0, rlsGenerator_1.generateRlsSqlFromModel)(model, tmpRls);
130
- // 結合して1ファイルにまとめる
131
- const schema = fs_1.default.readFileSync(tmpSchema, 'utf-8');
132
- const rls = fs_1.default.readFileSync(tmpRls, 'utf-8');
133
- fs_1.default.writeFileSync(options.out, schema + '\n' + rls);
134
- fs_1.default.unlinkSync(tmpSchema);
135
- fs_1.default.unlinkSync(tmpRls);
136
- console.log('テーブル・リレーション・RLS/セキュリティSQLを一括出力:', options.out);
162
+ // Merge into single file
163
+ const schema = fs.readFileSync(tmpSchema, 'utf-8');
164
+ const rls = fs.readFileSync(tmpRls, 'utf-8');
165
+ fs.writeFileSync(options.out, schema + '\n' + rls);
166
+ fs.unlinkSync(tmpSchema);
167
+ fs.unlinkSync(tmpRls);
168
+ console.log('Table, relation, RLS/security SQL output:', options.out);
137
169
  });
138
- // gen:rls サブコマンド
170
+ // gen:rls subcommand
139
171
  program
140
172
  .command('gen:rls <modelPath>')
141
- .description('モデルYAMLからRLS/セキュリティポリシーSQLを生成')
142
- .option('-o, --out <path>', '出力先パス', 'docs/generated/rls.sql')
173
+ .description('Generate RLS/security policy SQL from model YAML')
174
+ .option('-o, --out <path>', 'Output path', 'docs/generated/rls.sql')
143
175
  .action((modelPath, options) => {
144
176
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
145
177
  (0, rlsGenerator_1.generateRlsSqlFromModel)(model, options.out);
146
- console.log('RLS/セキュリティポリシーSQLを出力:', options.out);
178
+ console.log('RLS/security policy SQL output:', options.out);
147
179
  });
148
- // gen:all サブコマンド
180
+ // gen:all subcommand
149
181
  program
150
182
  .command('gen:all <modelPath>')
151
- .description('モデルYAMLから全て一括生成')
183
+ .description('Generate all from model YAML')
152
184
  .action((modelPath) => {
153
185
  const model = (0, modelParser_1.parseModelYaml)(modelPath);
154
186
  (0, typeGenerator_1.generateTypesFromModel)(model, 'docs/generated/types.ts');
155
187
  (0, crudGenerator_1.generateCrudFromModel)(model, 'docs/generated/crud');
156
188
  (0, docGenerator_1.generateTableDocMarkdown)(model, 'docs/generated/table-doc.md');
157
189
  (0, docGenerator_1.generateRelationsMarkdown)(model, 'docs/generated/relations.md');
158
- console.log('TypeScript型定義を出力: docs/generated/types.ts');
159
- console.log('CRUD関数TypeScriptコードを出力: docs/generated/crud/');
160
- console.log('テーブル定義書を出力: docs/generated/table-doc.md');
161
- console.log('リレーション一覧を出力: docs/generated/relations.md');
190
+ console.log('TypeScript types output: docs/generated/types.ts');
191
+ console.log('CRUD code output: docs/generated/crud/');
192
+ console.log('Table doc output: docs/generated/table-doc.md');
193
+ console.log('Relations list output: docs/generated/relations.md');
162
194
  });
163
- // create サブコマンド
195
+ // create subcommand
164
196
  program
165
197
  .command('create <template>')
166
- .description('テンプレートYAML雛形を生成')
167
- .option('-o, --out <path>', '出力先パス', 'docs/model-schema-example.yaml')
198
+ .description('Generate template YAML')
199
+ .option('-o, --out <path>', 'Output path', 'docs/model-schema-example.yaml')
168
200
  .action((template, options) => {
169
- const srcPath = path_1.default.join(__dirname, '../templates/yaml', `${template}.yaml`);
201
+ const srcPath = path.join(__dirname, '../templates/yaml', `${template}.yaml`);
170
202
  const destPath = options.out;
171
- if (!fs_1.default.existsSync(srcPath)) {
172
- console.error(`テンプレートが見つかりません: ${srcPath}`);
203
+ if (!fs.existsSync(srcPath)) {
204
+ console.error(`Template not found: ${srcPath}`);
173
205
  process.exit(1);
174
206
  }
175
- fs_1.default.copyFileSync(srcPath, destPath);
176
- console.log(`テンプレート雛形を生成: ${destPath}`);
207
+ fs.copyFileSync(srcPath, destPath);
208
+ console.log(`Template generated: ${destPath}`);
177
209
  });
178
- // crud コマンド(Supabase型定義→CRUD生成)
210
+ // crud command (Supabase types -> CRUD generation)
179
211
  program
180
212
  .command('crud')
181
- .description('Supabase型定義(TypeScript)からCRUD関数TypeScriptコードを生成')
182
- .option('-i, --input <path>', '型定義の入力パス', 'shared/')
183
- .option('-o, --output <path>', 'CRUDコード出力先', 'src/integrations/supabase/')
184
- .option('-t, --tables <names>', '生成対象テーブル(カンマ区切り)')
185
- .option('-f, --force', '出力先を強制上書き')
213
+ .description('Generate CRUD from Supabase type definitions [deprecated - prefer writing code with LLM]')
214
+ .option('-i, --input <path>', 'Type definition input path', 'shared/')
215
+ .option('-o, --output <path>', 'CRUD code output path', 'src/integrations/supabase/')
216
+ .option('-t, --tables <names>', 'Target tables (comma-separated)')
217
+ .option('-f, --force', 'Force overwrite output')
186
218
  .action((options) => {
187
- // コマンドライン引数をmain()に渡すため、process.argvをそのまま利用
219
+ console.warn('⚠️ crud is deprecated. With LLM development, writing code as needed is often more efficient.');
220
+ // Pass argv to main() for CLI args
188
221
  (0, index_1.main)();
189
222
  });
190
- // helpサブコマンド
223
+ // help subcommand
191
224
  program
192
225
  .command('help')
193
226
  .description('Show help')
194
227
  .action(() => {
195
228
  console.log(helptext_1.helpText);
196
229
  });
197
- // sync コマンド
230
+ // sync command (deprecated)
198
231
  program
199
232
  .command('sync')
200
- .description('ローカルスキーマとリモートスキーマを同期')
233
+ .description('Synchronize local and remote schemas [deprecated]')
201
234
  .option('-c, --connection <string>', 'Supabase connection string')
202
- .option('-s, --schema-dir <path>', 'ローカルスキーマディレクトリ', './supabase/schemas')
203
- .option('-t, --tables <pattern>', 'テーブルパターン(ワイルドカード対応)', '*')
204
- .option('-f, --force', '強制上書き(確認なし)')
205
- .option('--config <path>', '設定ファイルパス')
235
+ .option('-s, --schema-dir <path>', 'Local schema directory', './supabase/schemas')
236
+ .option('-t, --tables <pattern>', 'Table pattern (wildcards supported)', '*')
237
+ .option('-f, --force', 'Force overwrite (no confirmation)')
238
+ .option('--config <path>', 'Configuration file path')
206
239
  .action(async (options) => {
240
+ console.warn('⚠️ WARNING: sync command is deprecated.');
241
+ console.warn(' Please use `supatool deploy` command instead.');
242
+ console.warn(' Example: supatool deploy --table users --dry-run');
243
+ console.warn(' Example: supatool deploy --table all --dry-run # all tables');
244
+ console.warn('');
207
245
  const config = (0, sync_1.resolveConfig)({
208
246
  connectionString: options.connection
209
247
  }, options.config);
@@ -228,16 +266,86 @@ program
228
266
  process.exit(1);
229
267
  }
230
268
  });
231
- // seed コマンド
269
+ // deploy command (recommended)
270
+ program
271
+ .command('deploy')
272
+ .description('Deploy local schema to remote (diff detection, migration generation, confirm before apply)')
273
+ .option('-c, --connection <string>', 'Supabase connection string')
274
+ .option('-s, --schema-dir <path>', 'Local schema directory', './supabase/schemas')
275
+ .option('-t, --table <name>', 'Target table name (specify "all" for all tables)')
276
+ .option('--auto-apply', 'Auto-apply to remote (no confirmation)')
277
+ .option('--dry-run', 'Preview changes only (recommended)')
278
+ .option('--generate-only', 'Generate migration files only (no apply)')
279
+ .option('--config <path>', 'Configuration file path')
280
+ .action(async (options) => {
281
+ const config = (0, sync_1.resolveConfig)({
282
+ connectionString: options.connection
283
+ }, options.config);
284
+ if (!config.connectionString) {
285
+ console.error('Connection string is required. Set it using one of:');
286
+ console.error('1. --connection option');
287
+ console.error('2. SUPABASE_CONNECTION_STRING environment variable');
288
+ console.error('3. DATABASE_URL environment variable');
289
+ console.error('4. supatool.config.json configuration file');
290
+ process.exit(1);
291
+ }
292
+ // Validate table specification
293
+ if (!options.table) {
294
+ console.error('❌ Table name is required. Use --table <table-name>');
295
+ console.error(' Example: supatool deploy --table users --dry-run');
296
+ console.error(' Example: supatool deploy --table all --dry-run # all tables');
297
+ process.exit(1);
298
+ }
299
+ const tablePattern = options.table === 'all' ? '*' : options.table;
300
+ // Option processing
301
+ const isDryRun = options.dryRun || false;
302
+ const isAutoApply = options.autoApply || false;
303
+ const isGenerateOnly = options.generateOnly || false;
304
+ // Conflict check
305
+ const activeOptions = [isDryRun, isAutoApply, isGenerateOnly].filter(Boolean).length;
306
+ if (activeOptions > 1) {
307
+ console.error('❌ --dry-run, --auto-apply, --generate-only cannot be specified simultaneously');
308
+ process.exit(1);
309
+ }
310
+ if (isDryRun) {
311
+ console.log('🔍 Preview mode: showing changes');
312
+ }
313
+ else if (isAutoApply) {
314
+ console.log('⚡ Auto-apply mode: executing without confirmation');
315
+ }
316
+ else if (isGenerateOnly) {
317
+ console.log('📝 Migration generation mode: file generation only');
318
+ }
319
+ else {
320
+ console.log('✅ Confirmation mode: generating migration then confirming before execution');
321
+ }
322
+ try {
323
+ console.log(`Target tables: ${tablePattern}`);
324
+ await (0, sync_1.syncAllTables)({
325
+ connectionString: config.connectionString,
326
+ schemaDir: options.schemaDir,
327
+ tablePattern: tablePattern,
328
+ force: isAutoApply,
329
+ dryRun: isDryRun,
330
+ generateOnly: isGenerateOnly,
331
+ requireConfirmation: !isDryRun && !isAutoApply && !isGenerateOnly
332
+ });
333
+ }
334
+ catch (error) {
335
+ console.error('⚠️ Deploy error:', error);
336
+ process.exit(1);
337
+ }
338
+ });
339
+ // seed command
232
340
  program
233
341
  .command('seed')
234
- .description('指定テーブルのデータをリモートDBから取得し、AI用シードJSONを生成')
235
- .option('-c, --connection <string>', 'Supabase接続文字列')
236
- .option('-t, --tables <path>', '取得テーブル一覧YAML', 'tables.yaml')
237
- .option('-o, --out <dir>', '出力ディレクトリ', 'supabase/seeds')
238
- .option('--config <path>', '設定ファイルパス')
342
+ .description('Fetch table data from remote DB and generate AI seed JSON')
343
+ .option('-c, --connection <string>', 'Supabase connection string')
344
+ .option('-t, --tables <path>', 'Tables list YAML', 'tables.yaml')
345
+ .option('-o, --out <dir>', 'Output directory', 'supabase/seeds')
346
+ .option('--config <path>', 'Configuration file path')
239
347
  .action(async (options) => {
240
- // 接続情報の解決
348
+ // Resolve connection
241
349
  const config = (0, sync_1.resolveConfig)({
242
350
  connectionString: options.connection
243
351
  }, options.config);
@@ -257,7 +365,7 @@ program
257
365
  });
258
366
  }
259
367
  catch (error) {
260
- console.error('⚠️ Seed取得エラー:', error);
368
+ console.error('⚠️ Seed fetch error:', error);
261
369
  process.exit(1);
262
370
  }
263
371
  });
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.supabase = void 0;
4
- // Supabaseクライアント定義(自動生成/手動編集可)
5
- // 日本語コメント
4
+ // Supabase client definition (auto-generated / editable)
6
5
  const supabase_js_1 = require("@supabase/supabase-js");
7
6
  const supabaseUrl = process.env.SUPABASE_URL || '';
8
7
  const supabaseKey = process.env.SUPABASE_KEY || '';
@@ -4,14 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateCrudFromModel = generateCrudFromModel;
7
- // CRUD関数TypeScriptコード自動生成(Supabase実動作対応)
8
- // 日本語コメント
7
+ // CRUD TypeScript code auto-generation (Supabase-compatible)
9
8
  const path_1 = __importDefault(require("path"));
10
9
  const fs_1 = __importDefault(require("fs"));
11
10
  /**
12
- * dataSchemaまたはmodels/tablesから各テーブルごとのCRUD関数TypeScriptファイルを生成
13
- * @param model モデルオブジェクト
14
- * @param outDir 出力先ディレクトリ
11
+ * Generate CRUD TypeScript file per table from dataSchema or models/tables
12
+ * @param model Model object
13
+ * @param outDir Output directory
15
14
  */
16
15
  function generateCrudFromModel(model, outDir) {
17
16
  if (!fs_1.default.existsSync(outDir)) {
@@ -35,15 +34,15 @@ function generateCrudFromModel(model, outDir) {
35
34
  continue;
36
35
  const tableName = tableObj.tableName;
37
36
  const capitalizedName = capitalize(tableName);
38
- let code = `// 自動生成: ${tableName}用CRUD関数\n\n`;
37
+ let code = `// Auto-generated: CRUD for ${tableName}\n\n`;
39
38
  code += `import { supabase } from '../client';\n`;
40
39
  code += `import type { ${tableName} } from '../types';\n\n`;
41
- // 型定義
42
- code += `// フィルター型定義\n`;
40
+ // Type definitions
41
+ code += `// Filter type definition\n`;
43
42
  code += `type FilterValue = string | number | boolean | null;\n`;
44
43
  code += `type Filters = Record<string, FilterValue | FilterValue[]>;\n\n`;
45
- // 全件取得関数(改良版)
46
- code += `/** 全件取得 */\n`;
44
+ // Select all (improved)
45
+ code += `/** Select all */\n`;
47
46
  code += `export async function select${capitalizedName}Rows(): Promise<${tableName}[]> {\n`;
48
47
  code += ` try {\n`;
49
48
  code += ` const { data, error } = await supabase.from('${tableName}').select('*');\n`;
@@ -60,8 +59,8 @@ function generateCrudFromModel(model, outDir) {
60
59
  code += ` throw error;\n`;
61
60
  code += ` }\n`;
62
61
  code += `}\n\n`;
63
- // IDで1件取得関数(改良版)
64
- code += `/** IDで1件取得 */\n`;
62
+ // Select by ID (improved)
63
+ code += `/** Select by ID */\n`;
65
64
  code += `export async function select${capitalizedName}RowById({ id }: { id: string }): Promise<${tableName} | null> {\n`;
66
65
  code += ` if (!id) {\n`;
67
66
  code += ` throw new Error('ID is required');\n`;
@@ -69,7 +68,7 @@ function generateCrudFromModel(model, outDir) {
69
68
  code += ` try {\n`;
70
69
  code += ` const { data, error } = await supabase.from('${tableName}').select('*').eq('id', id).single();\n`;
71
70
  code += ` if (error) {\n`;
72
- code += ` // レコードが見つからない場合(PGRST116)は null を返す\n`;
71
+ code += ` // Return null when record not found (PGRST116)\n`;
73
72
  code += ` if (error.code === 'PGRST116') {\n`;
74
73
  code += ` return null;\n`;
75
74
  code += ` }\n`;
@@ -82,15 +81,15 @@ function generateCrudFromModel(model, outDir) {
82
81
  code += ` throw error;\n`;
83
82
  code += ` }\n`;
84
83
  code += `}\n\n`;
85
- // フィルターで検索関数
86
- code += `/** フィルターで複数件取得 */\n`;
84
+ // Select by filters
85
+ code += `/** Select multiple by filters */\n`;
87
86
  code += `export async function select${capitalizedName}RowsWithFilters({ filters }: { filters: Filters }): Promise<${tableName}[]> {\n`;
88
- code += ` // filtersのガード\n`;
87
+ code += ` // Guard for filters\n`;
89
88
  code += ` if (!filters || typeof filters !== 'object') return [];\n`;
90
89
  code += ` try {\n`;
91
90
  code += ` let query = supabase.from('${tableName}').select('*');\n`;
92
91
  code += ` \n`;
93
- code += ` // フィルターを適用\n`;
92
+ code += ` // Apply filters\n`;
94
93
  code += ` for (const [key, value] of Object.entries(filters)) {\n`;
95
94
  code += ` if (Array.isArray(value)) {\n`;
96
95
  code += ` query = query.in(key, value);\n`;
@@ -110,8 +109,8 @@ function generateCrudFromModel(model, outDir) {
110
109
  code += ` throw error;\n`;
111
110
  code += ` }\n`;
112
111
  code += `}\n\n`;
113
- // 作成関数
114
- code += `/** 新規作成 */\n`;
112
+ // Insert
113
+ code += `/** Insert */\n`;
115
114
  code += `export async function insert${capitalizedName}Row({ data }: { data: Omit<${tableName}, 'id' | 'created_at' | 'updated_at'> }): Promise<${tableName}> {\n`;
116
115
  code += ` if (!data) {\n`;
117
116
  code += ` throw new Error('Data is required for creation');\n`;
@@ -135,8 +134,8 @@ function generateCrudFromModel(model, outDir) {
135
134
  code += ` throw error;\n`;
136
135
  code += ` }\n`;
137
136
  code += `}\n\n`;
138
- // 更新関数
139
- code += `/** 更新 */\n`;
137
+ // Update
138
+ code += `/** Update */\n`;
140
139
  code += `export async function update${capitalizedName}Row({ id, data }: { id: string; data: Partial<Omit<${tableName}, 'id' | 'created_at'>> }): Promise<${tableName}> {\n`;
141
140
  code += ` if (!id) {\n`;
142
141
  code += ` throw new Error('ID is required for update');\n`;
@@ -167,8 +166,8 @@ function generateCrudFromModel(model, outDir) {
167
166
  code += ` throw error;\n`;
168
167
  code += ` }\n`;
169
168
  code += `}\n\n`;
170
- // 削除関数
171
- code += `/** 削除 */\n`;
169
+ // Delete
170
+ code += `/** Delete */\n`;
172
171
  code += `export async function delete${capitalizedName}Row({ id }: { id: string }): Promise<boolean> {\n`;
173
172
  code += ` if (!id) {\n`;
174
173
  code += ` throw new Error('ID is required for deletion');\n`;
@@ -5,31 +5,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateTableDocMarkdown = generateTableDocMarkdown;
7
7
  exports.generateRelationsMarkdown = generateRelationsMarkdown;
8
- // ドキュメント生成(最小雛形)
9
- // 日本語コメント
8
+ // Document generation (minimal template)
10
9
  const path_1 = __importDefault(require("path"));
11
10
  const fs_1 = __importDefault(require("fs"));
12
11
  /**
13
- * テーブル定義書(Markdown)を生成して保存
14
- * @param model モデルオブジェクト
15
- * @param outPath 出力先パス
12
+ * Generate and save table definition doc (Markdown)
13
+ * @param model Model object
14
+ * @param outPath Output path
16
15
  */
17
16
  function generateTableDocMarkdown(model, outPath) {
18
- // 出力先ディレクトリを作成
17
+ // Create output directory
19
18
  const dir = path_1.default.dirname(outPath);
20
19
  if (!fs_1.default.existsSync(dir)) {
21
20
  fs_1.default.mkdirSync(dir, { recursive: true });
22
21
  }
23
- let md = '# テーブル定義書\n\n';
22
+ let md = '# Table definition doc\n\n';
24
23
  for (const m of model.models) {
25
24
  const tables = m.tables || {};
26
25
  for (const [tableName, table] of Object.entries(tables)) {
27
26
  const t = table;
28
- let skipNote = t.skipCreate ? '(作成不要: Supabase組み込み)' : '';
27
+ let skipNote = t.skipCreate ? ' (skip: Supabase built-in)' : '';
29
28
  md += `## ${tableName}${skipNote}\n`;
30
29
  if (t.description)
31
30
  md += `${t.description}\n`;
32
- md += '\n| カラム | | 主キー | NotNull | デフォルト | ラベル |\n|---|---|---|---|---|---|\n';
31
+ md += '\n| Column | Type | PK | NotNull | Default | Label |\n|---|---|---|---|---|---|\n';
33
32
  for (const [colName, col] of Object.entries(t.fields || {})) {
34
33
  const c = col;
35
34
  md += `| ${colName} | ${c.type || ''} | ${c.primary ? '★' : ''} | ${c.notNull ? '○' : ''} | ${c.default || ''} | ${c.label || ''} |\n`;
@@ -40,16 +39,16 @@ function generateTableDocMarkdown(model, outPath) {
40
39
  fs_1.default.writeFileSync(outPath, md);
41
40
  }
42
41
  /**
43
- * リレーション一覧(Markdown)を生成して保存
44
- * @param model モデルオブジェクト
45
- * @param outPath 出力先パス
42
+ * Generate and save relations list (Markdown)
43
+ * @param model Model object
44
+ * @param outPath Output path
46
45
  */
47
46
  function generateRelationsMarkdown(model, outPath) {
48
47
  const dir = path_1.default.dirname(outPath);
49
48
  if (!fs_1.default.existsSync(dir)) {
50
49
  fs_1.default.mkdirSync(dir, { recursive: true });
51
50
  }
52
- let md = '# リレーション一覧\n\n| テーブル | 関係 | 対象 | 外部キー |\n|---|---|---|---|\n';
51
+ let md = '# Relations list\n\n| Table | Relation | Target | Foreign key |\n|---|---|---|---|\n';
53
52
  for (const m of model.models) {
54
53
  const tables = m.tables || {};
55
54
  for (const [tableName, table] of Object.entries(tables)) {