@thinkdata/cli 0.1.0 → 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.
@@ -6,14 +6,16 @@
6
6
  * npx @thinkdata/cli extract "postgresql://user@host/db"
7
7
  * npx @thinkdata/cli extract --interactive
8
8
  * npx @thinkdata/cli compare "postgresql://..." --token tk_...
9
+ * npx @thinkdata/cli serve --port 3100
9
10
  */
10
11
  import { Command } from 'commander';
11
12
  import { extractCommand } from '../commands/extract.js';
12
13
  import { compareCommand } from '../commands/compare.js';
14
+ import { serveCommand } from '../commands/serve.js';
13
15
  const program = new Command();
14
16
  program
15
17
  .name('thinkdata')
16
- .description('ThinkERD CLI — Database schema extraction and comparison')
18
+ .description('ThinkERD CLI — Database schema extraction, comparison, and local agent')
17
19
  .version('0.1.0');
18
20
  // ── extract 명령 ──
19
21
  program
@@ -31,7 +33,7 @@ program
31
33
  .option('-o, --output <file>', 'Save to JSON file instead of sending')
32
34
  .option('-i, --interactive', 'Interactive wizard mode')
33
35
  .action(extractCommand);
34
- // ── compare 명령 (스텁) ──
36
+ // ── compare 명령 ──
35
37
  program
36
38
  .command('compare [connection-string]')
37
39
  .description('Compare database schema with ThinkERD model')
@@ -39,5 +41,11 @@ program
39
41
  .option('--project <id>', 'ThinkERD project ID')
40
42
  .option('-f, --file <file>', 'Model JSON file to compare against')
41
43
  .action(compareCommand);
44
+ // ── serve 명령 (Agent 모드) ──
45
+ program
46
+ .command('serve')
47
+ .description('Start local HTTP agent for ThinkERD browser integration (localhost only)')
48
+ .option('-p, --port <port>', 'Port number (default: 3100)', parseInt)
49
+ .action(serveCommand);
42
50
  program.parse();
43
51
  //# sourceMappingURL=thinkdata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thinkdata.js","sourceRoot":"","sources":["../../src/bin/thinkdata.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,0DAA0D,CAAC;KACvE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,mBAAmB;AACnB,OAAO;KACF,OAAO,CAAC,6BAA6B,CAAC;KACtC,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,CAAC;KAC1D,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,mBAAmB,EAAE,eAAe,EAAE,QAAQ,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,eAAe,CAAC;KAC9C,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,yBAAyB,EAAE,8CAA8C,CAAC;KACjF,MAAM,CAAC,uBAAuB,EAAE,iCAAiC,CAAC;KAClE,MAAM,CAAC,OAAO,EAAE,uBAAuB,CAAC;KACxC,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,CAAC;KACrE,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;KACtD,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5B,wBAAwB;AACxB,OAAO;KACF,OAAO,CAAC,6BAA6B,CAAC;KACtC,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KAC/C,MAAM,CAAC,mBAAmB,EAAE,oCAAoC,CAAC;KACjE,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5B,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"thinkdata.js","sourceRoot":"","sources":["../../src/bin/thinkdata.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wEAAwE,CAAC;KACrF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,mBAAmB;AACnB,OAAO;KACF,OAAO,CAAC,6BAA6B,CAAC;KACtC,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,CAAC;KAC1D,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,mBAAmB,EAAE,eAAe,EAAE,QAAQ,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,eAAe,CAAC;KAC9C,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,yBAAyB,EAAE,8CAA8C,CAAC;KACjF,MAAM,CAAC,uBAAuB,EAAE,iCAAiC,CAAC;KAClE,MAAM,CAAC,OAAO,EAAE,uBAAuB,CAAC;KACxC,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,CAAC;KACrE,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;KACtD,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5B,mBAAmB;AACnB,OAAO;KACF,OAAO,CAAC,6BAA6B,CAAC;KACtC,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KAC/C,MAAM,CAAC,mBAAmB,EAAE,oCAAoC,CAAC;KACjE,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5B,4BAA4B;AAC5B,OAAO;KACF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,0EAA0E,CAAC;KACvF,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACpE,MAAM,CAAC,YAAY,CAAC,CAAC;AAE1B,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ interface ServeOptions {
2
+ port?: number;
3
+ }
4
+ /**
5
+ * HTTP 서버 시작
6
+ */
7
+ export declare function serveCommand(options: ServeOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAkBA,UAAU,YAAY;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAyMD;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDvE"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * serve 명령 — CLI Agent HTTP 서버
3
+ *
4
+ * 브라우저(ThinkERD)에서 직접 접근하는 로컬 HTTP 서버.
5
+ * 데이터가 외부 서버를 경유하지 않고 localhost에서만 처리됩니다.
6
+ *
7
+ * 사용법:
8
+ * npx @thinkdata/cli serve
9
+ * npx @thinkdata/cli serve --port 3100
10
+ */
11
+ import { createServer } from 'node:http';
12
+ import { createExtractor } from '../extractors/index.js';
13
+ import { convertToERD } from '../converter/schemaToERD.js';
14
+ import { compareSchemas } from './compare.js';
15
+ const DEFAULT_PORT = 3100;
16
+ /**
17
+ * JSON 바디 파서
18
+ */
19
+ async function parseBody(req) {
20
+ return new Promise((resolve, reject) => {
21
+ let body = '';
22
+ req.on('data', chunk => { body += chunk; });
23
+ req.on('end', () => {
24
+ try {
25
+ resolve(body ? JSON.parse(body) : {});
26
+ }
27
+ catch (e) {
28
+ reject(new Error('Invalid JSON body'));
29
+ }
30
+ });
31
+ req.on('error', reject);
32
+ });
33
+ }
34
+ /**
35
+ * CORS 헤더 설정
36
+ */
37
+ function setCorsHeaders(res) {
38
+ res.setHeader('Access-Control-Allow-Origin', '*');
39
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
40
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
41
+ res.setHeader('Access-Control-Max-Age', '86400');
42
+ }
43
+ /**
44
+ * JSON 응답 헬퍼
45
+ */
46
+ function jsonResponse(res, status, data) {
47
+ res.writeHead(status, { 'Content-Type': 'application/json' });
48
+ res.end(JSON.stringify(data));
49
+ }
50
+ /**
51
+ * ConnectionConfig 변환 (요청 바디 → CLI 타입)
52
+ */
53
+ function toConnectionConfig(body) {
54
+ const engineMap = {
55
+ postgresql: 'postgres',
56
+ postgres: 'postgres',
57
+ mysql: 'mysql',
58
+ mariadb: 'mysql',
59
+ };
60
+ return {
61
+ type: engineMap[body.engine] || body.engine || 'postgres',
62
+ host: body.host || 'localhost',
63
+ port: body.port || 5432,
64
+ database: body.database,
65
+ user: body.username || body.user,
66
+ password: body.password || '',
67
+ schema: body.schema,
68
+ ssl: body.ssl || false,
69
+ };
70
+ }
71
+ /**
72
+ * 라우트 핸들러
73
+ */
74
+ const routes = {
75
+ // ── Health Check ──
76
+ 'GET /health': async (_req, res) => {
77
+ jsonResponse(res, 200, {
78
+ status: 'ok',
79
+ agent: '@thinkdata/cli',
80
+ version: '0.2.0',
81
+ timestamp: new Date().toISOString(),
82
+ });
83
+ },
84
+ // ── 연결 테스트 ──
85
+ 'POST /test-connection': async (req, res) => {
86
+ const body = await parseBody(req);
87
+ if (!body.database || !body.username) {
88
+ jsonResponse(res, 400, { error: 'database, username은 필수입니다.' });
89
+ return;
90
+ }
91
+ const config = toConnectionConfig(body);
92
+ try {
93
+ const extractor = createExtractor(config.type);
94
+ const version = await extractor.testConnection(config);
95
+ // 비밀번호 즉시 폐기
96
+ config.password = '';
97
+ jsonResponse(res, 200, {
98
+ success: true,
99
+ engine: config.type,
100
+ version,
101
+ host: config.host,
102
+ database: config.database,
103
+ });
104
+ }
105
+ catch (err) {
106
+ config.password = '';
107
+ jsonResponse(res, 400, {
108
+ success: false,
109
+ error: err.message || 'Connection failed',
110
+ });
111
+ }
112
+ },
113
+ // ── 스키마 추출 ──
114
+ 'POST /extract-schema': async (req, res) => {
115
+ const body = await parseBody(req);
116
+ if (!body.database || !body.username) {
117
+ jsonResponse(res, 400, { error: 'database, username은 필수입니다.' });
118
+ return;
119
+ }
120
+ const config = toConnectionConfig(body);
121
+ try {
122
+ const extractor = createExtractor(config.type);
123
+ const schema = await extractor.extract(config);
124
+ // 비밀번호 즉시 폐기
125
+ config.password = '';
126
+ // ERD 포맷으로 변환 (옵션)
127
+ if (body.format === 'erd') {
128
+ const erd = convertToERD(schema);
129
+ jsonResponse(res, 200, {
130
+ success: true,
131
+ format: 'erd',
132
+ data: erd,
133
+ });
134
+ }
135
+ else {
136
+ jsonResponse(res, 200, {
137
+ success: true,
138
+ format: 'raw',
139
+ data: schema,
140
+ });
141
+ }
142
+ }
143
+ catch (err) {
144
+ config.password = '';
145
+ jsonResponse(res, 500, {
146
+ success: false,
147
+ error: err.message || 'Schema extraction failed',
148
+ });
149
+ }
150
+ },
151
+ // ── 스키마 비교 (드리프트 감지) ──
152
+ 'POST /compare-schema': async (req, res) => {
153
+ const body = await parseBody(req);
154
+ if (!body.database || !body.username) {
155
+ jsonResponse(res, 400, { error: 'database, username은 필수입니다.' });
156
+ return;
157
+ }
158
+ if (!body.model) {
159
+ jsonResponse(res, 400, { error: 'model (ERD 스키마)은 필수입니다.' });
160
+ return;
161
+ }
162
+ const config = toConnectionConfig(body);
163
+ try {
164
+ const extractor = createExtractor(config.type);
165
+ const dbSchema = await extractor.extract(config);
166
+ // 비밀번호 즉시 폐기
167
+ config.password = '';
168
+ // 모델 스키마와 비교
169
+ const modelSchema = body.model;
170
+ const diff = compareSchemas(dbSchema, modelSchema);
171
+ jsonResponse(res, 200, {
172
+ success: true,
173
+ diff,
174
+ summary: {
175
+ added: diff.added.length,
176
+ removed: diff.removed.length,
177
+ modified: diff.modified.length,
178
+ fkDiffs: diff.fkDiffs.length,
179
+ hasChanges: diff.added.length > 0 || diff.removed.length > 0 ||
180
+ diff.modified.length > 0 || diff.fkDiffs.length > 0,
181
+ },
182
+ });
183
+ }
184
+ catch (err) {
185
+ config.password = '';
186
+ jsonResponse(res, 500, {
187
+ success: false,
188
+ error: err.message || 'Schema comparison failed',
189
+ });
190
+ }
191
+ },
192
+ };
193
+ /**
194
+ * HTTP 서버 시작
195
+ */
196
+ export async function serveCommand(options) {
197
+ const port = options.port || DEFAULT_PORT;
198
+ const server = createServer(async (req, res) => {
199
+ setCorsHeaders(res);
200
+ // CORS Preflight
201
+ if (req.method === 'OPTIONS') {
202
+ res.writeHead(204);
203
+ res.end();
204
+ return;
205
+ }
206
+ const routeKey = `${req.method} ${req.url?.split('?')[0]}`;
207
+ const handler = routes[routeKey];
208
+ if (handler) {
209
+ try {
210
+ await handler(req, res);
211
+ }
212
+ catch (err) {
213
+ console.error(`[Agent] Error handling ${routeKey}:`, err);
214
+ jsonResponse(res, 500, { error: 'Internal server error' });
215
+ }
216
+ }
217
+ else {
218
+ jsonResponse(res, 404, { error: `Not found: ${routeKey}` });
219
+ }
220
+ });
221
+ server.listen(port, '127.0.0.1', () => {
222
+ console.log();
223
+ console.log(' ┌─────────────────────────────────────────────┐');
224
+ console.log(' │ │');
225
+ console.log(` │ 🚀 ThinkERD Agent running on port ${port} │`);
226
+ console.log(' │ │');
227
+ console.log(` │ Health: http://localhost:${port}/health │`);
228
+ console.log(' │ Bound: 127.0.0.1 (local only) │');
229
+ console.log(' │ │');
230
+ console.log(' │ ✅ Data never leaves your machine │');
231
+ console.log(' │ ✅ Passwords stay in process memory only │');
232
+ console.log(' │ │');
233
+ console.log(' │ Press Ctrl+C to stop │');
234
+ console.log(' │ │');
235
+ console.log(' └─────────────────────────────────────────────┘');
236
+ console.log();
237
+ });
238
+ // Graceful shutdown
239
+ process.on('SIGINT', () => {
240
+ console.log('\n 👋 Agent stopped.');
241
+ server.close();
242
+ process.exit(0);
243
+ });
244
+ process.on('SIGTERM', () => {
245
+ server.close();
246
+ process.exit(0);
247
+ });
248
+ }
249
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAmC,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAyB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,YAAY,GAAG,IAAI,CAAC;AAM1B;;GAEG;AACH,KAAK,UAAU,SAAS,CAAC,GAAoB;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACf,IAAI,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAC3C,CAAC;QACL,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAmB;IACvC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;IACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,6BAA6B,CAAC,CAAC;IAC7E,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAS;IAChE,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,IAAS;IACjC,MAAM,SAAS,GAA6C;QACxD,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,OAAO;KACnB,CAAC;IAEF,OAAO;QACH,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,UAAU;QACzD,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,WAAW;QAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK;KACzB,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,MAAM,GAAiF;IAEzF,qBAAqB;IACrB,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC/B,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;YACnB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC,CAAC,CAAC;IACP,CAAC;IAED,eAAe;IACf,uBAAuB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC;YAChE,OAAO;QACX,CAAC;QAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAEvD,aAAa;YACb,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YAErB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;gBACnB,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,OAAO;gBACP,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;aAC5B,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YACrB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,mBAAmB;aAC5C,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,eAAe;IACf,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC;YAChE,OAAO;QACX,CAAC;QAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAE/C,aAAa;YACb,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YAErB,mBAAmB;YACnB,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;gBACjC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;oBACnB,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,KAAK;oBACb,IAAI,EAAE,GAAG;iBACZ,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;oBACnB,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,KAAK;oBACb,IAAI,EAAE,MAAM;iBACf,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YACrB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,0BAA0B;aACnD,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,yBAAyB;IACzB,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC;YAChE,OAAO;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACd,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;YAC7D,OAAO;QACX,CAAC;QAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEjD,aAAa;YACb,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YAErB,aAAa;YACb,MAAM,WAAW,GAAoB,IAAI,CAAC,KAAK,CAAC;YAChD,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YAEnD,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;gBACnB,OAAO,EAAE,IAAI;gBACb,IAAI;gBACJ,OAAO,EAAE;oBACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;oBAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;oBAC9B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;oBAC5B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;wBACxD,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;iBAC1D;aACJ,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YACrB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,0BAA0B;aACnD,CAAC,CAAC;QACP,CAAC;IACL,CAAC;CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC;IAE1C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,cAAc,CAAC,GAAG,CAAC,CAAC;QAEpB,iBAAiB;QACjB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC3B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,OAAO,EAAE,CAAC;YACV,IAAI,CAAC;gBACD,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC1D,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAC/D,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;QAClC,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,2CAA2C,IAAI,OAAO,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mCAAmC,IAAI,gBAAgB,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,oBAAoB;IACpB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/index.d.ts CHANGED
@@ -11,4 +11,5 @@ export { convertToERD } from './converter/schemaToERD.js';
11
11
  export type { ERDEntity, ERDColumn, ERDRelationship, ConversionResult } from './converter/schemaToERD.js';
12
12
  export { compareSchemas } from './commands/compare.js';
13
13
  export type { SchemaDiff, TableDiff, ColumnDiff, FKDiff } from './commands/compare.js';
14
+ export { serveCommand } from './commands/serve.js';
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EACR,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EACR,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -3,4 +3,5 @@ export { PostgresExtractor } from './extractors/postgres.js';
3
3
  export { MySQLExtractor } from './extractors/mysql.js';
4
4
  export { convertToERD } from './converter/schemaToERD.js';
5
5
  export { compareSchemas } from './commands/compare.js';
6
+ export { serveCommand } from './commands/serve.js';
6
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkdata/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "ThinkERD CLI — Database schema extraction and comparison tool",
5
5
  "type": "module",
6
6
  "files": ["dist", "README.md"],