supatool 0.1.23 → 0.3.1

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.
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resetApprovalState = resetApprovalState;
37
+ exports.backupOrphanedFiles = backupOrphanedFiles;
38
+ exports.writeSchemaToFile = writeSchemaToFile;
39
+ exports.moveToBackup = moveToBackup;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const utils_1 = require("./utils");
43
+ // グローバルな「全て承認」状態を管理
44
+ let globalApproveAll = false;
45
+ /**
46
+ * 全て承認モードをリセット
47
+ */
48
+ function resetApprovalState() {
49
+ globalApproveAll = false;
50
+ }
51
+ /**
52
+ * 既存ファイルをバックアップディレクトリに移動
53
+ */
54
+ async function backupExistingFile(filePath, schemaDir, force = false) {
55
+ if (!fs.existsSync(filePath)) {
56
+ return true;
57
+ }
58
+ if (!force && !globalApproveAll) {
59
+ const fileName = path.basename(filePath);
60
+ const response = await (0, utils_1.askUserConfirmation)(`↓ 既存ファイル ${fileName} を上書きしますか?`, {
61
+ allowAll: true,
62
+ message: '(y/N/a[all]): '
63
+ });
64
+ if (response === 'all') {
65
+ globalApproveAll = true;
66
+ console.log('✅ すべてのファイルを承認します');
67
+ }
68
+ else if (response === false) {
69
+ console.log('スキップしました');
70
+ return false;
71
+ }
72
+ }
73
+ const backupDir = path.join(schemaDir, 'backup');
74
+ if (!fs.existsSync(backupDir)) {
75
+ fs.mkdirSync(backupDir, { recursive: true });
76
+ }
77
+ const fileName = path.basename(filePath);
78
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
79
+ const backupFileName = `${timestamp}_${fileName}`;
80
+ const backupPath = path.join(backupDir, backupFileName);
81
+ fs.renameSync(filePath, backupPath);
82
+ console.log(`既存ファイルをバックアップしました: ${backupPath}`);
83
+ return true;
84
+ }
85
+ /**
86
+ * 存在しないテーブルのファイルをバックアップに移動
87
+ */
88
+ async function backupOrphanedFiles(schemaDir, existingTables, force = false) {
89
+ if (!fs.existsSync(schemaDir)) {
90
+ return;
91
+ }
92
+ const files = fs.readdirSync(schemaDir);
93
+ const orphanedFiles = [];
94
+ for (const file of files) {
95
+ if (!file.endsWith('.sql'))
96
+ continue;
97
+ const tableName = path.basename(file, '.sql');
98
+ if (!existingTables.has(tableName)) {
99
+ orphanedFiles.push(file);
100
+ }
101
+ }
102
+ if (orphanedFiles.length === 0) {
103
+ return;
104
+ }
105
+ if (!force) {
106
+ console.log('\n以下のファイルは存在しないテーブルに対応しています:');
107
+ orphanedFiles.forEach(file => console.log(` - ${file}`));
108
+ const confirmed = await (0, utils_1.askUserConfirmation)('これらのファイルをバックアップフォルダに移動しますか?');
109
+ if (!confirmed) {
110
+ console.log('孤児ファイルの移動をスキップしました');
111
+ return;
112
+ }
113
+ }
114
+ for (const file of orphanedFiles) {
115
+ const tableName = path.basename(file, '.sql');
116
+ const filePath = path.join(schemaDir, file);
117
+ console.log(`[${tableName}] 存在しないテーブルのファイルをバックアップ`);
118
+ await backupExistingFile(filePath, schemaDir, true); // 確認済みなのでforce=true
119
+ }
120
+ }
121
+ /**
122
+ * スキーマをファイルに書き込み
123
+ */
124
+ async function writeSchemaToFile(ddl, schemaDir, timestamp, fileName, tableName, force = false) {
125
+ if (!fs.existsSync(schemaDir)) {
126
+ fs.mkdirSync(schemaDir, { recursive: true });
127
+ }
128
+ const filePath = path.join(schemaDir, fileName);
129
+ // 既存ファイルがある場合はバックアップ
130
+ const canProceed = await backupExistingFile(filePath, schemaDir, force);
131
+ if (!canProceed) {
132
+ return false;
133
+ }
134
+ // リモートデータベースの最終更新時刻を記録(比較用メタデータ - 編集禁止)
135
+ const remoteTimestamp = `-- Remote last updated: ${new Date(timestamp * 1000).toISOString()}\n`;
136
+ // 同期実行時刻(参考情報)
137
+ const syncTimestamp = `-- Synced by supatool at: ${new Date().toISOString()}\n`;
138
+ // 警告コメント
139
+ const warningComment = `-- ⚠️ このファイルはsupatoolによって自動生成されます。手動編集は同期時に失われる可能性があります。\n`;
140
+ const tableComment = `-- Table: ${tableName}\n\n`;
141
+ const finalContent = remoteTimestamp + syncTimestamp + warningComment + tableComment + ddl;
142
+ fs.writeFileSync(filePath, finalContent, 'utf-8');
143
+ console.log(`📁 ${tableName}.sql に保存しました`);
144
+ return true;
145
+ }
146
+ /**
147
+ * 孤立したファイルをバックアップフォルダに移動
148
+ */
149
+ function moveToBackup(schemaDir, fileName) {
150
+ const backupDir = path.join(schemaDir, 'backup');
151
+ if (!fs.existsSync(backupDir)) {
152
+ fs.mkdirSync(backupDir, { recursive: true });
153
+ }
154
+ const sourceFile = path.join(schemaDir, fileName);
155
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
156
+ const backupFile = path.join(backupDir, `${path.basename(fileName, '.sql')}_${timestamp}.sql`);
157
+ if (fs.existsSync(sourceFile)) {
158
+ fs.renameSync(sourceFile, backupFile);
159
+ console.log(`📦 ${fileName} を ${backupFile} にバックアップしました`);
160
+ }
161
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "supatool",
3
- "version": "0.1.23",
4
- "description": "A CLI tool that automatically generates TypeScript CRUD code from Supabase type definitions.",
3
+ "version": "0.3.1",
4
+ "description": "A CLI tool for Supabase schema extraction and TypeScript CRUD generation with declarative database schema support.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsc",
12
+ "postbuild": "npm link",
12
13
  "start": "tsx bin/supatool.ts"
13
14
  },
14
15
  "files": [
@@ -27,11 +28,25 @@
27
28
  "author": "IdeaGarage",
28
29
  "license": "MIT",
29
30
  "dependencies": {
31
+ "@supabase/supabase-js": "^2.49.4",
30
32
  "commander": "^13.1.0",
33
+ "diff": "^5.2.0",
34
+ "dotenv": "^16.5.0",
35
+ "js-yaml": "^4.1.0",
36
+ "minimist": "^1.2.8",
37
+ "ora": "^5.4.1",
38
+ "pg": "^8.11.3",
39
+ "pg-structure": "^7.2.0",
31
40
  "tsx": "^4.7.0",
32
41
  "typescript": "^5.0.0"
33
42
  },
34
43
  "devDependencies": {
35
- "@types/node": "^20.17.30"
44
+ "@types/diff": "^7.0.2",
45
+ "@types/js-yaml": "^4.0.9",
46
+ "@types/node": "^20.17.30",
47
+ "@types/pg": "^8.11.0"
48
+ },
49
+ "exports": {
50
+ "./schemas/supatool-data.schema": "./schemas/supatool-data.schema.ts"
36
51
  }
37
52
  }