metadatafy 1.4.2 → 1.4.4

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.
package/README.md CHANGED
@@ -7,18 +7,22 @@ A build plugin for extracting project metadata from your codebase. Supports Vite
7
7
  ## Features / 기능
8
8
 
9
9
  - **AST-based analysis** - Parses TypeScript/JavaScript files using TypeScript compiler API
10
+ - **Code pattern detection** - Automatically detects file types by analyzing actual code (hooks, components, services, etc.)
11
+ - **Smart path detection** - Supports various folder structures and naming conventions
10
12
  - **Import/Export extraction** - Tracks file dependencies and call graphs
11
13
  - **Component props detection** - Extracts React component props
12
14
  - **Korean keyword mapping** - Automatic English-Korean keyword translation
13
- - **Multiple output formats** - JSON file or API endpoint
15
+ - **Multiple output formats** - JSON file, API endpoint, or Supabase database
14
16
 
15
17
  ---
16
18
 
17
19
  - **AST 기반 분석** - TypeScript 컴파일러 API를 사용한 파일 파싱
20
+ - **코드 패턴 감지** - 실제 코드 분석으로 파일 타입 자동 감지 (hooks, components, services 등)
21
+ - **스마트 경로 감지** - 다양한 폴더 구조와 네이밍 컨벤션 지원
18
22
  - **Import/Export 추출** - 파일 의존성 및 호출 그래프 추적
19
23
  - **컴포넌트 Props 감지** - React 컴포넌트 props 추출
20
24
  - **한글 키워드 매핑** - 영어-한글 키워드 자동 변환
21
- - **다양한 출력 형식** - JSON 파일 또는 API 엔드포인트
25
+ - **다양한 출력 형식** - JSON 파일, API 엔드포인트, 또는 Supabase 데이터베이스
22
26
 
23
27
  ## Installation / 설치
24
28
 
@@ -54,32 +58,6 @@ This will:
54
58
  - 선택적으로 빌드 설정에 플러그인 추가 (vite.config.ts 또는 next.config.js)
55
59
  - 선택적으로 Supabase 연동 설정 (자동 업로드)
56
60
 
57
- ```
58
- $ npx metadatafy init
59
-
60
- 🚀 metadatafy 설정 마법사
61
-
62
- 프로젝트: my-app
63
- 경로: /Users/you/projects/my-app
64
-
65
- 🔍 프로젝트 분석 중...
66
-
67
- ✅ 감지된 정보:
68
- 프로젝트 타입: Next.js (App Router)
69
- 패키지 매니저: pnpm
70
- TypeScript: 예
71
- 주요 폴더: app, components, hooks, lib
72
-
73
- 📦 프로젝트 타입을 선택하세요:
74
- 1) Next.js (App Router) (감지됨)
75
- 2) Next.js (Pages Router)
76
- 3) Vite + React
77
- 4) Create React App
78
- 5) Node.js Backend
79
-
80
- 선택 [1]:
81
- ```
82
-
83
61
  ## Usage / 사용법
84
62
 
85
63
  ### CLI
@@ -130,15 +108,6 @@ npx metadatafy analyze --project-id my-project --output ./metadata.json --verbos
130
108
  | `--verbose` | | Enable detailed logging |
131
109
  | `--help` | `-h` | Show help |
132
110
 
133
- #### Upload Options / Upload 옵션
134
-
135
- | Option | Short | Description |
136
- |--------|-------|-------------|
137
- | `--input` | `-i` | Input file path (default: project-metadata.json) |
138
- | `--config` | `-c` | Config file path |
139
- | `--verbose` | | Enable detailed logging |
140
- | `--help` | `-h` | Show help |
141
-
142
111
  ### Vite Plugin
143
112
 
144
113
  ```typescript
@@ -165,12 +134,6 @@ export default defineConfig({
165
134
 
166
135
  #### Next.js 16+ (Turbopack) - Recommended
167
136
 
168
- Next.js 16부터 Turbopack이 기본 번들러입니다. Turbopack은 Webpack 플러그인을 지원하지 않으므로, Build Adapter 방식을 사용합니다.
169
-
170
- Since Next.js 16, Turbopack is the default bundler. Since Turbopack doesn't support Webpack plugins, use the Build Adapter approach.
171
-
172
- **Step 1: Create adapter file / 어댑터 파일 생성**
173
-
174
137
  ```javascript
175
138
  // metadata-adapter.js
176
139
  const { createMetadataAdapter } = require('metadatafy/next');
@@ -184,8 +147,6 @@ module.exports = createMetadataAdapter({
184
147
  });
185
148
  ```
186
149
 
187
- **Step 2: Configure next.config / next.config 설정**
188
-
189
150
  ```typescript
190
151
  // next.config.ts
191
152
  import type { NextConfig } from 'next';
@@ -201,38 +162,76 @@ export default nextConfig;
201
162
 
202
163
  #### Next.js 15 or Earlier (Webpack)
203
164
 
204
- For Next.js 15 or earlier, or when using `--webpack` flag:
205
-
206
- Next.js 15 이하 또는 `--webpack` 플래그 사용 시:
207
-
208
165
  ```javascript
209
166
  // next.config.js
210
167
  const { withMetadata } = require('metadatafy/next');
211
168
 
212
169
  /** @type {import('next').NextConfig} */
213
- const nextConfig = {
214
- // your config
215
- };
170
+ const nextConfig = {};
216
171
 
217
172
  module.exports = withMetadata({
218
173
  projectId: 'my-project',
219
174
  })(nextConfig);
220
175
  ```
221
176
 
222
- #### Alternative: CLI with npm scripts / 대안: npm 스크립트와 CLI
177
+ ## File Type Detection / 파일 타입 감지
178
+
179
+ metadatafy uses a **hybrid detection system** that combines multiple approaches:
180
+
181
+ metadatafy는 여러 접근 방식을 결합한 **하이브리드 감지 시스템**을 사용합니다:
182
+
183
+ ### Detection Priority / 감지 우선순위
184
+
185
+ 1. **Next.js special files** - `page.tsx`, `layout.tsx`, `route.ts` → route/api
186
+ 2. **Path segments** - `/api/` in path → api
187
+ 3. **Folder names** - `components/`, `hooks/`, `utils/`, `lib/` → corresponding type
188
+ 4. **Code pattern analysis** - AST-based detection of actual code patterns
189
+ 5. **Glob patterns** - User-defined patterns in config
190
+
191
+ ### Code Pattern Detection / 코드 패턴 감지
192
+
193
+ When folder/path detection fails, metadatafy analyzes the actual code:
194
+
195
+ 폴더/경로 감지가 실패하면 실제 코드를 분석합니다:
196
+
197
+ | Type | Detection Pattern |
198
+ |------|-------------------|
199
+ | **hook** | Uses `useState`, `useEffect`, etc. / Function starts with `use` |
200
+ | **component** | Returns JSX / Has `props` parameter |
201
+ | **api** | Exports `GET`, `POST`, etc. / Uses `NextRequest`/`NextResponse` |
202
+ | **service** | Uses `fetch`, `axios` / Multiple async functions / `*Service` class |
203
+ | **utility** | Multiple exported functions / No React dependencies |
204
+
205
+ ### Supported Naming Conventions / 지원하는 네이밍 컨벤션
206
+
207
+ All naming conventions are supported:
223
208
 
224
- Works with any Next.js version / 모든 Next.js 버전에서 동작:
209
+ 모든 네이밍 컨벤션을 지원합니다:
210
+
211
+ | Type | Examples |
212
+ |------|----------|
213
+ | **hook** | `useAuth.ts`, `use-auth.ts`, `use_auth.ts` |
214
+ | **service** | `AuthService.ts`, `auth-service.ts`, `auth.service.ts` |
215
+ | **utility** | `string-utils.ts`, `date_helper.ts`, `formatUtil.ts` |
216
+ | **component** | `Button.tsx`, `auth-modal.tsx`, `user_profile.tsx` |
217
+
218
+ ### Auto Pattern Expansion / 자동 패턴 확장
219
+
220
+ Include patterns are automatically expanded to match nested structures:
221
+
222
+ include 패턴은 중첩 구조에 맞게 자동 확장됩니다:
225
223
 
226
224
  ```json
227
225
  {
228
- "scripts": {
229
- "build": "next build",
230
- "build:with-metadata": "next build && metadatafy analyze",
231
- "metadata": "metadatafy analyze"
232
- }
226
+ "include": ["hooks/**/*.ts"]
233
227
  }
234
228
  ```
235
229
 
230
+ This will match both:
231
+ - `hooks/useAuth.ts`
232
+ - `src/hooks/useAuth.ts`
233
+ - `src/features/auth/hooks/useAuth.ts`
234
+
236
235
  ## Configuration / 설정
237
236
 
238
237
  Create `metadata.config.json` in your project root:
@@ -259,11 +258,13 @@ Create `metadata.config.json` in your project root:
259
258
  "enabled": true,
260
259
  "path": "project-metadata.json"
261
260
  },
262
- "api": {
263
- "enabled": false,
264
- "endpoint": "https://your-api.com/metadata",
265
- "headers": {
266
- "Authorization": "Bearer YOUR_TOKEN"
261
+ "database": {
262
+ "enabled": true,
263
+ "provider": "supabase",
264
+ "supabase": {
265
+ "url": "${SUPABASE_URL}",
266
+ "serviceRoleKey": "${SUPABASE_SERVICE_ROLE_KEY}",
267
+ "tableName": "code_index"
267
268
  }
268
269
  }
269
270
  },
@@ -279,9 +280,8 @@ Create `metadata.config.json` in your project root:
279
280
 
280
281
  ```json
281
282
  {
282
- "version": "1.0.0",
283
283
  "projectId": "my-project",
284
- "generatedAt": "2025-01-04T12:00:00Z",
284
+ "timestamp": "2025-01-04T12:00:00Z",
285
285
  "stats": {
286
286
  "totalFiles": 150,
287
287
  "byType": {
@@ -313,195 +313,137 @@ Create `metadata.config.json` in your project root:
313
313
  }
314
314
  ```
315
315
 
316
- ## File Type Detection / 파일 타입 감지
317
-
318
- | Pattern | Type |
319
- |---------|------|
320
- | `app/**/page.tsx` | route |
321
- | `app/**/route.ts` | api |
322
- | `components/**/*.tsx` | component |
323
- | `hooks/**/*.ts` | hook |
324
- | `services/**/*.ts` | service |
325
- | `lib/**/*.ts` | utility |
326
- | `supabase/migrations/*.sql` | table |
327
-
328
- ## API / 프로그래밍 방식 사용
329
-
330
- ```typescript
331
- import { ProjectAnalyzer, createDefaultConfig } from 'metadatafy';
332
-
333
- const config = createDefaultConfig({
334
- projectId: 'my-project',
335
- verbose: true,
336
- });
337
-
338
- const analyzer = new ProjectAnalyzer(config);
339
- const result = await analyzer.analyze(process.cwd());
340
-
341
- console.log(result.stats);
342
- console.log(result.items);
343
- ```
344
-
345
- ## Korean Keyword Mapping / 한글 키워드 매핑
346
-
347
- Built-in mappings include common development terms:
348
-
349
- 기본 제공되는 매핑에는 일반적인 개발 용어가 포함됩니다:
350
-
351
- | English | Korean |
352
- |---------|--------|
353
- | create | 생성, 만들기, 추가 |
354
- | update | 수정, 업데이트, 변경 |
355
- | delete | 삭제, 제거 |
356
- | search | 검색, 찾기 |
357
- | login | 로그인 |
358
- | user | 사용자, 유저, 회원 |
359
- | button | 버튼 |
360
- | modal | 모달, 팝업 |
361
- | ... | ... |
362
-
363
- You can extend with custom mappings in config.
364
-
365
- 설정에서 커스텀 매핑을 추가할 수 있습니다.
366
-
367
316
  ## Database Integration / 데이터베이스 연동
368
317
 
369
- Automatically upload metadata to Supabase on every build. Uses Service Role Key for RLS bypass.
370
-
371
- 빌드할 때마다 자동으로 Supabase에 메타데이터를 업로드합니다. Service Role Key를 사용하여 RLS를 우회합니다.
372
-
373
- ### Setup with init / init으로 설정
374
-
375
- The easiest way is through `npx metadatafy init`:
376
-
377
- 가장 쉬운 방법은 `npx metadatafy init`을 사용하는 것입니다:
378
-
379
- ```
380
- 🗄️ Supabase에 메타데이터를 자동 저장할까요?
381
- 빌드 시 자동으로 데이터베이스에 업로드됩니다.
382
-
383
- Supabase 연동 설정? [y/N]: y
384
-
385
- 🔧 Supabase 설정
386
- Settings > API에서 확인할 수 있습니다.
387
-
388
- 💡 환경변수 이름을 입력하면 ${VAR} 형식으로 저장됩니다.
389
- 예: SUPABASE_URL → ${SUPABASE_URL}
390
-
391
- Supabase URL 환경변수 이름 [SUPABASE_URL]:
392
- Service Role Key 환경변수 이름 [SUPABASE_SERVICE_ROLE_KEY]:
393
- 테이블 이름 [project_metadata]:
394
- ```
318
+ ### Supabase Table Schema / Supabase 테이블 스키마
395
319
 
396
- ### Manual Setup / 수동 설정
320
+ metadatafy stores each file as an individual row for better queryability:
397
321
 
398
- Or use the dedicated command:
322
+ metadatafy는 나은 쿼리를 위해 각 파일을 개별 row로 저장합니다:
399
323
 
400
- 또는 전용 명령어를 사용하세요:
324
+ ```sql
325
+ -- File type enum
326
+ CREATE TYPE file_type AS ENUM (
327
+ 'route', 'component', 'hook', 'service', 'api', 'table', 'utility'
328
+ );
401
329
 
402
- ```bash
403
- npx metadatafy database-init
404
- ```
330
+ -- Main table: individual code file metadata
331
+ CREATE TABLE code_index (
332
+ id TEXT PRIMARY KEY,
333
+ project_id TEXT NOT NULL,
334
+ file_type file_type NOT NULL,
335
+ name TEXT NOT NULL,
336
+ path TEXT NOT NULL,
337
+ keywords TEXT[] DEFAULT '{}',
338
+ search_text TEXT,
339
+ calls TEXT[] DEFAULT '{}',
340
+ called_by TEXT[] DEFAULT '{}',
341
+ metadata JSONB DEFAULT '{}',
342
+ created_at TIMESTAMPTZ DEFAULT NOW(),
343
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
344
+ UNIQUE(project_id, path)
345
+ );
405
346
 
406
- ### Direct Plugin Configuration / 플러그인 직접 설정
347
+ -- Analysis log table
348
+ CREATE TABLE code_analysis_log (
349
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
350
+ project_id TEXT NOT NULL,
351
+ total_files INTEGER NOT NULL,
352
+ stats JSONB NOT NULL,
353
+ parse_errors TEXT[] DEFAULT '{}',
354
+ analyzed_at TIMESTAMPTZ NOT NULL,
355
+ created_at TIMESTAMPTZ DEFAULT NOW()
356
+ );
407
357
 
408
- You can also pass Supabase config directly to the plugin:
358
+ -- Indexes for search optimization
359
+ CREATE INDEX idx_code_index_project_id ON code_index(project_id);
360
+ CREATE INDEX idx_code_index_file_type ON code_index(file_type);
361
+ CREATE INDEX idx_code_index_keywords ON code_index USING GIN(keywords);
362
+ CREATE INDEX idx_code_index_search_text ON code_index USING GIN(to_tsvector('simple', search_text));
409
363
 
410
- 플러그인에 직접 Supabase 설정을 전달할 수도 있습니다:
364
+ -- RLS Policies
365
+ ALTER TABLE code_index ENABLE ROW LEVEL SECURITY;
366
+ ALTER TABLE code_analysis_log ENABLE ROW LEVEL SECURITY;
411
367
 
412
- ```typescript
413
- // vite.config.ts
414
- import metadatafy from 'metadatafy/vite';
368
+ -- Read access for authenticated users
369
+ CREATE POLICY "Authenticated users can read code_index"
370
+ ON code_index FOR SELECT TO authenticated USING (true);
415
371
 
416
- export default defineConfig({
417
- plugins: [
418
- metadatafy({
419
- projectId: 'my-project',
420
- supabase: {
421
- url: process.env.SUPABASE_URL!,
422
- serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,
423
- tableName: 'project_metadata',
424
- },
425
- }),
426
- ],
427
- });
372
+ -- Write access for service role only
373
+ CREATE POLICY "Service role can manage code_index"
374
+ ON code_index FOR ALL TO service_role USING (true) WITH CHECK (true);
428
375
  ```
429
376
 
430
- ```typescript
431
- // next.config.ts
432
- import { withMetadata } from 'metadatafy/next';
377
+ ### Configuration / 설정
433
378
 
434
- export default withMetadata({
435
- projectId: 'my-project',
436
- supabase: {
437
- url: process.env.SUPABASE_URL!,
438
- serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,
439
- tableName: 'project_metadata',
440
- },
441
- })(nextConfig);
442
- ```
443
-
444
- ### Supabase Table Schema / Supabase 테이블 스키마
445
-
446
- ```sql
447
- CREATE TABLE project_metadata (
448
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
449
- project_id TEXT UNIQUE NOT NULL,
450
- metadata JSONB NOT NULL,
451
- created_at TIMESTAMPTZ DEFAULT NOW(),
452
- updated_at TIMESTAMPTZ DEFAULT NOW()
453
- );
454
-
455
- -- RLS Policy (optional - Service Role Key bypasses RLS)
456
- ALTER TABLE project_metadata ENABLE ROW LEVEL SECURITY;
379
+ ```json
380
+ {
381
+ "output": {
382
+ "database": {
383
+ "enabled": true,
384
+ "provider": "supabase",
385
+ "supabase": {
386
+ "url": "${SUPABASE_URL}",
387
+ "serviceRoleKey": "${SUPABASE_SERVICE_ROLE_KEY}",
388
+ "tableName": "code_index"
389
+ }
390
+ }
391
+ }
392
+ }
457
393
  ```
458
394
 
459
395
  ### Environment Variables / 환경변수
460
396
 
461
- Add to your `.env` file:
462
-
463
- `.env` 파일에 추가하세요:
464
-
465
397
  ```bash
466
398
  SUPABASE_URL=https://your-project.supabase.co
467
399
  SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
468
400
  ```
469
401
 
470
- > **Note**: Service Role Key is used (not anon key) to bypass RLS and ensure reliable upserts.
471
- >
472
- > **참고**: RLS 우회 및 안정적인 upsert를 위해 Service Role Key를 사용합니다 (anon key가 아님).
473
-
474
402
  ### How It Works / 작동 방식
475
403
 
476
- - **Upsert by project_id**: If a record with the same `project_id` exists, it updates. Otherwise, it creates a new record.
477
- - **Automatic on build**: When using Vite/Next.js plugins with Supabase config, metadata is uploaded on every build.
478
- - **CLI support**: `npx metadatafy analyze` also uploads if database config is in `metadata.config.json`.
404
+ 1. **Delete existing project data** - Removes all rows with matching `project_id`
405
+ 2. **Bulk insert new data** - Inserts all files in chunks of 500
406
+ 3. **Log analysis run** - Records stats in `code_analysis_log` table
479
407
 
480
- - **project_id 기준 upsert**: 동일한 `project_id`가 있으면 업데이트, 없으면 새로 생성합니다.
481
- - **빌드 시 자동 업로드**: Vite/Next.js 플러그인에 Supabase 설정이 있으면 빌드마다 자동 업로드됩니다.
482
- - **CLI 지원**: `npx metadatafy analyze --upload`로 DB에 업로드합니다.
408
+ ---
483
409
 
484
- ### Recommended Workflow / 권장 워크플로우
410
+ 1. **기존 프로젝트 데이터 삭제** - 동일한 `project_id`의 모든 row 삭제
411
+ 2. **새 데이터 일괄 삽입** - 500개 단위로 모든 파일 삽입
412
+ 3. **분석 로그 기록** - `code_analysis_log` 테이블에 통계 기록
413
+
414
+ ### Querying Code / 코드 쿼리 예시
485
415
 
486
- Build and metadata generation are separate. Run manually or add to CI.
416
+ ```sql
417
+ -- Find all hooks in a project
418
+ SELECT * FROM code_index
419
+ WHERE project_id = 'my-project' AND file_type = 'hook';
420
+
421
+ -- Full-text search
422
+ SELECT * FROM code_index
423
+ WHERE project_id = 'my-project'
424
+ AND search_text ILIKE '%authentication%';
425
+
426
+ -- Find files that call a specific file
427
+ SELECT * FROM code_index
428
+ WHERE 'hooks/useAuth.ts' = ANY(calls);
429
+
430
+ -- Get analysis history
431
+ SELECT * FROM code_analysis_log
432
+ WHERE project_id = 'my-project'
433
+ ORDER BY analyzed_at DESC;
434
+ ```
487
435
 
488
- 빌드와 메타데이터 생성은 분리되어 있습니다. 수동으로 실행하거나 CI에 추가하세요.
436
+ ### Recommended Workflow / 권장 워크플로우
489
437
 
490
438
  ```bash
491
- # Regular build (unchanged)
492
- # 일반 빌드 (변경 없음)
493
- npm run build
494
-
495
- # Generate metadata + upload (when needed)
496
- # 메타데이터 생성 + 업로드 (필요할 때)
439
+ # Generate metadata + upload
497
440
  npx metadatafy analyze --upload
498
441
 
499
- # Or upload existing file only
500
- # 또는 기존 파일만 업로드
501
- npx metadatafy upload
442
+ # Or in CI/CD
443
+ npx metadatafy analyze --upload
502
444
  ```
503
445
 
504
- **For CI / GitHub Actions:**
446
+ **GitHub Actions:**
505
447
 
506
448
  ```yaml
507
449
  - run: npm run build
@@ -511,6 +453,42 @@ npx metadatafy upload
511
453
  SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
512
454
  ```
513
455
 
456
+ ## API / 프로그래밍 방식 사용
457
+
458
+ ```typescript
459
+ import { ProjectAnalyzer, createDefaultConfig } from 'metadatafy';
460
+
461
+ const config = createDefaultConfig({
462
+ projectId: 'my-project',
463
+ verbose: true,
464
+ });
465
+
466
+ const analyzer = new ProjectAnalyzer(config);
467
+ const result = await analyzer.analyze(process.cwd());
468
+
469
+ console.log(result.stats);
470
+ console.log(result.items);
471
+ ```
472
+
473
+ ## Korean Keyword Mapping / 한글 키워드 매핑
474
+
475
+ Built-in mappings include common development terms:
476
+
477
+ 기본 제공되는 매핑에는 일반적인 개발 용어가 포함됩니다:
478
+
479
+ | English | Korean |
480
+ |---------|--------|
481
+ | create | 생성, 만들기, 추가 |
482
+ | update | 수정, 업데이트, 변경 |
483
+ | delete | 삭제, 제거 |
484
+ | search | 검색, 찾기 |
485
+ | login | 로그인 |
486
+ | user | 사용자, 유저, 회원 |
487
+
488
+ You can extend with custom mappings in config.
489
+
490
+ 설정에서 커스텀 매핑을 추가할 수 있습니다.
491
+
514
492
  ## License / 라이선스
515
493
 
516
494
  MIT
@@ -1 +1 @@
1
- async function a(e){switch(e.provider){case "supabase":let{SupabaseProvider:r}=await import('./supabase-TGVJDKHE.js');return new r(e);case "custom":let{CustomApiProvider:t}=await import('./custom-api-MPVFDKPU.js');return new t(e);default:throw new Error(`Unknown provider: ${e.provider}`)}}export{a};
1
+ async function a(e){switch(e.provider){case "supabase":let{SupabaseProvider:r}=await import('./supabase-QJ4W7OH5.js');return new r(e);case "custom":let{CustomApiProvider:t}=await import('./custom-api-MPVFDKPU.js');return new t(e);default:throw new Error(`Unknown provider: ${e.provider}`)}}export{a};
@@ -1 +1 @@
1
- 'use strict';async function a(e){switch(e.provider){case "supabase":let{SupabaseProvider:r}=await import('./supabase-HWODZTEI.cjs');return new r(e);case "custom":let{CustomApiProvider:t}=await import('./custom-api-THEHQ4IR.cjs');return new t(e);default:throw new Error(`Unknown provider: ${e.provider}`)}}exports.a=a;
1
+ 'use strict';async function a(e){switch(e.provider){case "supabase":let{SupabaseProvider:r}=await import('./supabase-ODLVMAF6.cjs');return new r(e);case "custom":let{CustomApiProvider:t}=await import('./custom-api-THEHQ4IR.cjs');return new t(e);default:throw new Error(`Unknown provider: ${e.provider}`)}}exports.a=a;
package/dist/cli.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var chunkXR3EVOXW_cjs=require('./chunk-XR3EVOXW.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),chunkZAACVJBX_cjs=require('./chunk-ZAACVJBX.cjs'),util=require('util'),f=require('path'),m=require('fs/promises'),_=require('readline');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var f__namespace=/*#__PURE__*/_interopNamespace(f);var m__namespace=/*#__PURE__*/_interopNamespace(m);var ___namespace=/*#__PURE__*/_interopNamespace(_);async function oe(e){let s=[{file:"pnpm-lock.yaml",manager:"pnpm"},{file:"yarn.lock",manager:"yarn"},{file:"package-lock.json",manager:"npm"}];for(let{file:t,manager:a}of s)try{return await m__namespace.access(f__namespace.join(e,t)),a}catch{}return "npm"}async function ae(e){let s={};try{let a=await m__namespace.readFile(f__namespace.join(e,"package.json"),"utf-8");s=JSON.parse(a);}catch{return "unknown"}let t={...s.dependencies||{},...s.devDependencies||{}};return t.next?await S(f__namespace.join(e,"app"))||await S(f__namespace.join(e,"src","app"))?"nextjs-app":"nextjs-pages":t.vite?"vite":t["react-scripts"]?"cra":t.express||t.fastify||t.koa?"node":"unknown"}async function D(e){let[s,t]=await Promise.all([ae(e),oe(e)]),a=await se(f__namespace.join(e,"tsconfig.json")),o=await S(f__namespace.join(e,"src")),n=["app","pages","components","hooks","services","lib","utils","api","src/app","src/pages","src/components","src/hooks","src/services","src/lib","src/utils"],i=[];for(let c of n)await S(f__namespace.join(e,c))&&i.push(c);let r=await S(f__namespace.join(e,"prisma")),u=await S(f__namespace.join(e,"supabase"));return {type:s,packageManager:t,hasTypescript:a,hasSrc:o,existingFolders:i,hasPrisma:r,hasSupabase:u}}async function se(e){try{return (await m__namespace.stat(e)).isFile()}catch{return false}}async function S(e){try{return (await m__namespace.stat(e)).isDirectory()}catch{return false}}function O(e){return {"nextjs-app":"Next.js (App Router)","nextjs-pages":"Next.js (Pages Router)",vite:"Vite + React",cra:"Create React App",node:"Node.js Backend",unknown:"Unknown"}[e]}var x=null;function ne(){return x||(x=___namespace.createInterface({input:process.stdin,output:process.stdout,terminal:false})),x}function b(e){return new Promise(s=>{process.stdout.write(e),ne().once("line",t=>{s(t);});})}function F(){x&&(x.close(),x=null);}async function M(e){let s=[{key:"1",type:"nextjs-app",label:"Next.js (App Router)"},{key:"2",type:"nextjs-pages",label:"Next.js (Pages Router)"},{key:"3",type:"vite",label:"Vite + React"},{key:"4",type:"cra",label:"Create React App"},{key:"5",type:"node",label:"Node.js Backend"}],t=s.findIndex(r=>r.type===e),a=t>=0?s[t].key:"1";console.log(`
2
+ 'use strict';var chunkW2STEULD_cjs=require('./chunk-W2STEULD.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),chunkZAACVJBX_cjs=require('./chunk-ZAACVJBX.cjs'),util=require('util'),f=require('path'),m=require('fs/promises'),_=require('readline');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var f__namespace=/*#__PURE__*/_interopNamespace(f);var m__namespace=/*#__PURE__*/_interopNamespace(m);var ___namespace=/*#__PURE__*/_interopNamespace(_);async function oe(e){let s=[{file:"pnpm-lock.yaml",manager:"pnpm"},{file:"yarn.lock",manager:"yarn"},{file:"package-lock.json",manager:"npm"}];for(let{file:t,manager:a}of s)try{return await m__namespace.access(f__namespace.join(e,t)),a}catch{}return "npm"}async function ae(e){let s={};try{let a=await m__namespace.readFile(f__namespace.join(e,"package.json"),"utf-8");s=JSON.parse(a);}catch{return "unknown"}let t={...s.dependencies||{},...s.devDependencies||{}};return t.next?await S(f__namespace.join(e,"app"))||await S(f__namespace.join(e,"src","app"))?"nextjs-app":"nextjs-pages":t.vite?"vite":t["react-scripts"]?"cra":t.express||t.fastify||t.koa?"node":"unknown"}async function D(e){let[s,t]=await Promise.all([ae(e),oe(e)]),a=await se(f__namespace.join(e,"tsconfig.json")),o=await S(f__namespace.join(e,"src")),n=["app","pages","components","hooks","services","lib","utils","api","src/app","src/pages","src/components","src/hooks","src/services","src/lib","src/utils"],i=[];for(let c of n)await S(f__namespace.join(e,c))&&i.push(c);let r=await S(f__namespace.join(e,"prisma")),u=await S(f__namespace.join(e,"supabase"));return {type:s,packageManager:t,hasTypescript:a,hasSrc:o,existingFolders:i,hasPrisma:r,hasSupabase:u}}async function se(e){try{return (await m__namespace.stat(e)).isFile()}catch{return false}}async function S(e){try{return (await m__namespace.stat(e)).isDirectory()}catch{return false}}function O(e){return {"nextjs-app":"Next.js (App Router)","nextjs-pages":"Next.js (Pages Router)",vite:"Vite + React",cra:"Create React App",node:"Node.js Backend",unknown:"Unknown"}[e]}var x=null;function ne(){return x||(x=___namespace.createInterface({input:process.stdin,output:process.stdout,terminal:false})),x}function b(e){return new Promise(s=>{process.stdout.write(e),ne().once("line",t=>{s(t);});})}function F(){x&&(x.close(),x=null);}async function M(e){let s=[{key:"1",type:"nextjs-app",label:"Next.js (App Router)"},{key:"2",type:"nextjs-pages",label:"Next.js (Pages Router)"},{key:"3",type:"vite",label:"Vite + React"},{key:"4",type:"cra",label:"Create React App"},{key:"5",type:"node",label:"Node.js Backend"}],t=s.findIndex(r=>r.type===e),a=t>=0?s[t].key:"1";console.log(`
3
3
  \u{1F4E6} \uD504\uB85C\uC81D\uD2B8 \uD0C0\uC785\uC744 \uC120\uD0DD\uD558\uC138\uC694:`),s.forEach(r=>{let c=r.type===e?" (\uAC10\uC9C0\uB428)":"";console.log(` ${r.key}) ${r.label}${c}`);});let n=(await b(`
4
4
  \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.type||e}async function B(e){let s=[{key:"1",manager:"npm"},{key:"2",manager:"yarn"},{key:"3",manager:"pnpm"}],t=s.findIndex(r=>r.manager===e),a=t>=0?s[t].key:"1";console.log(`
5
5
  \u{1F4E6} \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB97C \uC120\uD0DD\uD558\uC138\uC694:`),s.forEach(r=>{let c=r.manager===e?" (\uAC10\uC9C0\uB428)":"";console.log(` ${r.key}) ${r.manager}${c}`);});let n=(await b(`
6
- \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.manager||e}async function K(e){if(e==="node"||e==="unknown")return false;let s=e.startsWith("nextjs")?"next.config":"vite.config";return console.log(`
7
- \u{1F527} ${s} \uD30C\uC77C\uC5D0 metadatafy \uD50C\uB7EC\uADF8\uC778\uC744 \uC790\uB3D9\uC73C\uB85C \uCD94\uAC00\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uBA54\uD0C0\uB370\uC774\uD130\uAC00 \uC0DD\uC131\uB429\uB2C8\uB2E4."),(await b(`
8
- \uCD94\uAC00\uD560\uAE4C\uC694? [Y/n]: `)).trim().toLowerCase()!=="n"}async function W(e,s=true){let o=(await b(`${e} ${s?"[Y/n]":"[y/N]"}: `)).trim().toLowerCase();return o===""?s:o==="y"||o==="yes"}async function J(){return console.log(`
6
+ \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.manager||e}async function K(e){return e==="node"||e==="unknown"||e.startsWith("nextjs")?false:(console.log(`
7
+ \u{1F527} vite.config \uD30C\uC77C\uC5D0 metadatafy \uD50C\uB7EC\uADF8\uC778\uC744 \uC790\uB3D9\uC73C\uB85C \uCD94\uAC00\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uBA54\uD0C0\uB370\uC774\uD130\uAC00 \uC0DD\uC131\uB429\uB2C8\uB2E4."),(await b(`
8
+ \uCD94\uAC00\uD560\uAE4C\uC694? [Y/n]: `)).trim().toLowerCase()!=="n")}async function W(e,s=true){let o=(await b(`${e} ${s?"[Y/n]":"[y/N]"}: `)).trim().toLowerCase();return o===""?s:o==="y"||o==="yes"}async function J(){return console.log(`
9
9
  \u{1F5C4}\uFE0F Supabase\uC5D0 \uBA54\uD0C0\uB370\uC774\uD130\uB97C \uC790\uB3D9 \uC800\uC7A5\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC5C5\uB85C\uB4DC\uB429\uB2C8\uB2E4."),(await b(`
10
10
  Supabase \uC5F0\uB3D9 \uC124\uC815? [y/N]: `)).trim().toLowerCase()==="y"}async function V(e={}){console.log(`
11
11
  \u{1F527} Supabase \uC124\uC815`),console.log(`\uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC0AC\uC6A9 \uC911\uC778 \uD658\uACBD\uBCC0\uC218 \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694.
@@ -32,7 +32,7 @@ Supabase \uC5F0\uB3D9 \uC124\uC815? [y/N]: `)).trim().toLowerCase()==="y"}async
32
32
  \uD14C\uC774\uBE14 \uC774\uB984 [project_metadata]: `)).trim()||"project_metadata";console.log(`
33
33
  \u{1F4DD} \uD544\uB4DC \uB9E4\uD551 \uC124\uC815`),console.log(`\uBA54\uD0C0\uB370\uC774\uD130\uB97C \uC800\uC7A5\uD560 \uCEEC\uB7FC \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694.
34
34
  `);let r=await g("\uD504\uB85C\uC81D\uD2B8 ID \uD544\uB4DC [project_id]: "),u=await g("\uBA54\uD0C0\uB370\uC774\uD130 JSON \uD544\uB4DC [metadata]: "),c=await g('\uC0DD\uC131 \uC2DC\uAC04 \uD544\uB4DC (\uBE48\uCE78=created_at, "none"=\uC0AC\uC6A9\uC548\uD568) [created_at]: '),l=await g('\uC5C5\uB370\uC774\uD2B8 \uC2DC\uAC04 \uD544\uB4DC (\uBE48\uCE78=updated_at, "none"=\uC0AC\uC6A9\uC548\uD568) [updated_at]: ');return {config:{enabled:true,provider:"supabase",supabase:{url:a,serviceRoleKey:o,tableName:i,fields:{projectId:r.trim()||"project_id",metadata:u.trim()||"metadata",...c.trim().toLowerCase()!=="none"&&{createdAt:c.trim()||"created_at"},...l.trim().toLowerCase()!=="none"&&{updatedAt:l.trim()||"updated_at"}}}},actualValues:{url:s.trim(),serviceRoleKey:t}}}async function ue(e,s){if(console.log(`
35
- \u{1F50C} \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911...`),e.provider!=="supabase"||!e.supabase)return true;let t={provider:"supabase",enabled:true,url:s.url,serviceRoleKey:s.serviceRoleKey,tableName:e.supabase.tableName,fields:{projectId:e.supabase.fields.projectId,metadata:e.supabase.fields.metadata,createdAt:e.supabase.fields.createdAt,updatedAt:e.supabase.fields.updatedAt}};try{return await(await chunkXR3EVOXW_cjs.a(t)).testConnection()?(console.log("\u2705 \uC5F0\uACB0 \uC131\uACF5!"),!0):(console.log("\u274C \uC5F0\uACB0 \uC2E4\uD328. \uC124\uC815\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694."),!1)}catch(a){return console.log(`\u274C \uC5F0\uACB0 \uC624\uB958: ${a instanceof Error?a.message:a}`),false}}async function de(e,s){let t=f__namespace.join(e,"metadata.config.json"),a={};try{let n=await m__namespace.readFile(t,"utf-8");a=JSON.parse(n);}catch{a={projectId:f__namespace.basename(e),include:["src/**/*.{ts,tsx}"],exclude:["**/node_modules/**","**/*.test.{ts,tsx}"],output:{}};}let o=a.output||{};return o.database=s,a.output=o,await m__namespace.writeFile(t,JSON.stringify(a,null,2)),t}function ge(e){if(!e.supabase)return;let{tableName:s,fields:t}=e.supabase;console.log(`
35
+ \u{1F50C} \uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911...`),e.provider!=="supabase"||!e.supabase)return true;let t={provider:"supabase",enabled:true,url:s.url,serviceRoleKey:s.serviceRoleKey,tableName:e.supabase.tableName,fields:{projectId:e.supabase.fields.projectId,metadata:e.supabase.fields.metadata,createdAt:e.supabase.fields.createdAt,updatedAt:e.supabase.fields.updatedAt}};try{return await(await chunkW2STEULD_cjs.a(t)).testConnection()?(console.log("\u2705 \uC5F0\uACB0 \uC131\uACF5!"),!0):(console.log("\u274C \uC5F0\uACB0 \uC2E4\uD328. \uC124\uC815\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694."),!1)}catch(a){return console.log(`\u274C \uC5F0\uACB0 \uC624\uB958: ${a instanceof Error?a.message:a}`),false}}async function de(e,s){let t=f__namespace.join(e,"metadata.config.json"),a={};try{let n=await m__namespace.readFile(t,"utf-8");a=JSON.parse(n);}catch{a={projectId:f__namespace.basename(e),include:["src/**/*.{ts,tsx}"],exclude:["**/node_modules/**","**/*.test.{ts,tsx}"],output:{}};}let o=a.output||{};return o.database=s,a.output=o,await m__namespace.writeFile(t,JSON.stringify(a,null,2)),t}function ge(e){if(!e.supabase)return;let{tableName:s,fields:t}=e.supabase;console.log(`
36
36
  \u{1F4CB} Supabase\uC5D0\uC11C \uB2E4\uC74C SQL\uB85C \uD14C\uC774\uBE14\uC744 \uC0DD\uC131\uD558\uC138\uC694:
37
37
  `),console.log("```sql"),console.log(`CREATE TABLE ${s} (`),console.log(" id UUID DEFAULT gen_random_uuid() PRIMARY KEY,"),console.log(` ${t.projectId} TEXT UNIQUE NOT NULL,`),console.log(` ${t.metadata} JSONB NOT NULL,`),t.createdAt&&console.log(` ${t.createdAt} TIMESTAMPTZ DEFAULT NOW(),`),t.updatedAt&&console.log(` ${t.updatedAt} TIMESTAMPTZ DEFAULT NOW()`),console.log(");"),console.log(""),console.log("-- RLS \uC815\uCC45 (\uD544\uC694\uC2DC)"),console.log(`ALTER TABLE ${s} ENABLE ROW LEVEL SECURITY;`),console.log("```\n");}function fe(e){if(e.provider!=="supabase"||!e.supabase)return;let{url:s,serviceRoleKey:t}=e.supabase;if(s.startsWith("${")||t.startsWith("${")){if(console.log(`\u{1F510} .env \uD30C\uC77C\uC5D0 \uB2E4\uC74C \uD658\uACBD\uBCC0\uC218\uB97C \uC124\uC815\uD558\uC138\uC694:
38
38
  `),s.startsWith("${")){let a=s.slice(2,-1);console.log(`${a}=https://your-project.supabase.co`);}if(t.startsWith("${")){let a=t.slice(2,-1);console.log(`${a}=your-service-role-key`);}console.log(`
@@ -93,7 +93,7 @@ Options:
93
93
  `),console.log("\u{1F4CA} Results:"),console.log(` Total files: ${p.stats.totalFiles}`),console.log(` - Routes: ${p.stats.byType.route}`),console.log(` - Components: ${p.stats.byType.component}`),console.log(` - Hooks: ${p.stats.byType.hook}`),console.log(` - Services: ${p.stats.byType.service}`),console.log(` - APIs: ${p.stats.byType.api}`),console.log(` - Tables: ${p.stats.byType.table}`),console.log(` - Utilities: ${p.stats.byType.utility}`),console.log(`
94
94
  \u{1F4C4} Output: ${v}`),p.stats.parseErrors.length>0&&(console.log(`
95
95
  \u26A0\uFE0F Parse errors (${p.stats.parseErrors.length}):`),p.stats.parseErrors.slice(0,5).forEach(h=>{console.log(` - ${h}`);}),p.stats.parseErrors.length>5&&console.log(` ... and ${p.stats.parseErrors.length-5} more`)),console.log("");}catch(l){console.error("\u274C Analysis failed:",l),process.exit(1);}}async function Pe(e){let{values:s}=util.parseArgs({args:e,options:{input:{type:"string",short:"i"},config:{type:"string",short:"c"},verbose:{type:"boolean"},help:{type:"boolean",short:"h"}}});s.help&&(console.log(be),process.exit(0));let t=process.cwd();chunkZAACVJBX_cjs.b(t,s.verbose);let a=s.input||"project-metadata.json",o=s.verbose||false,n={};if(s.config)try{let c=await m__namespace.readFile(s.config,"utf-8");n=JSON.parse(c);}catch{console.error(`Failed to load config file: ${s.config}`),process.exit(1);}else {let c=f__namespace.join(t,"metadata.config.json");try{let l=await m__namespace.readFile(c,"utf-8");n=JSON.parse(l),o&&console.log(`Loaded config from ${c}`);}catch{console.error("\u274C metadata.config.json \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."),console.log(" npx metadatafy init \uC73C\uB85C \uC124\uC815\uC744 \uBA3C\uC800 \uC0DD\uC131\uD558\uC138\uC694."),process.exit(1);}}let i=f__namespace.resolve(t,a),r;try{let c=await m__namespace.readFile(i,"utf-8");r=JSON.parse(c);}catch{console.error(`\u274C \uBA54\uD0C0\uB370\uC774\uD130 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${i}`),console.log(" npx metadatafy analyze \uB85C \uBA3C\uC800 \uBD84\uC11D\uC744 \uC2E4\uD589\uD558\uC138\uC694."),process.exit(1);}console.log(`
96
- \u{1F4E4} Uploading metadata from: ${i}`);let u=await te(t,n);u||(console.error("\u274C \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."),console.log(" npx metadatafy database-init \uC73C\uB85C \uC124\uC815\uC744 \uCD94\uAC00\uD558\uC138\uC694."),process.exit(1));try{let l=await(await chunkXR3EVOXW_cjs.a(u)).upload(r);l.success?console.log(`
96
+ \u{1F4E4} Uploading metadata from: ${i}`);let u=await te(t,n);u||(console.error("\u274C \uB370\uC774\uD130\uBCA0\uC774\uC2A4 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."),console.log(" npx metadatafy database-init \uC73C\uB85C \uC124\uC815\uC744 \uCD94\uAC00\uD558\uC138\uC694."),process.exit(1));try{let l=await(await chunkW2STEULD_cjs.a(u)).upload(r);l.success?console.log(`
97
97
  \u2705 ${l.message} (${u.provider})`):(console.error(`
98
98
  \u274C Upload failed: ${l.error}`),process.exit(1));}catch(c){console.error(`
99
99
  \u274C Upload error: ${c instanceof Error?c.message:c}`),process.exit(1);}}async function je(){let e=process.cwd(),s=f__namespace.basename(e);console.log(`
@@ -114,4 +114,4 @@ Options:
114
114
  \u{1F4CB} Supabase\uC5D0\uC11C \uD14C\uC774\uBE14\uC744 \uC0DD\uC131\uD558\uC138\uC694:
115
115
  `),console.log(` CREATE TABLE ${u.tableName} (`),console.log(" id UUID DEFAULT gen_random_uuid() PRIMARY KEY,"),console.log(" project_id TEXT UNIQUE NOT NULL,"),console.log(" metadata JSONB NOT NULL,"),console.log(" created_at TIMESTAMPTZ DEFAULT NOW(),"),console.log(" updated_at TIMESTAMPTZ DEFAULT NOW()"),console.log(` );
116
116
  `));}finally{F();}}function T(e){if(!e||typeof e!="string")return e;if(e.startsWith("${")&&e.endsWith("}")){let s=e.slice(2,-1);return process.env[s]||""}return e}async function te(e,s){let t=s.output?.database;if(!t||!t.enabled)return null;if(t.provider==="supabase"&&t.supabase){let{supabase:a}=t,o=T(a.url),n=T(a.serviceRoleKey);return !o||!n?(console.log("\u26A0\uFE0F Supabase \uD658\uACBD\uBCC0\uC218\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."),a.url.startsWith("${")&&console.log(` ${a.url.slice(2,-1)}\uC744(\uB97C) \uC124\uC815\uD574\uC8FC\uC138\uC694.`),a.serviceRoleKey.startsWith("${")&&console.log(` ${a.serviceRoleKey.slice(2,-1)}\uC744(\uB97C) \uC124\uC815\uD574\uC8FC\uC138\uC694.`),null):{provider:"supabase",enabled:true,url:o,serviceRoleKey:n,tableName:a.tableName,fields:{projectId:a.fields.projectId,metadata:a.fields.metadata,createdAt:a.fields.createdAt,updatedAt:a.fields.updatedAt}}}if(t.provider==="custom"&&t.custom){let{custom:a}=t,o={};if(a.headers)for(let[n,i]of Object.entries(a.headers))o[n]=T(i);return {provider:"custom",enabled:true,endpoint:T(a.endpoint),method:a.method,headers:o}}return null}async function ve(e,s,t){let a=await te(process.cwd(),e);if(a){t&&console.log(`
117
- \u{1F5C4}\uFE0F Uploading to ${a.provider}...`);try{let n=await(await chunkXR3EVOXW_cjs.a(a)).upload(s);n.success?console.log(`\u{1F5C4}\uFE0F ${n.message} (${a.provider})`):console.log(`\u26A0\uFE0F Database upload failed: ${n.error}`);}catch(o){console.log(`\u26A0\uFE0F Database upload error: ${o instanceof Error?o.message:o}`);}}}he().catch(e=>{console.error("Fatal error:",e),process.exit(1);});
117
+ \u{1F5C4}\uFE0F Uploading to ${a.provider}...`);try{let n=await(await chunkW2STEULD_cjs.a(a)).upload(s);n.success?console.log(`\u{1F5C4}\uFE0F ${n.message} (${a.provider})`):console.log(`\u26A0\uFE0F Database upload failed: ${n.error}`);}catch(o){console.log(`\u26A0\uFE0F Database upload error: ${o instanceof Error?o.message:o}`);}}}he().catch(e=>{console.error("Fatal error:",e),process.exit(1);});
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import {a}from'./chunk-ESZLTJIF.js';import {d,y,z as z$1,A}from'./chunk-UIDEH2GS.js';import {b as b$1}from'./chunk-BJMCLX3M.js';import {parseArgs}from'util';import*as f from'path';import*as m from'fs/promises';import*as _ from'readline';async function oe(e){let s=[{file:"pnpm-lock.yaml",manager:"pnpm"},{file:"yarn.lock",manager:"yarn"},{file:"package-lock.json",manager:"npm"}];for(let{file:t,manager:a}of s)try{return await m.access(f.join(e,t)),a}catch{}return "npm"}async function ae(e){let s={};try{let a=await m.readFile(f.join(e,"package.json"),"utf-8");s=JSON.parse(a);}catch{return "unknown"}let t={...s.dependencies||{},...s.devDependencies||{}};return t.next?await S(f.join(e,"app"))||await S(f.join(e,"src","app"))?"nextjs-app":"nextjs-pages":t.vite?"vite":t["react-scripts"]?"cra":t.express||t.fastify||t.koa?"node":"unknown"}async function D(e){let[s,t]=await Promise.all([ae(e),oe(e)]),a=await se(f.join(e,"tsconfig.json")),o=await S(f.join(e,"src")),n=["app","pages","components","hooks","services","lib","utils","api","src/app","src/pages","src/components","src/hooks","src/services","src/lib","src/utils"],i=[];for(let c of n)await S(f.join(e,c))&&i.push(c);let r=await S(f.join(e,"prisma")),u=await S(f.join(e,"supabase"));return {type:s,packageManager:t,hasTypescript:a,hasSrc:o,existingFolders:i,hasPrisma:r,hasSupabase:u}}async function se(e){try{return (await m.stat(e)).isFile()}catch{return false}}async function S(e){try{return (await m.stat(e)).isDirectory()}catch{return false}}function O(e){return {"nextjs-app":"Next.js (App Router)","nextjs-pages":"Next.js (Pages Router)",vite:"Vite + React",cra:"Create React App",node:"Node.js Backend",unknown:"Unknown"}[e]}var x=null;function ne(){return x||(x=_.createInterface({input:process.stdin,output:process.stdout,terminal:false})),x}function b(e){return new Promise(s=>{process.stdout.write(e),ne().once("line",t=>{s(t);});})}function F(){x&&(x.close(),x=null);}async function M(e){let s=[{key:"1",type:"nextjs-app",label:"Next.js (App Router)"},{key:"2",type:"nextjs-pages",label:"Next.js (Pages Router)"},{key:"3",type:"vite",label:"Vite + React"},{key:"4",type:"cra",label:"Create React App"},{key:"5",type:"node",label:"Node.js Backend"}],t=s.findIndex(r=>r.type===e),a=t>=0?s[t].key:"1";console.log(`
2
+ import {a}from'./chunk-7VGYPCY7.js';import {d,y,z as z$1,A}from'./chunk-UIDEH2GS.js';import {b as b$1}from'./chunk-BJMCLX3M.js';import {parseArgs}from'util';import*as f from'path';import*as m from'fs/promises';import*as _ from'readline';async function oe(e){let s=[{file:"pnpm-lock.yaml",manager:"pnpm"},{file:"yarn.lock",manager:"yarn"},{file:"package-lock.json",manager:"npm"}];for(let{file:t,manager:a}of s)try{return await m.access(f.join(e,t)),a}catch{}return "npm"}async function ae(e){let s={};try{let a=await m.readFile(f.join(e,"package.json"),"utf-8");s=JSON.parse(a);}catch{return "unknown"}let t={...s.dependencies||{},...s.devDependencies||{}};return t.next?await S(f.join(e,"app"))||await S(f.join(e,"src","app"))?"nextjs-app":"nextjs-pages":t.vite?"vite":t["react-scripts"]?"cra":t.express||t.fastify||t.koa?"node":"unknown"}async function D(e){let[s,t]=await Promise.all([ae(e),oe(e)]),a=await se(f.join(e,"tsconfig.json")),o=await S(f.join(e,"src")),n=["app","pages","components","hooks","services","lib","utils","api","src/app","src/pages","src/components","src/hooks","src/services","src/lib","src/utils"],i=[];for(let c of n)await S(f.join(e,c))&&i.push(c);let r=await S(f.join(e,"prisma")),u=await S(f.join(e,"supabase"));return {type:s,packageManager:t,hasTypescript:a,hasSrc:o,existingFolders:i,hasPrisma:r,hasSupabase:u}}async function se(e){try{return (await m.stat(e)).isFile()}catch{return false}}async function S(e){try{return (await m.stat(e)).isDirectory()}catch{return false}}function O(e){return {"nextjs-app":"Next.js (App Router)","nextjs-pages":"Next.js (Pages Router)",vite:"Vite + React",cra:"Create React App",node:"Node.js Backend",unknown:"Unknown"}[e]}var x=null;function ne(){return x||(x=_.createInterface({input:process.stdin,output:process.stdout,terminal:false})),x}function b(e){return new Promise(s=>{process.stdout.write(e),ne().once("line",t=>{s(t);});})}function F(){x&&(x.close(),x=null);}async function M(e){let s=[{key:"1",type:"nextjs-app",label:"Next.js (App Router)"},{key:"2",type:"nextjs-pages",label:"Next.js (Pages Router)"},{key:"3",type:"vite",label:"Vite + React"},{key:"4",type:"cra",label:"Create React App"},{key:"5",type:"node",label:"Node.js Backend"}],t=s.findIndex(r=>r.type===e),a=t>=0?s[t].key:"1";console.log(`
3
3
  \u{1F4E6} \uD504\uB85C\uC81D\uD2B8 \uD0C0\uC785\uC744 \uC120\uD0DD\uD558\uC138\uC694:`),s.forEach(r=>{let c=r.type===e?" (\uAC10\uC9C0\uB428)":"";console.log(` ${r.key}) ${r.label}${c}`);});let n=(await b(`
4
4
  \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.type||e}async function B(e){let s=[{key:"1",manager:"npm"},{key:"2",manager:"yarn"},{key:"3",manager:"pnpm"}],t=s.findIndex(r=>r.manager===e),a=t>=0?s[t].key:"1";console.log(`
5
5
  \u{1F4E6} \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB97C \uC120\uD0DD\uD558\uC138\uC694:`),s.forEach(r=>{let c=r.manager===e?" (\uAC10\uC9C0\uB428)":"";console.log(` ${r.key}) ${r.manager}${c}`);});let n=(await b(`
6
- \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.manager||e}async function K(e){if(e==="node"||e==="unknown")return false;let s=e.startsWith("nextjs")?"next.config":"vite.config";return console.log(`
7
- \u{1F527} ${s} \uD30C\uC77C\uC5D0 metadatafy \uD50C\uB7EC\uADF8\uC778\uC744 \uC790\uB3D9\uC73C\uB85C \uCD94\uAC00\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uBA54\uD0C0\uB370\uC774\uD130\uAC00 \uC0DD\uC131\uB429\uB2C8\uB2E4."),(await b(`
8
- \uCD94\uAC00\uD560\uAE4C\uC694? [Y/n]: `)).trim().toLowerCase()!=="n"}async function W(e,s=true){let o=(await b(`${e} ${s?"[Y/n]":"[y/N]"}: `)).trim().toLowerCase();return o===""?s:o==="y"||o==="yes"}async function J(){return console.log(`
6
+ \uC120\uD0DD [${a}]: `)).trim()||a;return s.find(r=>r.key===n)?.manager||e}async function K(e){return e==="node"||e==="unknown"||e.startsWith("nextjs")?false:(console.log(`
7
+ \u{1F527} vite.config \uD30C\uC77C\uC5D0 metadatafy \uD50C\uB7EC\uADF8\uC778\uC744 \uC790\uB3D9\uC73C\uB85C \uCD94\uAC00\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uBA54\uD0C0\uB370\uC774\uD130\uAC00 \uC0DD\uC131\uB429\uB2C8\uB2E4."),(await b(`
8
+ \uCD94\uAC00\uD560\uAE4C\uC694? [Y/n]: `)).trim().toLowerCase()!=="n")}async function W(e,s=true){let o=(await b(`${e} ${s?"[Y/n]":"[y/N]"}: `)).trim().toLowerCase();return o===""?s:o==="y"||o==="yes"}async function J(){return console.log(`
9
9
  \u{1F5C4}\uFE0F Supabase\uC5D0 \uBA54\uD0C0\uB370\uC774\uD130\uB97C \uC790\uB3D9 \uC800\uC7A5\uD560\uAE4C\uC694?`),console.log(" \uBE4C\uB4DC \uC2DC \uC790\uB3D9\uC73C\uB85C \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC5C5\uB85C\uB4DC\uB429\uB2C8\uB2E4."),(await b(`
10
10
  Supabase \uC5F0\uB3D9 \uC124\uC815? [y/N]: `)).trim().toLowerCase()==="y"}async function V(e={}){console.log(`
11
11
  \u{1F527} Supabase \uC124\uC815`),console.log(`\uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC0AC\uC6A9 \uC911\uC778 \uD658\uACBD\uBCC0\uC218 \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694.
package/dist/next.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var chunkXR3EVOXW_cjs=require('./chunk-XR3EVOXW.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),u=require('path'),v=require('fs/promises');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var u__namespace=/*#__PURE__*/_interopNamespace(u);var v__namespace=/*#__PURE__*/_interopNamespace(v);async function m(a,t,e){let i=new chunkOPGCPTPY_cjs.y(a),n=new chunkOPGCPTPY_cjs.z(a),l=a.output.api?.enabled?new chunkOPGCPTPY_cjs.A(a):null;a.verbose&&console.log("[metadata-plugin] Starting analysis...");let r=await i.analyze(t);if(a.output.file?.enabled){let s=u__namespace.resolve(t,a.output.file.path);await n.write(r,s),a.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${s}`);}if(l&&(await l.send(r),a.verbose&&console.log("[metadata-plugin] Sent metadata to API")),e?.url&&e?.serviceRoleKey)try{let s={provider:"supabase",enabled:!0,url:e.url,serviceRoleKey:e.serviceRoleKey,tableName:e.tableName,fields:{projectId:e.fields?.projectId||"project_id",metadata:e.fields?.metadata||"metadata",createdAt:e.fields?.createdAt||"created_at",updatedAt:e.fields?.updatedAt||"updated_at"}},p=await(await chunkXR3EVOXW_cjs.a(s)).upload(r);a.verbose&&(p.success?console.log(`[metadata-plugin] ${p.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${p.error}`));}catch(s){console.error("[metadata-plugin] Supabase upload error:",s);}}function A(a={}){let t=chunkOPGCPTPY_cjs.d(a),e=a.supabase,i=chunkOPGCPTPY_cjs.e(t);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var chunkW2STEULD_cjs=require('./chunk-W2STEULD.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),u=require('path'),v=require('fs/promises');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var u__namespace=/*#__PURE__*/_interopNamespace(u);var v__namespace=/*#__PURE__*/_interopNamespace(v);async function m(a,t,e){let i=new chunkOPGCPTPY_cjs.y(a),n=new chunkOPGCPTPY_cjs.z(a),l=a.output.api?.enabled?new chunkOPGCPTPY_cjs.A(a):null;a.verbose&&console.log("[metadata-plugin] Starting analysis...");let r=await i.analyze(t);if(a.output.file?.enabled){let s=u__namespace.resolve(t,a.output.file.path);await n.write(r,s),a.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${s}`);}if(l&&(await l.send(r),a.verbose&&console.log("[metadata-plugin] Sent metadata to API")),e?.url&&e?.serviceRoleKey)try{let s={provider:"supabase",enabled:!0,url:e.url,serviceRoleKey:e.serviceRoleKey,tableName:e.tableName,fields:{projectId:e.fields?.projectId||"project_id",metadata:e.fields?.metadata||"metadata",createdAt:e.fields?.createdAt||"created_at",updatedAt:e.fields?.updatedAt||"updated_at"}},p=await(await chunkW2STEULD_cjs.a(s)).upload(r);a.verbose&&(p.success?console.log(`[metadata-plugin] ${p.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${p.error}`));}catch(s){console.error("[metadata-plugin] Supabase upload error:",s);}}function A(a={}){let t=chunkOPGCPTPY_cjs.d(a),e=a.supabase,i=chunkOPGCPTPY_cjs.e(t);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
2
2
  ${i.join(`
3
3
  `)}`);return {name:"metadata-adapter",async onBuildComplete({projectDir:n}){t.verbose&&console.log("[metadata-plugin] Build completed, running analysis..."),await m(t,n,e),t.verbose&&console.log("[metadata-plugin] Analysis completed");}}}async function N(a,t={}){let e=u__namespace.join(a,".metadata-adapter.js"),i=`
4
4
  // Auto-generated by metadatafy
package/dist/next.js CHANGED
@@ -1,4 +1,4 @@
1
- import {a}from'./chunk-ESZLTJIF.js';import {d,e,y,z,A as A$1}from'./chunk-UIDEH2GS.js';import*as u from'path';import*as v from'fs/promises';async function m(a$1,t,e){let i=new y(a$1),n=new z(a$1),l=a$1.output.api?.enabled?new A$1(a$1):null;a$1.verbose&&console.log("[metadata-plugin] Starting analysis...");let r=await i.analyze(t);if(a$1.output.file?.enabled){let s=u.resolve(t,a$1.output.file.path);await n.write(r,s),a$1.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${s}`);}if(l&&(await l.send(r),a$1.verbose&&console.log("[metadata-plugin] Sent metadata to API")),e?.url&&e?.serviceRoleKey)try{let s={provider:"supabase",enabled:!0,url:e.url,serviceRoleKey:e.serviceRoleKey,tableName:e.tableName,fields:{projectId:e.fields?.projectId||"project_id",metadata:e.fields?.metadata||"metadata",createdAt:e.fields?.createdAt||"created_at",updatedAt:e.fields?.updatedAt||"updated_at"}},p=await(await a(s)).upload(r);a$1.verbose&&(p.success?console.log(`[metadata-plugin] ${p.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${p.error}`));}catch(s){console.error("[metadata-plugin] Supabase upload error:",s);}}function A(a={}){let t=d(a),e$1=a.supabase,i=e(t);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
1
+ import {a}from'./chunk-7VGYPCY7.js';import {d,e,y,z,A as A$1}from'./chunk-UIDEH2GS.js';import*as u from'path';import*as v from'fs/promises';async function m(a$1,t,e){let i=new y(a$1),n=new z(a$1),l=a$1.output.api?.enabled?new A$1(a$1):null;a$1.verbose&&console.log("[metadata-plugin] Starting analysis...");let r=await i.analyze(t);if(a$1.output.file?.enabled){let s=u.resolve(t,a$1.output.file.path);await n.write(r,s),a$1.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${s}`);}if(l&&(await l.send(r),a$1.verbose&&console.log("[metadata-plugin] Sent metadata to API")),e?.url&&e?.serviceRoleKey)try{let s={provider:"supabase",enabled:!0,url:e.url,serviceRoleKey:e.serviceRoleKey,tableName:e.tableName,fields:{projectId:e.fields?.projectId||"project_id",metadata:e.fields?.metadata||"metadata",createdAt:e.fields?.createdAt||"created_at",updatedAt:e.fields?.updatedAt||"updated_at"}},p=await(await a(s)).upload(r);a$1.verbose&&(p.success?console.log(`[metadata-plugin] ${p.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${p.error}`));}catch(s){console.error("[metadata-plugin] Supabase upload error:",s);}}function A(a={}){let t=d(a),e$1=a.supabase,i=e(t);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
2
2
  ${i.join(`
3
3
  `)}`);return {name:"metadata-adapter",async onBuildComplete({projectDir:n}){t.verbose&&console.log("[metadata-plugin] Build completed, running analysis..."),await m(t,n,e$1),t.verbose&&console.log("[metadata-plugin] Analysis completed");}}}async function N(a,t={}){let e=u.join(a,".metadata-adapter.js"),i=`
4
4
  // Auto-generated by metadatafy
@@ -0,0 +1 @@
1
+ 'use strict';var i=class{constructor(e){this.name="Supabase";this.config=e;}getRestUrl(e){return `${this.config.url.replace(/\/$/,"")}/rest/v1/${e}`}getHeaders(){return {apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json"}}async testConnection(){try{let e=await fetch(this.getRestUrl(this.config.tableName),{method:"GET",headers:{...this.getHeaders(),Range:"0-0"}});return e.ok||e.status===416}catch{return false}}async upload(e){let{tableName:a}=this.config;try{if(await this.deleteByProjectId(e.projectId),e.items.length>0){let t=await this.bulkInsertItems(e.items);if(!t.success)return t}return await this.logAnalysis(e),{success:!0,message:`${e.items.length} files uploaded to ${a}`,data:{itemsCount:e.items.length,stats:e.stats}}}catch(t){return {success:false,message:"Failed to upload metadata",error:t instanceof Error?t.message:String(t)}}}async deleteByProjectId(e){let{tableName:a}=this.config,t=await fetch(`${this.getRestUrl(a)}?project_id=eq.${encodeURIComponent(e)}`,{method:"DELETE",headers:this.getHeaders()});if(!t.ok&&t.status!==404){let r=await t.text();throw new Error(`Failed to delete existing data: ${r}`)}}async bulkInsertItems(e){let{tableName:a}=this.config,t=e.map(s=>({id:s.id,project_id:s.projectId,file_type:s.type,name:s.name,path:s.path,keywords:s.keywords,search_text:s.searchText,calls:s.calls,called_by:s.calledBy,metadata:s.metadata})),n=this.chunkArray(t,500);for(let s of n){let o=await fetch(this.getRestUrl(a),{method:"POST",headers:{...this.getHeaders(),Prefer:"return=minimal"},body:JSON.stringify(s)});if(!o.ok)return {success:false,message:"Failed to insert items",error:await o.text()}}return {success:true,message:"Items inserted successfully"}}async logAnalysis(e){let a="code_analysis_log",t={project_id:e.projectId,total_files:e.stats.totalFiles,stats:e.stats.byType,parse_errors:e.stats.parseErrors,analyzed_at:e.timestamp};try{await fetch(this.getRestUrl(a),{method:"POST",headers:{...this.getHeaders(),Prefer:"return=minimal"},body:JSON.stringify(t)});}catch{}}chunkArray(e,a){let t=[];for(let r=0;r<e.length;r+=a)t.push(e.slice(r,r+a));return t}};exports.SupabaseProvider=i;
@@ -0,0 +1 @@
1
+ var i=class{constructor(e){this.name="Supabase";this.config=e;}getRestUrl(e){return `${this.config.url.replace(/\/$/,"")}/rest/v1/${e}`}getHeaders(){return {apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json"}}async testConnection(){try{let e=await fetch(this.getRestUrl(this.config.tableName),{method:"GET",headers:{...this.getHeaders(),Range:"0-0"}});return e.ok||e.status===416}catch{return false}}async upload(e){let{tableName:a}=this.config;try{if(await this.deleteByProjectId(e.projectId),e.items.length>0){let t=await this.bulkInsertItems(e.items);if(!t.success)return t}return await this.logAnalysis(e),{success:!0,message:`${e.items.length} files uploaded to ${a}`,data:{itemsCount:e.items.length,stats:e.stats}}}catch(t){return {success:false,message:"Failed to upload metadata",error:t instanceof Error?t.message:String(t)}}}async deleteByProjectId(e){let{tableName:a}=this.config,t=await fetch(`${this.getRestUrl(a)}?project_id=eq.${encodeURIComponent(e)}`,{method:"DELETE",headers:this.getHeaders()});if(!t.ok&&t.status!==404){let r=await t.text();throw new Error(`Failed to delete existing data: ${r}`)}}async bulkInsertItems(e){let{tableName:a}=this.config,t=e.map(s=>({id:s.id,project_id:s.projectId,file_type:s.type,name:s.name,path:s.path,keywords:s.keywords,search_text:s.searchText,calls:s.calls,called_by:s.calledBy,metadata:s.metadata})),n=this.chunkArray(t,500);for(let s of n){let o=await fetch(this.getRestUrl(a),{method:"POST",headers:{...this.getHeaders(),Prefer:"return=minimal"},body:JSON.stringify(s)});if(!o.ok)return {success:false,message:"Failed to insert items",error:await o.text()}}return {success:true,message:"Items inserted successfully"}}async logAnalysis(e){let a="code_analysis_log",t={project_id:e.projectId,total_files:e.stats.totalFiles,stats:e.stats.byType,parse_errors:e.stats.parseErrors,analyzed_at:e.timestamp};try{await fetch(this.getRestUrl(a),{method:"POST",headers:{...this.getHeaders(),Prefer:"return=minimal"},body:JSON.stringify(t)});}catch{}}chunkArray(e,a){let t=[];for(let r=0;r<e.length;r+=a)t.push(e.slice(r,r+a));return t}};export{i as SupabaseProvider};
package/dist/vite.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var chunkXR3EVOXW_cjs=require('./chunk-XR3EVOXW.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),v=require('path');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var v__namespace=/*#__PURE__*/_interopNamespace(v);async function P(e,l,t){let s=new chunkOPGCPTPY_cjs.y(e),n=new chunkOPGCPTPY_cjs.z(e),o=e.output.api?.enabled?new chunkOPGCPTPY_cjs.A(e):null;e.verbose&&console.log("[metadata-plugin] Starting analysis...");let a=await s.analyze(l);if(e.output.file?.enabled){let r=v__namespace.resolve(l,e.output.file.path);await n.write(a,r),e.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${r}`);}if(o&&(await o.send(a),e.verbose&&console.log("[metadata-plugin] Sent metadata to API")),t?.url&&t?.serviceRoleKey)try{let r={provider:"supabase",enabled:!0,url:t.url,serviceRoleKey:t.serviceRoleKey,tableName:t.tableName,fields:{projectId:t.fields?.projectId||"project_id",metadata:t.fields?.metadata||"metadata",createdAt:t.fields?.createdAt||"created_at",updatedAt:t.fields?.updatedAt||"updated_at"}},i=await(await chunkXR3EVOXW_cjs.a(r)).upload(a);e.verbose&&(i.success?console.log(`[metadata-plugin] ${i.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${i.error}`));}catch(r){console.error("[metadata-plugin] Supabase upload error:",r);}return a}function b(e={}){let l=chunkOPGCPTPY_cjs.d(e),t=e.runOn||"build",s=e.emitStatsFile!==false,n=e.supabase,o,a=null,r=false;return {name:"vite-metadata-plugin",enforce:"post",configResolved(d){o=d;let i=chunkOPGCPTPY_cjs.e(l);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var chunkW2STEULD_cjs=require('./chunk-W2STEULD.cjs'),chunkOPGCPTPY_cjs=require('./chunk-OPGCPTPY.cjs'),v=require('path');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var v__namespace=/*#__PURE__*/_interopNamespace(v);async function P(e,l,t){let s=new chunkOPGCPTPY_cjs.y(e),n=new chunkOPGCPTPY_cjs.z(e),o=e.output.api?.enabled?new chunkOPGCPTPY_cjs.A(e):null;e.verbose&&console.log("[metadata-plugin] Starting analysis...");let a=await s.analyze(l);if(e.output.file?.enabled){let r=v__namespace.resolve(l,e.output.file.path);await n.write(a,r),e.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${r}`);}if(o&&(await o.send(a),e.verbose&&console.log("[metadata-plugin] Sent metadata to API")),t?.url&&t?.serviceRoleKey)try{let r={provider:"supabase",enabled:!0,url:t.url,serviceRoleKey:t.serviceRoleKey,tableName:t.tableName,fields:{projectId:t.fields?.projectId||"project_id",metadata:t.fields?.metadata||"metadata",createdAt:t.fields?.createdAt||"created_at",updatedAt:t.fields?.updatedAt||"updated_at"}},i=await(await chunkW2STEULD_cjs.a(r)).upload(a);e.verbose&&(i.success?console.log(`[metadata-plugin] ${i.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${i.error}`));}catch(r){console.error("[metadata-plugin] Supabase upload error:",r);}return a}function b(e={}){let l=chunkOPGCPTPY_cjs.d(e),t=e.runOn||"build",s=e.emitStatsFile!==false,n=e.supabase,o,a=null,r=false;return {name:"vite-metadata-plugin",enforce:"post",configResolved(d){o=d;let i=chunkOPGCPTPY_cjs.e(l);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
2
2
  ${i.join(`
3
3
  `)}`)},async buildStart(){if(r||!(t==="both"||t==="build"&&o.command==="build"||t==="serve"&&o.command==="serve"))return;r=true;let i=o.root;try{a=await P(l,i,n);}catch(u){if(console.error("[metadata-plugin] Analysis failed:",u),o.command==="build")throw u}},generateBundle(){!a||!s||this.emitFile({type:"asset",fileName:"metadata-stats.json",source:JSON.stringify(a.stats,null,2)});},closeBundle(){l.verbose&&a&&console.log(`[metadata-plugin] Build complete. Analyzed ${a.stats.totalFiles} files.`),r=false,a=null;}}}exports.default=b;exports.metadataPlugin=b;
package/dist/vite.js CHANGED
@@ -1,3 +1,3 @@
1
- import {a}from'./chunk-ESZLTJIF.js';import {d,e,y,z,A}from'./chunk-UIDEH2GS.js';import*as v from'path';async function P(e,l,t){let s=new y(e),n=new z(e),o=e.output.api?.enabled?new A(e):null;e.verbose&&console.log("[metadata-plugin] Starting analysis...");let a$1=await s.analyze(l);if(e.output.file?.enabled){let r=v.resolve(l,e.output.file.path);await n.write(a$1,r),e.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${r}`);}if(o&&(await o.send(a$1),e.verbose&&console.log("[metadata-plugin] Sent metadata to API")),t?.url&&t?.serviceRoleKey)try{let r={provider:"supabase",enabled:!0,url:t.url,serviceRoleKey:t.serviceRoleKey,tableName:t.tableName,fields:{projectId:t.fields?.projectId||"project_id",metadata:t.fields?.metadata||"metadata",createdAt:t.fields?.createdAt||"created_at",updatedAt:t.fields?.updatedAt||"updated_at"}},i=await(await a(r)).upload(a$1);e.verbose&&(i.success?console.log(`[metadata-plugin] ${i.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${i.error}`));}catch(r){console.error("[metadata-plugin] Supabase upload error:",r);}return a$1}function b(e$1={}){let l=d(e$1),t=e$1.runOn||"build",s=e$1.emitStatsFile!==false,n=e$1.supabase,o,a=null,r=false;return {name:"vite-metadata-plugin",enforce:"post",configResolved(d){o=d;let i=e(l);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
1
+ import {a}from'./chunk-7VGYPCY7.js';import {d,e,y,z,A}from'./chunk-UIDEH2GS.js';import*as v from'path';async function P(e,l,t){let s=new y(e),n=new z(e),o=e.output.api?.enabled?new A(e):null;e.verbose&&console.log("[metadata-plugin] Starting analysis...");let a$1=await s.analyze(l);if(e.output.file?.enabled){let r=v.resolve(l,e.output.file.path);await n.write(a$1,r),e.verbose&&console.log(`[metadata-plugin] Wrote metadata to ${r}`);}if(o&&(await o.send(a$1),e.verbose&&console.log("[metadata-plugin] Sent metadata to API")),t?.url&&t?.serviceRoleKey)try{let r={provider:"supabase",enabled:!0,url:t.url,serviceRoleKey:t.serviceRoleKey,tableName:t.tableName,fields:{projectId:t.fields?.projectId||"project_id",metadata:t.fields?.metadata||"metadata",createdAt:t.fields?.createdAt||"created_at",updatedAt:t.fields?.updatedAt||"updated_at"}},i=await(await a(r)).upload(a$1);e.verbose&&(i.success?console.log(`[metadata-plugin] ${i.message} (Supabase)`):console.log(`[metadata-plugin] Supabase upload failed: ${i.error}`));}catch(r){console.error("[metadata-plugin] Supabase upload error:",r);}return a$1}function b(e$1={}){let l=d(e$1),t=e$1.runOn||"build",s=e$1.emitStatsFile!==false,n=e$1.supabase,o,a=null,r=false;return {name:"vite-metadata-plugin",enforce:"post",configResolved(d){o=d;let i=e(l);if(i.length>0)throw new Error(`[metadata-plugin] Invalid config:
2
2
  ${i.join(`
3
3
  `)}`)},async buildStart(){if(r||!(t==="both"||t==="build"&&o.command==="build"||t==="serve"&&o.command==="serve"))return;r=true;let i=o.root;try{a=await P(l,i,n);}catch(u){if(console.error("[metadata-plugin] Analysis failed:",u),o.command==="build")throw u}},generateBundle(){!a||!s||this.emitFile({type:"asset",fileName:"metadata-stats.json",source:JSON.stringify(a.stats,null,2)});},closeBundle(){l.verbose&&a&&console.log(`[metadata-plugin] Build complete. Analyzed ${a.stats.totalFiles} files.`),r=false,a=null;}}}export{b as default,b as metadataPlugin};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metadatafy",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "Build plugin for extracting project metadata for ticket analysis system",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1 +0,0 @@
1
- 'use strict';var i=class{constructor(e){this.name="Supabase";this.config=e;}getRestUrl(e){return `${this.config.url.replace(/\/$/,"")}/rest/v1/${e}`}async testConnection(){try{let e=await fetch(this.getRestUrl(this.config.tableName),{method:"GET",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Range:"0-0"}});return e.ok||e.status===416}catch{return false}}async upload(e){let{fields:t,tableName:o}=this.config,s=await this.findByProjectId(e.projectId),a={[t.projectId]:e.projectId,[t.metadata]:e};t.updatedAt&&(a[t.updatedAt]=new Date().toISOString()),!s&&t.createdAt&&(a[t.createdAt]=new Date().toISOString());try{let r;if(s?r=await fetch(`${this.getRestUrl(o)}?${t.projectId}=eq.${e.projectId}`,{method:"PATCH",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify(a)}):r=await fetch(this.getRestUrl(o),{method:"POST",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify(a)}),!r.ok){let c=await r.text();return {success:!1,message:`Supabase API error: ${r.status}`,error:c}}let n=await r.json();return {success:!0,message:s?"Metadata updated":"Metadata created",data:n}}catch(r){return {success:false,message:"Failed to upload metadata",error:r instanceof Error?r.message:String(r)}}}async findByProjectId(e){try{let{fields:t,tableName:o}=this.config,s=await fetch(`${this.getRestUrl(o)}?${t.projectId}=eq.${e}&limit=1`,{method:"GET",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json"}});if(!s.ok)return null;let a=await s.json();return Array.isArray(a)&&a.length>0?a[0]:null}catch{return null}}};exports.SupabaseProvider=i;
@@ -1 +0,0 @@
1
- var i=class{constructor(e){this.name="Supabase";this.config=e;}getRestUrl(e){return `${this.config.url.replace(/\/$/,"")}/rest/v1/${e}`}async testConnection(){try{let e=await fetch(this.getRestUrl(this.config.tableName),{method:"GET",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Range:"0-0"}});return e.ok||e.status===416}catch{return false}}async upload(e){let{fields:t,tableName:o}=this.config,s=await this.findByProjectId(e.projectId),a={[t.projectId]:e.projectId,[t.metadata]:e};t.updatedAt&&(a[t.updatedAt]=new Date().toISOString()),!s&&t.createdAt&&(a[t.createdAt]=new Date().toISOString());try{let r;if(s?r=await fetch(`${this.getRestUrl(o)}?${t.projectId}=eq.${e.projectId}`,{method:"PATCH",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify(a)}):r=await fetch(this.getRestUrl(o),{method:"POST",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json",Prefer:"return=representation"},body:JSON.stringify(a)}),!r.ok){let c=await r.text();return {success:!1,message:`Supabase API error: ${r.status}`,error:c}}let n=await r.json();return {success:!0,message:s?"Metadata updated":"Metadata created",data:n}}catch(r){return {success:false,message:"Failed to upload metadata",error:r instanceof Error?r.message:String(r)}}}async findByProjectId(e){try{let{fields:t,tableName:o}=this.config,s=await fetch(`${this.getRestUrl(o)}?${t.projectId}=eq.${e}&limit=1`,{method:"GET",headers:{apikey:this.config.serviceRoleKey,Authorization:`Bearer ${this.config.serviceRoleKey}`,"Content-Type":"application/json"}});if(!s.ok)return null;let a=await s.json();return Array.isArray(a)&&a.length>0?a[0]:null}catch{return null}}};export{i as SupabaseProvider};