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 +198 -220
- package/dist/{chunk-ESZLTJIF.js → chunk-7VGYPCY7.js} +1 -1
- package/dist/{chunk-XR3EVOXW.cjs → chunk-W2STEULD.cjs} +1 -1
- package/dist/cli.cjs +7 -7
- package/dist/cli.js +4 -4
- package/dist/next.cjs +1 -1
- package/dist/next.js +1 -1
- package/dist/supabase-ODLVMAF6.cjs +1 -0
- package/dist/supabase-QJ4W7OH5.js +1 -0
- package/dist/vite.cjs +1 -1
- package/dist/vite.js +1 -1
- package/package.json +1 -1
- package/dist/supabase-HWODZTEI.cjs +0 -1
- package/dist/supabase-TGVJDKHE.js +0 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
263
|
-
"enabled":
|
|
264
|
-
"
|
|
265
|
-
"
|
|
266
|
-
"
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
320
|
+
metadatafy stores each file as an individual row for better queryability:
|
|
397
321
|
|
|
398
|
-
|
|
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
|
-
|
|
403
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
431
|
-
// next.config.ts
|
|
432
|
-
import { withMetadata } from 'metadatafy/next';
|
|
377
|
+
### Configuration / 설정
|
|
433
378
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
|
|
481
|
-
- **빌드 시 자동 업로드**: Vite/Next.js 플러그인에 Supabase 설정이 있으면 빌드마다 자동 업로드됩니다.
|
|
482
|
-
- **CLI 지원**: `npx metadatafy analyze --upload`로 DB에 업로드합니다.
|
|
408
|
+
---
|
|
483
409
|
|
|
484
|
-
|
|
410
|
+
1. **기존 프로젝트 데이터 삭제** - 동일한 `project_id`의 모든 row 삭제
|
|
411
|
+
2. **새 데이터 일괄 삽입** - 500개 단위로 모든 파일 삽입
|
|
412
|
+
3. **분석 로그 기록** - `code_analysis_log` 테이블에 통계 기록
|
|
413
|
+
|
|
414
|
+
### Querying Code / 코드 쿼리 예시
|
|
485
415
|
|
|
486
|
-
|
|
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
|
-
|
|
436
|
+
### Recommended Workflow / 권장 워크플로우
|
|
489
437
|
|
|
490
438
|
```bash
|
|
491
|
-
#
|
|
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
|
|
500
|
-
|
|
501
|
-
npx metadatafy upload
|
|
442
|
+
# Or in CI/CD
|
|
443
|
+
npx metadatafy analyze --upload
|
|
502
444
|
```
|
|
503
445
|
|
|
504
|
-
**
|
|
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-
|
|
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-
|
|
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
|
|
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){
|
|
7
|
-
\u{1F527}
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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){
|
|
7
|
-
\u{1F527}
|
|
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
|
|
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-
|
|
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
|
|
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-
|
|
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 +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};
|