metadatafy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-ECKCIPM5.js +1329 -0
- package/dist/chunk-ECKCIPM5.js.map +1 -0
- package/dist/chunk-EDHWKZRG.cjs +1384 -0
- package/dist/chunk-EDHWKZRG.cjs.map +1 -0
- package/dist/cli.cjs +1478 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +1450 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +120 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +390 -0
- package/dist/index.d.ts +390 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/next.cjs +111 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +19 -0
- package/dist/next.d.ts +19 -0
- package/dist/next.js +86 -0
- package/dist/next.js.map +1 -0
- package/dist/types-DlsgsNoY.d.cts +127 -0
- package/dist/types-DlsgsNoY.d.ts +127 -0
- package/dist/vite.cjs +91 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +19 -0
- package/dist/vite.d.ts +19 -0
- package/dist/vite.js +66 -0
- package/dist/vite.js.map +1 -0
- package/package.json +74 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { P as PluginConfig, F as FileType, A as AnalysisResult, a as ParsedFile, I as ImportInfo, E as ExportInfo, b as PropInfo, C as CallGraphEntry } from './types-DlsgsNoY.js';
|
|
2
|
+
export { e as AnalysisStats, c as CodeIndexItem, d as CodeMetadata, O as OutputConfig, T as TableColumn } from './types-DlsgsNoY.js';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 기본 파일 타입 매핑 (glob 패턴 -> FileType)
|
|
7
|
+
*/
|
|
8
|
+
declare const DEFAULT_FILE_TYPE_MAPPING: Record<string, FileType>;
|
|
9
|
+
/**
|
|
10
|
+
* 기본 포함 패턴
|
|
11
|
+
*/
|
|
12
|
+
declare const DEFAULT_INCLUDE_PATTERNS: string[];
|
|
13
|
+
/**
|
|
14
|
+
* 기본 제외 패턴
|
|
15
|
+
*/
|
|
16
|
+
declare const DEFAULT_EXCLUDE_PATTERNS: string[];
|
|
17
|
+
/**
|
|
18
|
+
* 기본 설정으로 PluginConfig 생성
|
|
19
|
+
*/
|
|
20
|
+
declare function createDefaultConfig(overrides?: Partial<PluginConfig>): PluginConfig;
|
|
21
|
+
/**
|
|
22
|
+
* 설정 유효성 검증
|
|
23
|
+
*/
|
|
24
|
+
declare function validateConfig(config: PluginConfig): string[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 프로젝트 분석기 - 메인 오케스트레이터
|
|
28
|
+
*/
|
|
29
|
+
declare class ProjectAnalyzer {
|
|
30
|
+
private config;
|
|
31
|
+
private tsParser;
|
|
32
|
+
private sqlParser;
|
|
33
|
+
private importExtractor;
|
|
34
|
+
private exportExtractor;
|
|
35
|
+
private propsExtractor;
|
|
36
|
+
private keywordExtractor;
|
|
37
|
+
private callGraphBuilder;
|
|
38
|
+
constructor(config: PluginConfig);
|
|
39
|
+
/**
|
|
40
|
+
* 프로젝트 분석 실행
|
|
41
|
+
*/
|
|
42
|
+
analyze(rootDir: string): Promise<AnalysisResult>;
|
|
43
|
+
/**
|
|
44
|
+
* 대상 파일 수집
|
|
45
|
+
*/
|
|
46
|
+
private collectFiles;
|
|
47
|
+
/**
|
|
48
|
+
* 단일 파일 파싱
|
|
49
|
+
*/
|
|
50
|
+
private parseFile;
|
|
51
|
+
/**
|
|
52
|
+
* 파일 타입 결정
|
|
53
|
+
*/
|
|
54
|
+
private determineFileType;
|
|
55
|
+
/**
|
|
56
|
+
* 파일/컴포넌트 이름 추출
|
|
57
|
+
*/
|
|
58
|
+
private extractName;
|
|
59
|
+
/**
|
|
60
|
+
* CodeIndexItem 생성
|
|
61
|
+
*/
|
|
62
|
+
private createIndexItem;
|
|
63
|
+
/**
|
|
64
|
+
* 검색용 텍스트 생성
|
|
65
|
+
*/
|
|
66
|
+
private buildSearchText;
|
|
67
|
+
/**
|
|
68
|
+
* 분석 통계 계산
|
|
69
|
+
*/
|
|
70
|
+
private calculateStats;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* TypeScript AST 파서
|
|
75
|
+
*/
|
|
76
|
+
declare class TypeScriptParser {
|
|
77
|
+
private compilerOptions;
|
|
78
|
+
constructor();
|
|
79
|
+
/**
|
|
80
|
+
* 소스 코드를 AST로 파싱
|
|
81
|
+
*/
|
|
82
|
+
parse(content: string, filePath: string): ts.SourceFile;
|
|
83
|
+
/**
|
|
84
|
+
* 파일 확장자에 따른 ScriptKind 결정
|
|
85
|
+
*/
|
|
86
|
+
private getScriptKind;
|
|
87
|
+
/**
|
|
88
|
+
* AST 노드 순회
|
|
89
|
+
*/
|
|
90
|
+
traverse(node: ts.Node, visitor: (node: ts.Node) => void | boolean): void;
|
|
91
|
+
/**
|
|
92
|
+
* 특정 조건을 만족하는 노드 수집
|
|
93
|
+
*/
|
|
94
|
+
findNodes<T extends ts.Node>(sourceFile: ts.SourceFile, predicate: (node: ts.Node) => node is T): T[];
|
|
95
|
+
/**
|
|
96
|
+
* 노드의 텍스트 추출
|
|
97
|
+
*/
|
|
98
|
+
getNodeText(node: ts.Node, sourceFile: ts.SourceFile): string;
|
|
99
|
+
/**
|
|
100
|
+
* JSDoc 코멘트 추출
|
|
101
|
+
*/
|
|
102
|
+
getJSDocComment(node: ts.Node): string | undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* SQL 마이그레이션 파일 파서
|
|
107
|
+
*/
|
|
108
|
+
declare class SQLParser {
|
|
109
|
+
/**
|
|
110
|
+
* SQL 파일 파싱
|
|
111
|
+
*/
|
|
112
|
+
parse(content: string, relativePath: string): ParsedFile;
|
|
113
|
+
/**
|
|
114
|
+
* CREATE TABLE 문에서 테이블 정보 추출
|
|
115
|
+
*/
|
|
116
|
+
private extractTables;
|
|
117
|
+
/**
|
|
118
|
+
* 컬럼 정의 파싱
|
|
119
|
+
*/
|
|
120
|
+
private parseColumns;
|
|
121
|
+
/**
|
|
122
|
+
* 단일 컬럼 정의 파싱
|
|
123
|
+
*/
|
|
124
|
+
private parseColumnDefinition;
|
|
125
|
+
/**
|
|
126
|
+
* REFERENCES 절에서 참조 정보 추출
|
|
127
|
+
*/
|
|
128
|
+
private extractReference;
|
|
129
|
+
/**
|
|
130
|
+
* 파일 경로에서 테이블 이름 추출
|
|
131
|
+
*/
|
|
132
|
+
private extractNameFromPath;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* import 문에서 정보를 추출하는 클래스
|
|
137
|
+
*/
|
|
138
|
+
declare class ImportExtractor {
|
|
139
|
+
/**
|
|
140
|
+
* SourceFile에서 모든 import 정보 추출
|
|
141
|
+
*/
|
|
142
|
+
extract(sourceFile: ts.SourceFile): ImportInfo[];
|
|
143
|
+
/**
|
|
144
|
+
* ImportDeclaration 노드를 ImportInfo로 변환
|
|
145
|
+
*/
|
|
146
|
+
private parseImportDeclaration;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* export 문에서 정보를 추출하는 클래스
|
|
151
|
+
*/
|
|
152
|
+
declare class ExportExtractor {
|
|
153
|
+
/**
|
|
154
|
+
* SourceFile에서 모든 export 정보 추출
|
|
155
|
+
*/
|
|
156
|
+
extract(sourceFile: ts.SourceFile): ExportInfo[];
|
|
157
|
+
/**
|
|
158
|
+
* 노드에서 export 정보 추출
|
|
159
|
+
*/
|
|
160
|
+
private extractFromNode;
|
|
161
|
+
/**
|
|
162
|
+
* export 키워드가 있는지 확인
|
|
163
|
+
*/
|
|
164
|
+
private hasExportModifier;
|
|
165
|
+
/**
|
|
166
|
+
* default 키워드가 있는지 확인
|
|
167
|
+
*/
|
|
168
|
+
private hasDefaultModifier;
|
|
169
|
+
/**
|
|
170
|
+
* export default의 이름 추출
|
|
171
|
+
*/
|
|
172
|
+
private getExportDefaultName;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* React 컴포넌트의 Props 정보를 추출하는 클래스
|
|
177
|
+
*/
|
|
178
|
+
declare class PropsExtractor {
|
|
179
|
+
/**
|
|
180
|
+
* SourceFile에서 Props 정보 추출
|
|
181
|
+
*/
|
|
182
|
+
extract(sourceFile: ts.SourceFile): PropInfo[];
|
|
183
|
+
/**
|
|
184
|
+
* Props 타입 정의 찾기
|
|
185
|
+
*/
|
|
186
|
+
private findPropsType;
|
|
187
|
+
/**
|
|
188
|
+
* 컴포넌트 함수 찾기
|
|
189
|
+
*/
|
|
190
|
+
private findComponentFunction;
|
|
191
|
+
/**
|
|
192
|
+
* 타입 노드에서 Props 추출
|
|
193
|
+
*/
|
|
194
|
+
private extractFromTypeNode;
|
|
195
|
+
/**
|
|
196
|
+
* 타입 멤버에서 PropInfo 추출
|
|
197
|
+
*/
|
|
198
|
+
private extractMemberProp;
|
|
199
|
+
/**
|
|
200
|
+
* 함수 매개변수에서 Props 추출
|
|
201
|
+
*/
|
|
202
|
+
private extractFromFunctionParams;
|
|
203
|
+
/**
|
|
204
|
+
* export 키워드가 있는지 확인
|
|
205
|
+
*/
|
|
206
|
+
private isExported;
|
|
207
|
+
/**
|
|
208
|
+
* 중복 Props 제거
|
|
209
|
+
*/
|
|
210
|
+
private deduplicateProps;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 검색용 키워드를 추출하는 클래스
|
|
215
|
+
*/
|
|
216
|
+
declare class KeywordExtractor {
|
|
217
|
+
private customKoreanMap;
|
|
218
|
+
constructor(customKoreanMap?: Record<string, string[]>);
|
|
219
|
+
/**
|
|
220
|
+
* 다양한 소스에서 키워드 추출
|
|
221
|
+
*/
|
|
222
|
+
extract(name: string, path: string, exports?: string[], props?: string[]): string[];
|
|
223
|
+
/**
|
|
224
|
+
* 이름에서 키워드 추출
|
|
225
|
+
*/
|
|
226
|
+
private extractFromName;
|
|
227
|
+
/**
|
|
228
|
+
* 경로에서 키워드 추출
|
|
229
|
+
*/
|
|
230
|
+
private extractFromPath;
|
|
231
|
+
/**
|
|
232
|
+
* 영어 키워드에 대응하는 한글 키워드 찾기
|
|
233
|
+
*/
|
|
234
|
+
private findKorean;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* import 경로를 실제 파일 경로로 해석하는 클래스
|
|
239
|
+
*/
|
|
240
|
+
declare class DependencyResolver {
|
|
241
|
+
private aliasMap;
|
|
242
|
+
private extensions;
|
|
243
|
+
constructor(aliasMap?: Record<string, string>, extensions?: string[]);
|
|
244
|
+
/**
|
|
245
|
+
* import 경로를 실제 파일 경로로 해석
|
|
246
|
+
*/
|
|
247
|
+
resolve(importSource: string, importerPath: string, rootDir: string): string | null;
|
|
248
|
+
/**
|
|
249
|
+
* 외부 패키지인지 확인
|
|
250
|
+
*/
|
|
251
|
+
private isExternalPackage;
|
|
252
|
+
/**
|
|
253
|
+
* alias 해석
|
|
254
|
+
*/
|
|
255
|
+
private resolveAlias;
|
|
256
|
+
/**
|
|
257
|
+
* 확장자를 추가하여 파일 경로 해석
|
|
258
|
+
*/
|
|
259
|
+
private resolveWithExtensions;
|
|
260
|
+
/**
|
|
261
|
+
* 디렉토리에서 index 파일 찾기
|
|
262
|
+
*/
|
|
263
|
+
private findIndexFile;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 파일 간 호출 관계 그래프를 구축하는 클래스
|
|
268
|
+
*/
|
|
269
|
+
declare class CallGraphBuilder {
|
|
270
|
+
private resolver;
|
|
271
|
+
constructor(aliasMap?: Record<string, string>);
|
|
272
|
+
/**
|
|
273
|
+
* 파싱된 파일들로부터 호출 그래프 구축
|
|
274
|
+
*/
|
|
275
|
+
build(parsedFiles: ParsedFile[], rootDir: string): Map<string, CallGraphEntry>;
|
|
276
|
+
/**
|
|
277
|
+
* 파일이 호출하는 다른 파일들을 해석
|
|
278
|
+
*/
|
|
279
|
+
private resolveCalls;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 분석 결과를 JSON 파일로 출력하는 클래스
|
|
284
|
+
*/
|
|
285
|
+
declare class FileWriter {
|
|
286
|
+
private config;
|
|
287
|
+
constructor(config: PluginConfig);
|
|
288
|
+
/**
|
|
289
|
+
* 분석 결과를 파일로 저장
|
|
290
|
+
*/
|
|
291
|
+
write(result: AnalysisResult, outputPath: string): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* 출력 형식 생성
|
|
294
|
+
*/
|
|
295
|
+
private formatOutput;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
interface ApiSenderOptions {
|
|
299
|
+
maxRetries?: number;
|
|
300
|
+
retryDelay?: number;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 분석 결과를 API로 전송하는 클래스
|
|
304
|
+
*/
|
|
305
|
+
declare class ApiSender {
|
|
306
|
+
protected config: PluginConfig;
|
|
307
|
+
private maxRetries;
|
|
308
|
+
private retryDelay;
|
|
309
|
+
constructor(config: PluginConfig, options?: ApiSenderOptions);
|
|
310
|
+
/**
|
|
311
|
+
* 분석 결과를 API로 전송
|
|
312
|
+
*/
|
|
313
|
+
send(result: AnalysisResult): Promise<void>;
|
|
314
|
+
/**
|
|
315
|
+
* HTTP POST 요청
|
|
316
|
+
*/
|
|
317
|
+
private sendRequest;
|
|
318
|
+
/**
|
|
319
|
+
* 지연 함수
|
|
320
|
+
*/
|
|
321
|
+
private delay;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Supabase 특화 API Sender
|
|
325
|
+
*/
|
|
326
|
+
declare class SupabaseApiSender extends ApiSender {
|
|
327
|
+
/**
|
|
328
|
+
* Supabase upsert 형식으로 전송
|
|
329
|
+
*/
|
|
330
|
+
send(result: AnalysisResult): Promise<void>;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* camelCase를 분리
|
|
335
|
+
* 예: "attendanceCheck" -> ["attendance", "Check"]
|
|
336
|
+
*/
|
|
337
|
+
declare function splitCamelCase(str: string): string[];
|
|
338
|
+
/**
|
|
339
|
+
* PascalCase를 분리
|
|
340
|
+
* 예: "AttendanceCheckModal" -> ["Attendance", "Check", "Modal"]
|
|
341
|
+
*/
|
|
342
|
+
declare function splitPascalCase(str: string): string[];
|
|
343
|
+
/**
|
|
344
|
+
* snake_case를 분리
|
|
345
|
+
* 예: "attendance_check" -> ["attendance", "check"]
|
|
346
|
+
*/
|
|
347
|
+
declare function splitSnakeCase(str: string): string[];
|
|
348
|
+
/**
|
|
349
|
+
* kebab-case를 분리
|
|
350
|
+
* 예: "attendance-check" -> ["attendance", "check"]
|
|
351
|
+
*/
|
|
352
|
+
declare function splitKebabCase(str: string): string[];
|
|
353
|
+
/**
|
|
354
|
+
* 모든 케이스를 처리하여 단어 분리
|
|
355
|
+
*/
|
|
356
|
+
declare function splitIntoWords(str: string): string[];
|
|
357
|
+
/**
|
|
358
|
+
* 연속된 대문자(약어) 추출
|
|
359
|
+
* 예: "XMLHTTPRequest" -> ["XML", "HTTP"]
|
|
360
|
+
*/
|
|
361
|
+
declare function extractAcronyms(str: string): string[];
|
|
362
|
+
/**
|
|
363
|
+
* 문자열을 여러 형식으로 변환
|
|
364
|
+
*/
|
|
365
|
+
declare function toAllCases(str: string): {
|
|
366
|
+
camel: string;
|
|
367
|
+
pascal: string;
|
|
368
|
+
snake: string;
|
|
369
|
+
kebab: string;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* 기본 영한 키워드 매핑
|
|
374
|
+
*/
|
|
375
|
+
declare const KOREAN_KEYWORD_MAP: Record<string, string[]>;
|
|
376
|
+
/**
|
|
377
|
+
* 영어 키워드에 대응하는 한글 키워드 찾기
|
|
378
|
+
*/
|
|
379
|
+
declare function findKoreanKeywords(englishKeyword: string): string[];
|
|
380
|
+
/**
|
|
381
|
+
* 한글 키워드 매핑 확장
|
|
382
|
+
*/
|
|
383
|
+
declare function extendKoreanMap(customMap: Record<string, string[]>): Record<string, string[]>;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 프로젝트 ID와 파일 경로로 고유 ID 생성
|
|
387
|
+
*/
|
|
388
|
+
declare function generateId(projectId: string, filePath: string): string;
|
|
389
|
+
|
|
390
|
+
export { AnalysisResult, ApiSender, CallGraphBuilder, CallGraphEntry, DEFAULT_EXCLUDE_PATTERNS, DEFAULT_FILE_TYPE_MAPPING, DEFAULT_INCLUDE_PATTERNS, DependencyResolver, ExportExtractor, ExportInfo, FileType, FileWriter, ImportExtractor, ImportInfo, KOREAN_KEYWORD_MAP, KeywordExtractor, ParsedFile, PluginConfig, ProjectAnalyzer, PropInfo, PropsExtractor, SQLParser, SupabaseApiSender, TypeScriptParser, createDefaultConfig, extendKoreanMap, extractAcronyms, findKoreanKeywords, generateId, splitCamelCase, splitIntoWords, splitKebabCase, splitPascalCase, splitSnakeCase, toAllCases, validateConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ApiSender, CallGraphBuilder, DEFAULT_EXCLUDE_PATTERNS, DEFAULT_FILE_TYPE_MAPPING, DEFAULT_INCLUDE_PATTERNS, DependencyResolver, ExportExtractor, FileWriter, ImportExtractor, KOREAN_KEYWORD_MAP, KeywordExtractor, ProjectAnalyzer, PropsExtractor, SQLParser, SupabaseApiSender, TypeScriptParser, createDefaultConfig, extendKoreanMap, extractAcronyms, findKoreanKeywords, generateId, splitCamelCase, splitIntoWords, splitKebabCase, splitPascalCase, splitSnakeCase, toAllCases, validateConfig } from './chunk-ECKCIPM5.js';
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/next.cjs
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var chunkEDHWKZRG_cjs = require('./chunk-EDHWKZRG.cjs');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
27
|
+
|
|
28
|
+
function withMetadata(options = {}) {
|
|
29
|
+
const pluginConfig = chunkEDHWKZRG_cjs.createDefaultConfig(options);
|
|
30
|
+
const runOn = options.runOn || "build";
|
|
31
|
+
const errors = chunkEDHWKZRG_cjs.validateConfig(pluginConfig);
|
|
32
|
+
if (errors.length > 0) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`[metadata-plugin] Invalid config:
|
|
35
|
+
${errors.join("\n")}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return (nextConfig) => {
|
|
39
|
+
return {
|
|
40
|
+
...nextConfig,
|
|
41
|
+
webpack(config, context) {
|
|
42
|
+
const { dev, isServer } = context;
|
|
43
|
+
if (!isServer) {
|
|
44
|
+
return typeof nextConfig.webpack === "function" ? nextConfig.webpack(config, context) : config;
|
|
45
|
+
}
|
|
46
|
+
const shouldRun = runOn === "both" || runOn === "build" && !dev || runOn === "dev" && dev;
|
|
47
|
+
if (shouldRun) {
|
|
48
|
+
config.plugins = config.plugins || [];
|
|
49
|
+
config.plugins.push(new MetadataWebpackPlugin(pluginConfig));
|
|
50
|
+
}
|
|
51
|
+
if (typeof nextConfig.webpack === "function") {
|
|
52
|
+
return nextConfig.webpack(config, context);
|
|
53
|
+
}
|
|
54
|
+
return config;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
var MetadataWebpackPlugin = class {
|
|
60
|
+
constructor(config) {
|
|
61
|
+
this.hasRun = false;
|
|
62
|
+
this.config = config;
|
|
63
|
+
}
|
|
64
|
+
apply(compiler) {
|
|
65
|
+
const pluginName = "MetadataWebpackPlugin";
|
|
66
|
+
compiler.hooks.beforeCompile.tapAsync(
|
|
67
|
+
pluginName,
|
|
68
|
+
async (_params, callback) => {
|
|
69
|
+
if (this.hasRun) {
|
|
70
|
+
return callback();
|
|
71
|
+
}
|
|
72
|
+
this.hasRun = true;
|
|
73
|
+
try {
|
|
74
|
+
await this.runAnalysis(compiler.context);
|
|
75
|
+
callback();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
callback(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
compiler.hooks.watchRun.tap(pluginName, () => {
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async runAnalysis(rootDir) {
|
|
85
|
+
const analyzer = new chunkEDHWKZRG_cjs.ProjectAnalyzer(this.config);
|
|
86
|
+
const fileWriter = new chunkEDHWKZRG_cjs.FileWriter(this.config);
|
|
87
|
+
const apiSender = this.config.output.api?.enabled ? new chunkEDHWKZRG_cjs.ApiSender(this.config) : null;
|
|
88
|
+
if (this.config.verbose) {
|
|
89
|
+
console.log("[metadata-plugin] Starting analysis...");
|
|
90
|
+
}
|
|
91
|
+
const result = await analyzer.analyze(rootDir);
|
|
92
|
+
if (this.config.output.file?.enabled) {
|
|
93
|
+
const outputPath = path__namespace.resolve(rootDir, this.config.output.file.path);
|
|
94
|
+
await fileWriter.write(result, outputPath);
|
|
95
|
+
if (this.config.verbose) {
|
|
96
|
+
console.log(`[metadata-plugin] Wrote metadata to ${outputPath}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (apiSender) {
|
|
100
|
+
await apiSender.send(result);
|
|
101
|
+
if (this.config.verbose) {
|
|
102
|
+
console.log("[metadata-plugin] Sent metadata to API");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
exports.default = withMetadata;
|
|
109
|
+
exports.withMetadata = withMetadata;
|
|
110
|
+
//# sourceMappingURL=next.cjs.map
|
|
111
|
+
//# sourceMappingURL=next.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/next-adapter.ts"],"names":["createDefaultConfig","validateConfig","ProjectAnalyzer","FileWriter","ApiSender","path"],"mappings":"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","file":"next.cjs","sourcesContent":["import type { NextConfig } from 'next';\nimport type { Compiler, WebpackPluginInstance } from 'webpack';\nimport * as path from 'path';\nimport type { PluginConfig } from '../core/types';\nimport { ProjectAnalyzer } from '../core/analyzer';\nimport { createDefaultConfig, validateConfig } from '../core/config';\nimport { FileWriter } from '../core/output/file-writer';\nimport { ApiSender } from '../core/output/api-sender';\n\nexport interface NextPluginOptions extends Partial<PluginConfig> {\n /**\n * 분석 실행 시점\n * - 'build': 프로덕션 빌드 시에만 (기본값)\n * - 'dev': 개발 모드 시에만\n * - 'both': 둘 다\n */\n runOn?: 'build' | 'dev' | 'both';\n}\n\n/**\n * Next.js 설정을 확장하는 함수\n */\nexport function withMetadata(\n options: NextPluginOptions = {}\n): (nextConfig: NextConfig) => NextConfig {\n const pluginConfig = createDefaultConfig(options);\n const runOn = options.runOn || 'build';\n\n // 설정 검증\n const errors = validateConfig(pluginConfig);\n if (errors.length > 0) {\n throw new Error(\n `[metadata-plugin] Invalid config:\\n${errors.join('\\n')}`\n );\n }\n\n return (nextConfig: NextConfig): NextConfig => {\n return {\n ...nextConfig,\n\n webpack(config, context) {\n const { dev, isServer } = context;\n\n // 서버 사이드에서만 실행 (클라이언트 빌드에서 중복 실행 방지)\n if (!isServer) {\n return typeof nextConfig.webpack === 'function'\n ? nextConfig.webpack(config, context)\n : config;\n }\n\n const shouldRun =\n runOn === 'both' ||\n (runOn === 'build' && !dev) ||\n (runOn === 'dev' && dev);\n\n if (shouldRun) {\n config.plugins = config.plugins || [];\n config.plugins.push(new MetadataWebpackPlugin(pluginConfig));\n }\n\n // 기존 webpack 설정 체이닝\n if (typeof nextConfig.webpack === 'function') {\n return nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n };\n}\n\n/**\n * Webpack 플러그인 클래스\n */\nclass MetadataWebpackPlugin implements WebpackPluginInstance {\n private config: PluginConfig;\n private hasRun: boolean = false;\n\n constructor(config: PluginConfig) {\n this.config = config;\n }\n\n apply(compiler: Compiler): void {\n const pluginName = 'MetadataWebpackPlugin';\n\n // 컴파일 시작 시 분석 실행\n compiler.hooks.beforeCompile.tapAsync(\n pluginName,\n async (_params, callback) => {\n // 중복 실행 방지\n if (this.hasRun) {\n return callback();\n }\n this.hasRun = true;\n\n try {\n await this.runAnalysis(compiler.context);\n callback();\n } catch (error) {\n callback(error as Error);\n }\n }\n );\n\n // 개발 모드에서 watch 재빌드 시 플래그 리셋\n compiler.hooks.watchRun.tap(pluginName, () => {\n // 필요시 재분석 로직 추가\n });\n }\n\n private async runAnalysis(rootDir: string): Promise<void> {\n const analyzer = new ProjectAnalyzer(this.config);\n const fileWriter = new FileWriter(this.config);\n const apiSender = this.config.output.api?.enabled\n ? new ApiSender(this.config)\n : null;\n\n if (this.config.verbose) {\n console.log('[metadata-plugin] Starting analysis...');\n }\n\n const result = await analyzer.analyze(rootDir);\n\n // 파일 출력\n if (this.config.output.file?.enabled) {\n const outputPath = path.resolve(rootDir, this.config.output.file.path);\n await fileWriter.write(result, outputPath);\n\n if (this.config.verbose) {\n console.log(`[metadata-plugin] Wrote metadata to ${outputPath}`);\n }\n }\n\n // API 전송\n if (apiSender) {\n await apiSender.send(result);\n\n if (this.config.verbose) {\n console.log('[metadata-plugin] Sent metadata to API');\n }\n }\n }\n}\n"]}
|
package/dist/next.d.cts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
import { P as PluginConfig } from './types-DlsgsNoY.cjs';
|
|
3
|
+
export { A as AnalysisResult, c as CodeIndexItem } from './types-DlsgsNoY.cjs';
|
|
4
|
+
|
|
5
|
+
interface NextPluginOptions extends Partial<PluginConfig> {
|
|
6
|
+
/**
|
|
7
|
+
* 분석 실행 시점
|
|
8
|
+
* - 'build': 프로덕션 빌드 시에만 (기본값)
|
|
9
|
+
* - 'dev': 개발 모드 시에만
|
|
10
|
+
* - 'both': 둘 다
|
|
11
|
+
*/
|
|
12
|
+
runOn?: 'build' | 'dev' | 'both';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Next.js 설정을 확장하는 함수
|
|
16
|
+
*/
|
|
17
|
+
declare function withMetadata(options?: NextPluginOptions): (nextConfig: NextConfig) => NextConfig;
|
|
18
|
+
|
|
19
|
+
export { type NextPluginOptions, PluginConfig, withMetadata as default, withMetadata };
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
import { P as PluginConfig } from './types-DlsgsNoY.js';
|
|
3
|
+
export { A as AnalysisResult, c as CodeIndexItem } from './types-DlsgsNoY.js';
|
|
4
|
+
|
|
5
|
+
interface NextPluginOptions extends Partial<PluginConfig> {
|
|
6
|
+
/**
|
|
7
|
+
* 분석 실행 시점
|
|
8
|
+
* - 'build': 프로덕션 빌드 시에만 (기본값)
|
|
9
|
+
* - 'dev': 개발 모드 시에만
|
|
10
|
+
* - 'both': 둘 다
|
|
11
|
+
*/
|
|
12
|
+
runOn?: 'build' | 'dev' | 'both';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Next.js 설정을 확장하는 함수
|
|
16
|
+
*/
|
|
17
|
+
declare function withMetadata(options?: NextPluginOptions): (nextConfig: NextConfig) => NextConfig;
|
|
18
|
+
|
|
19
|
+
export { type NextPluginOptions, PluginConfig, withMetadata as default, withMetadata };
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createDefaultConfig, validateConfig, ProjectAnalyzer, FileWriter, ApiSender } from './chunk-ECKCIPM5.js';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
function withMetadata(options = {}) {
|
|
5
|
+
const pluginConfig = createDefaultConfig(options);
|
|
6
|
+
const runOn = options.runOn || "build";
|
|
7
|
+
const errors = validateConfig(pluginConfig);
|
|
8
|
+
if (errors.length > 0) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`[metadata-plugin] Invalid config:
|
|
11
|
+
${errors.join("\n")}`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return (nextConfig) => {
|
|
15
|
+
return {
|
|
16
|
+
...nextConfig,
|
|
17
|
+
webpack(config, context) {
|
|
18
|
+
const { dev, isServer } = context;
|
|
19
|
+
if (!isServer) {
|
|
20
|
+
return typeof nextConfig.webpack === "function" ? nextConfig.webpack(config, context) : config;
|
|
21
|
+
}
|
|
22
|
+
const shouldRun = runOn === "both" || runOn === "build" && !dev || runOn === "dev" && dev;
|
|
23
|
+
if (shouldRun) {
|
|
24
|
+
config.plugins = config.plugins || [];
|
|
25
|
+
config.plugins.push(new MetadataWebpackPlugin(pluginConfig));
|
|
26
|
+
}
|
|
27
|
+
if (typeof nextConfig.webpack === "function") {
|
|
28
|
+
return nextConfig.webpack(config, context);
|
|
29
|
+
}
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
var MetadataWebpackPlugin = class {
|
|
36
|
+
constructor(config) {
|
|
37
|
+
this.hasRun = false;
|
|
38
|
+
this.config = config;
|
|
39
|
+
}
|
|
40
|
+
apply(compiler) {
|
|
41
|
+
const pluginName = "MetadataWebpackPlugin";
|
|
42
|
+
compiler.hooks.beforeCompile.tapAsync(
|
|
43
|
+
pluginName,
|
|
44
|
+
async (_params, callback) => {
|
|
45
|
+
if (this.hasRun) {
|
|
46
|
+
return callback();
|
|
47
|
+
}
|
|
48
|
+
this.hasRun = true;
|
|
49
|
+
try {
|
|
50
|
+
await this.runAnalysis(compiler.context);
|
|
51
|
+
callback();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
callback(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
compiler.hooks.watchRun.tap(pluginName, () => {
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async runAnalysis(rootDir) {
|
|
61
|
+
const analyzer = new ProjectAnalyzer(this.config);
|
|
62
|
+
const fileWriter = new FileWriter(this.config);
|
|
63
|
+
const apiSender = this.config.output.api?.enabled ? new ApiSender(this.config) : null;
|
|
64
|
+
if (this.config.verbose) {
|
|
65
|
+
console.log("[metadata-plugin] Starting analysis...");
|
|
66
|
+
}
|
|
67
|
+
const result = await analyzer.analyze(rootDir);
|
|
68
|
+
if (this.config.output.file?.enabled) {
|
|
69
|
+
const outputPath = path.resolve(rootDir, this.config.output.file.path);
|
|
70
|
+
await fileWriter.write(result, outputPath);
|
|
71
|
+
if (this.config.verbose) {
|
|
72
|
+
console.log(`[metadata-plugin] Wrote metadata to ${outputPath}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (apiSender) {
|
|
76
|
+
await apiSender.send(result);
|
|
77
|
+
if (this.config.verbose) {
|
|
78
|
+
console.log("[metadata-plugin] Sent metadata to API");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { withMetadata as default, withMetadata };
|
|
85
|
+
//# sourceMappingURL=next.js.map
|
|
86
|
+
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/next-adapter.ts"],"names":[],"mappings":"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","file":"next.js","sourcesContent":["import type { NextConfig } from 'next';\nimport type { Compiler, WebpackPluginInstance } from 'webpack';\nimport * as path from 'path';\nimport type { PluginConfig } from '../core/types';\nimport { ProjectAnalyzer } from '../core/analyzer';\nimport { createDefaultConfig, validateConfig } from '../core/config';\nimport { FileWriter } from '../core/output/file-writer';\nimport { ApiSender } from '../core/output/api-sender';\n\nexport interface NextPluginOptions extends Partial<PluginConfig> {\n /**\n * 분석 실행 시점\n * - 'build': 프로덕션 빌드 시에만 (기본값)\n * - 'dev': 개발 모드 시에만\n * - 'both': 둘 다\n */\n runOn?: 'build' | 'dev' | 'both';\n}\n\n/**\n * Next.js 설정을 확장하는 함수\n */\nexport function withMetadata(\n options: NextPluginOptions = {}\n): (nextConfig: NextConfig) => NextConfig {\n const pluginConfig = createDefaultConfig(options);\n const runOn = options.runOn || 'build';\n\n // 설정 검증\n const errors = validateConfig(pluginConfig);\n if (errors.length > 0) {\n throw new Error(\n `[metadata-plugin] Invalid config:\\n${errors.join('\\n')}`\n );\n }\n\n return (nextConfig: NextConfig): NextConfig => {\n return {\n ...nextConfig,\n\n webpack(config, context) {\n const { dev, isServer } = context;\n\n // 서버 사이드에서만 실행 (클라이언트 빌드에서 중복 실행 방지)\n if (!isServer) {\n return typeof nextConfig.webpack === 'function'\n ? nextConfig.webpack(config, context)\n : config;\n }\n\n const shouldRun =\n runOn === 'both' ||\n (runOn === 'build' && !dev) ||\n (runOn === 'dev' && dev);\n\n if (shouldRun) {\n config.plugins = config.plugins || [];\n config.plugins.push(new MetadataWebpackPlugin(pluginConfig));\n }\n\n // 기존 webpack 설정 체이닝\n if (typeof nextConfig.webpack === 'function') {\n return nextConfig.webpack(config, context);\n }\n\n return config;\n },\n };\n };\n}\n\n/**\n * Webpack 플러그인 클래스\n */\nclass MetadataWebpackPlugin implements WebpackPluginInstance {\n private config: PluginConfig;\n private hasRun: boolean = false;\n\n constructor(config: PluginConfig) {\n this.config = config;\n }\n\n apply(compiler: Compiler): void {\n const pluginName = 'MetadataWebpackPlugin';\n\n // 컴파일 시작 시 분석 실행\n compiler.hooks.beforeCompile.tapAsync(\n pluginName,\n async (_params, callback) => {\n // 중복 실행 방지\n if (this.hasRun) {\n return callback();\n }\n this.hasRun = true;\n\n try {\n await this.runAnalysis(compiler.context);\n callback();\n } catch (error) {\n callback(error as Error);\n }\n }\n );\n\n // 개발 모드에서 watch 재빌드 시 플래그 리셋\n compiler.hooks.watchRun.tap(pluginName, () => {\n // 필요시 재분석 로직 추가\n });\n }\n\n private async runAnalysis(rootDir: string): Promise<void> {\n const analyzer = new ProjectAnalyzer(this.config);\n const fileWriter = new FileWriter(this.config);\n const apiSender = this.config.output.api?.enabled\n ? new ApiSender(this.config)\n : null;\n\n if (this.config.verbose) {\n console.log('[metadata-plugin] Starting analysis...');\n }\n\n const result = await analyzer.analyze(rootDir);\n\n // 파일 출력\n if (this.config.output.file?.enabled) {\n const outputPath = path.resolve(rootDir, this.config.output.file.path);\n await fileWriter.write(result, outputPath);\n\n if (this.config.verbose) {\n console.log(`[metadata-plugin] Wrote metadata to ${outputPath}`);\n }\n }\n\n // API 전송\n if (apiSender) {\n await apiSender.send(result);\n\n if (this.config.verbose) {\n console.log('[metadata-plugin] Sent metadata to API');\n }\n }\n }\n}\n"]}
|