aiwf 0.3.2 → 0.3.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.
Files changed (214) hide show
  1. package/.aiwf/config/language.json +1 -1
  2. package/.aiwf/installed.flag +1 -0
  3. package/.aiwf/sessions/session_1752877859489_1t7n2fhdb.json +7 -0
  4. package/.aiwf/sessions/session_1752877859515_cwdv211ry.json +7 -0
  5. package/.aiwf/sessions/session_1752877860664_huziadmbo.json +7 -0
  6. package/.aiwf/sessions/session_1752877860666_kyr5u1np6.json +7 -0
  7. package/.aiwf/sessions/session_1752877861848_9yinepw3t.json +7 -0
  8. package/.aiwf/sessions/session_1752877861874_y32sputuc.json +7 -0
  9. package/.aiwf/sessions/session_1752877862685_ivxbl5rhz.json +7 -0
  10. package/.aiwf/sessions/session_1752877862820_wnq4glvxi.json +7 -0
  11. package/.aiwf/sessions/session_1752877864632_3ebnpaelb.json +7 -0
  12. package/.aiwf/sessions/session_1752877864879_b9zgjcb7d.json +7 -0
  13. package/.aiwf/sessions/session_1752877865533_x14m1vodi.json +7 -0
  14. package/.aiwf/sessions/session_1752877865562_gkoh19n7d.json +7 -0
  15. package/.aiwf/sessions/session_1752877866333_wp8qpdcoh.json +7 -0
  16. package/.aiwf/sessions/session_1752877866509_dawntfpab.json +7 -0
  17. package/.aiwf/sessions/session_1752877866890_plc5vfucl.json +7 -0
  18. package/.aiwf/sessions/session_1752877866895_ga8hmq3oi.json +7 -0
  19. package/.aiwf/sessions/session_1752877867761_ayjp4v5f5.json +7 -0
  20. package/.aiwf/sessions/session_1752877867892_lfz6jy252.json +7 -0
  21. package/.aiwf/sessions/session_1752877868139_7bqd9ubli.json +7 -0
  22. package/.aiwf/sessions/session_1752877868162_zq3ofjbsh.json +7 -0
  23. package/.aiwf/sessions/session_1752877869054_7rlgm9jt6.json +7 -0
  24. package/.aiwf/sessions/session_1752877869477_ax3nhbxzr.json +7 -0
  25. package/.aiwf/sessions/session_1752877870095_6hgp4vl1e.json +7 -0
  26. package/.aiwf/sessions/session_1752877870381_qfcrdg4li.json +7 -0
  27. package/.aiwf/sessions/session_1752877871895_pgd5vllhz.json +7 -0
  28. package/.aiwf/sessions/session_1752877872199_jbhv2g2da.json +7 -0
  29. package/.aiwf/sessions/session_1752877872680_x04wpffu6.json +7 -0
  30. package/.aiwf/sessions/session_1752877872895_3y4vbeauo.json +7 -0
  31. package/.aiwf/sessions/session_1752877873178_3maolzc6b.json +7 -0
  32. package/.aiwf/sessions/session_1752877873180_ytm83j07f.json +7 -0
  33. package/.aiwf/sessions/session_1752877874217_dp56c9t42.json +7 -0
  34. package/.aiwf/sessions/session_1752877874415_epwp1g1og.json +7 -0
  35. package/.aiwf/sessions/session_1752877874454_heicyuryb.json +7 -0
  36. package/.aiwf/sessions/session_1752877874869_1c2illeu5.json +7 -0
  37. package/.aiwf/sessions/session_1752877874879_k1vo4vxyx.json +7 -0
  38. package/.aiwf/sessions/session_1752877874913_bwgyiz9bp.json +7 -0
  39. package/.aiwf/sessions/session_1752877876218_44807kztz.json +7 -0
  40. package/.aiwf/sessions/session_1752877876515_qkhjv5kpw.json +7 -0
  41. package/.aiwf/sessions/session_1752877876543_p605aud1m.json +7 -0
  42. package/.aiwf/sessions/session_1752877876819_l65w7ifck.json +7 -0
  43. package/.aiwf/sessions/session_1752877876867_xrhzss4we.json +7 -0
  44. package/.aiwf/sessions/session_1752877876872_u7aso54qb.json +7 -0
  45. package/.aiwf/sessions/session_1752877877705_telnfg4o6.json +7 -0
  46. package/.aiwf/sessions/session_1752877878285_6s45im2ib.json +7 -0
  47. package/.aiwf/sessions/session_1752877878506_v0dvguqhz.json +7 -0
  48. package/.aiwf/sessions/session_1752877878581_3ri3yc66a.json +7 -0
  49. package/.aiwf/sessions/session_1752877878756_a82x9s2pd.json +7 -0
  50. package/.aiwf/sessions/session_1752877878886_20pjsfour.json +7 -0
  51. package/.aiwf/sessions/session_1752877880266_fm1ydjw0g.json +7 -0
  52. package/.aiwf/sessions/session_1752877881149_xbat4z03d.json +7 -0
  53. package/.aiwf/sessions/session_1752877881551_qy5sic9qs.json +7 -0
  54. package/.aiwf/sessions/session_1752877881554_24ugd96wu.json +7 -0
  55. package/.aiwf/sessions/session_1752877881797_e9mm25uh0.json +7 -0
  56. package/.aiwf/sessions/session_1752877881822_bxvjj8c9g.json +7 -0
  57. package/.aiwf/sessions/session_1752877881890_jv7l6jve3.json +7 -0
  58. package/.aiwf/sessions/session_1752877881991_f0qugdtcq.json +7 -0
  59. package/.aiwf/sessions/session_1752877883387_0bvw9rvnx.json +7 -0
  60. package/.aiwf/sessions/session_1752877883820_q6g2md2up.json +7 -0
  61. package/.aiwf/sessions/session_1752877884393_sqr7trvjl.json +7 -0
  62. package/.aiwf/sessions/session_1752877884500_whtypmzlf.json +7 -0
  63. package/.aiwf/sessions/session_1752877884645_y9mvvxli1.json +7 -0
  64. package/.aiwf/sessions/session_1752877884733_hk46eenel.json +7 -0
  65. package/.aiwf/sessions/session_1752877884738_c62j6214r.json +7 -0
  66. package/.aiwf/sessions/session_1752877884771_temhxehoz.json +7 -0
  67. package/.aiwf/sessions/session_1752877885643_6v5fcktc7.json +7 -0
  68. package/.aiwf/sessions/session_1752877886426_ee8di2fqh.json +7 -0
  69. package/.aiwf/sessions/session_1752877886549_3xj6tdoew.json +7 -0
  70. package/.aiwf/sessions/session_1752877886604_aj80yyfco.json +7 -0
  71. package/.aiwf/sessions/session_1752877886702_2b8841vyg.json +7 -0
  72. package/.aiwf/sessions/session_1752877886712_ntqc8b8bz.json +7 -0
  73. package/.aiwf/sessions/session_1752877886968_946m8tbw6.json +7 -0
  74. package/.aiwf/sessions/session_1752877887008_wg6zfg8dn.json +7 -0
  75. package/.aiwf/sessions/session_1752877888479_ciiu2qiqs.json +7 -0
  76. package/.aiwf/sessions/session_1752877889330_ravg8l66k.json +7 -0
  77. package/.aiwf/sessions/session_1752877889542_7zepkhjkc.json +7 -0
  78. package/.aiwf/sessions/session_1752877889638_ev4htqiu0.json +7 -0
  79. package/.aiwf/sessions/session_1752877889956_szphy2qma.json +7 -0
  80. package/.aiwf/sessions/session_1752877890220_o6aaa57tt.json +7 -0
  81. package/.aiwf/sessions/session_1752877890527_v2loy5vu1.json +7 -0
  82. package/.aiwf/sessions/session_1752877890572_cwq8fiuma.json +7 -0
  83. package/.aiwf/sessions/session_1752877892200_sgcwq1alt.json +7 -0
  84. package/.aiwf/sessions/session_1752877892268_v8kexpbc5.json +7 -0
  85. package/.aiwf/sessions/session_1752877892384_1gbbgrp4y.json +7 -0
  86. package/.aiwf/sessions/session_1752877893568_9p2n5p31a.json +7 -0
  87. package/.aiwf/sessions/session_1752877893727_un34a5tvp.json +7 -0
  88. package/.aiwf/sessions/session_1752877893778_01j79sw9i.json +7 -0
  89. package/.aiwf/sessions/session_1752877894053_jrhba6wko.json +7 -0
  90. package/.aiwf/sessions/session_1752877894082_x3bghawox.json +7 -0
  91. package/.aiwf/sessions/session_1752877894500_iytiav2ku.json +7 -0
  92. package/.aiwf/sessions/session_1752877894667_ucn0gc2ge.json +7 -0
  93. package/.aiwf/test-results-s02.json +4 -4
  94. package/.claude/commands/aiwf/aiwf_changelog.md +82 -0
  95. package/.claude/commands/aiwf/aiwf_code_review.md +88 -0
  96. package/.claude/commands/aiwf/aiwf_commit.md +160 -0
  97. package/.claude/commands/aiwf/aiwf_compress_context.md +116 -0
  98. package/.claude/commands/aiwf/aiwf_create_feature_ledger.md +54 -0
  99. package/.claude/commands/aiwf/aiwf_create_general_task.md +147 -0
  100. package/.claude/commands/aiwf/aiwf_create_milestone_plan.md +194 -0
  101. package/.claude/commands/aiwf/aiwf_create_prd.md +280 -0
  102. package/.claude/commands/aiwf/aiwf_create_sprint_tasks.md +189 -0
  103. package/.claude/commands/aiwf/aiwf_create_sprints_from_milestone.md +121 -0
  104. package/.claude/commands/aiwf/aiwf_default_mode.md +44 -0
  105. package/.claude/commands/aiwf/aiwf_discuss_review.md +29 -0
  106. package/.claude/commands/aiwf/aiwf_do_task.md +109 -0
  107. package/.claude/commands/aiwf/aiwf_docs.md +225 -0
  108. package/.claude/commands/aiwf/aiwf_get_feature_details.md +78 -0
  109. package/.claude/commands/aiwf/aiwf_infinite.md +202 -0
  110. package/.claude/commands/aiwf/aiwf_initialize.md +134 -0
  111. package/.claude/commands/aiwf/aiwf_issue_create.md +65 -0
  112. package/.claude/commands/aiwf/aiwf_link_feature_to_milestone.md +57 -0
  113. package/.claude/commands/aiwf/aiwf_list_features.md +54 -0
  114. package/.claude/commands/aiwf/aiwf_mermaid.md +272 -0
  115. package/.claude/commands/aiwf/aiwf_persona_architect.md +48 -0
  116. package/.claude/commands/aiwf/aiwf_persona_backend.md +37 -0
  117. package/.claude/commands/aiwf/aiwf_persona_data_analyst.md +37 -0
  118. package/.claude/commands/aiwf/aiwf_persona_frontend.md +37 -0
  119. package/.claude/commands/aiwf/aiwf_persona_security.md +48 -0
  120. package/.claude/commands/aiwf/aiwf_persona_status.md +50 -0
  121. package/.claude/commands/aiwf/aiwf_pr_create.md +76 -0
  122. package/.claude/commands/aiwf/aiwf_prime.md +9 -0
  123. package/.claude/commands/aiwf/aiwf_project_review.md +261 -0
  124. package/.claude/commands/aiwf/aiwf_switch_language.md +160 -0
  125. package/.claude/commands/aiwf/aiwf_test.md +124 -0
  126. package/.claude/commands/aiwf/aiwf_testing_review.md +198 -0
  127. package/.claude/commands/aiwf/aiwf_tm-run-all-subtask.md +210 -0
  128. package/.claude/commands/aiwf/aiwf_ultrathink_code_advanced.md +460 -0
  129. package/.claude/commands/aiwf/aiwf_ultrathink_code_basic.md +165 -0
  130. package/.claude/commands/aiwf/aiwf_ultrathink_general.md +305 -0
  131. package/.claude/commands/aiwf/aiwf_update_docs_kr.md +25 -0
  132. package/.claude/commands/aiwf/aiwf_update_feature_status.md +53 -0
  133. package/.claude/commands/aiwf/aiwf_yolo.md +300 -0
  134. package/.eslintrc.json +26 -0
  135. package/.prettierrc +10 -0
  136. package/CLAUDE.md +154 -54
  137. package/README.ko.md +25 -0
  138. package/README.md +25 -0
  139. package/TEST_RECOVERY_PLAN.md +68 -0
  140. package/docs/CLEANUP_RECOMMENDATIONS.md +86 -0
  141. package/docs/CLI_USAGE_GUIDE.md +479 -0
  142. package/package.json +9 -9
  143. package/scripts/update-feature-status.js +70 -0
  144. package/{lib → src/cli}/cache-cli.js +4 -4
  145. package/src/cli/index.js +165 -0
  146. package/{language-cli.js → src/cli/language-cli.js} +11 -4
  147. package/src/commands/cache-templates.js +209 -0
  148. package/src/commands/create-offline.js +86 -0
  149. package/src/commands/create-project.js +151 -0
  150. package/src/lib/backup-manager.js +270 -0
  151. package/src/lib/file-downloader.js +208 -0
  152. package/src/lib/installer.js +676 -0
  153. package/src/lib/rollback-manager.js +418 -0
  154. package/src/lib/validator.js +561 -0
  155. package/src/utils/git-integration.js +173 -0
  156. package/{language-utils.js → src/utils/language-utils.js} +2 -1
  157. package/src/utils/messages.js +136 -0
  158. package/src/utils/paths.js +130 -0
  159. package/tests/application.test.js +2 -2
  160. package/tests/installer.test.js +2 -2
  161. package/tests/integration/ai-persona-system.test.js +4 -4
  162. package/tests/integration/test-persona-system/docs/README.md +1 -0
  163. package/tests/integration/test-persona-system/package.json +1 -0
  164. package/tests/integration/test-persona-system/src/auth.js +1 -0
  165. package/tests/integration/test-persona-system/src/index.js +1 -0
  166. package/tests/integration/test-persona-system/test/test.js +1 -0
  167. package/tests/language-utils.test.js +1 -1
  168. package/tests/temp_invalid_json/invalid.json +1 -0
  169. package/tests/unit/ai-persona-manager.test.js +7 -7
  170. package/.aiwf/05_DOCUMENTATION/performance-report.md +0 -33
  171. package/.aiwf/test-cache/86c7f9e80251abb8bedd58953ab0d1779e46b4f43ea33b63bffdb778106373b0.json +0 -6
  172. package/.aiwf/test-cache/9e252a90b80fce0585d7ed0646e7a9b4343e109f661f42a3ae678ba1ec5e22c7.json +0 -7
  173. package/.aiwf/token-data/alerts.json +0 -293
  174. package/.aiwf/token-data/monitor-config.json +0 -12
  175. package/CHANGELOG_M02.md +0 -52
  176. package/claude-code/aiwf/ko/bin/aiwf-create.js +0 -56
  177. package/claude-code/aiwf/ko/bin/aiwf.js +0 -21
  178. package/claude-code/aiwf/ko/docs/00_PROJECT_MANIFEST.md +0 -183
  179. package/claude-code/aiwf/ko/docs/ARCHITECTURE.md +0 -121
  180. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_ADVANCED_USE_CASES.md +0 -412
  181. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_API_REFERENCE.md +0 -361
  182. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_COMMANDS_GUIDE.md +0 -254
  183. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_FAQ.md +0 -365
  184. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_SYSTEM_OVERVIEW.md +0 -305
  185. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_USER_GUIDE.md +0 -416
  186. package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_/354/213/234/354/236/221_/352/260/200/354/235/264/353/223/234.md +0 -247
  187. package/claude-code/aiwf/ko/token-data/alerts.json +0 -293
  188. package/claude-code/aiwf/ko/token-data/monitor-config.json +0 -12
  189. package/docs/m02-dod-checklist.md +0 -125
  190. package/docs/m02-gap-analysis.md +0 -214
  191. package/docs/m02-milestone-completion-report.md +0 -186
  192. package/docs/m02-milestone-executive-summary.md +0 -68
  193. package/index.js +0 -1947
  194. package/lib/cache-integration.js +0 -401
  195. package/lib/file-batch-processor.js +0 -401
  196. package/lib/performance-benchmark.js +0 -621
  197. package/lib/template-manager.js +0 -310
  198. package/scripts/validate-commands.cjs +0 -338
  199. /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_aggressive_persona.md +0 -0
  200. /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_minimal_persona.md +0 -0
  201. /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_stats.md +0 -0
  202. /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_with_persona.md +0 -0
  203. /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_evaluate.md +0 -0
  204. /package/{lib → src/lib}/ai-persona-manager.js +0 -0
  205. /package/{lib → src/lib}/cache-system.js +0 -0
  206. /package/{lib → src/lib}/context-engine.js +0 -0
  207. /package/{lib → src/lib}/memory-profiler.js +0 -0
  208. /package/{lib → src/lib}/metrics-collector.js +0 -0
  209. /package/{lib → src/lib}/offline-detector.js +0 -0
  210. /package/{lib → src/lib}/task-analyzer.js +0 -0
  211. /package/{lib → src/lib}/template-cache-system.js +0 -0
  212. /package/{lib → src/lib}/template-downloader.js +0 -0
  213. /package/{lib → src/lib}/template-version-manager.js +0 -0
  214. /package/{lib → src/lib}/token-optimizer.js +0 -0
@@ -1,401 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'fs/promises';
4
- import path from 'path';
5
- import { Worker } from 'worker_threads';
6
- import { pipeline } from 'stream/promises';
7
- import { createReadStream, createWriteStream } from 'fs';
8
-
9
- /**
10
- * 파일 시스템 작업 배치 처리 시스템
11
- * - 파일 읽기/쓰기 작업을 배치로 처리
12
- * - 병렬 처리를 통한 성능 향상
13
- * - 메모리 사용량 최적화
14
- */
15
- class FileBatchProcessor {
16
- constructor(options = {}) {
17
- this.maxConcurrency = options.maxConcurrency || 10;
18
- this.batchSize = options.batchSize || 50;
19
- this.queue = [];
20
- this.processing = false;
21
- this.workers = new Map();
22
- this.stats = {
23
- totalOperations: 0,
24
- successfulOperations: 0,
25
- failedOperations: 0,
26
- averageProcessingTime: 0,
27
- memoryUsage: 0
28
- };
29
- }
30
-
31
- // 파일 읽기 작업 추가
32
- addReadOperation(filePath, options = {}) {
33
- return new Promise((resolve, reject) => {
34
- this.queue.push({
35
- type: 'read',
36
- filePath,
37
- options,
38
- resolve,
39
- reject,
40
- timestamp: Date.now()
41
- });
42
- this.processQueue();
43
- });
44
- }
45
-
46
- // 파일 쓰기 작업 추가
47
- addWriteOperation(filePath, content, options = {}) {
48
- return new Promise((resolve, reject) => {
49
- this.queue.push({
50
- type: 'write',
51
- filePath,
52
- content,
53
- options,
54
- resolve,
55
- reject,
56
- timestamp: Date.now()
57
- });
58
- this.processQueue();
59
- });
60
- }
61
-
62
- // 파일 복사 작업 추가
63
- addCopyOperation(source, destination, options = {}) {
64
- return new Promise((resolve, reject) => {
65
- this.queue.push({
66
- type: 'copy',
67
- source,
68
- destination,
69
- options,
70
- resolve,
71
- reject,
72
- timestamp: Date.now()
73
- });
74
- this.processQueue();
75
- });
76
- }
77
-
78
- // 디렉토리 생성 작업 추가
79
- addMkdirOperation(dirPath, options = {}) {
80
- return new Promise((resolve, reject) => {
81
- this.queue.push({
82
- type: 'mkdir',
83
- dirPath,
84
- options,
85
- resolve,
86
- reject,
87
- timestamp: Date.now()
88
- });
89
- this.processQueue();
90
- });
91
- }
92
-
93
- // 큐 처리
94
- async processQueue() {
95
- if (this.processing || this.queue.length === 0) {
96
- return;
97
- }
98
-
99
- this.processing = true;
100
-
101
- try {
102
- while (this.queue.length > 0) {
103
- const batch = this.queue.splice(0, this.batchSize);
104
- await this.processBatch(batch);
105
- }
106
- } catch (error) {
107
- console.error('Batch processing error:', error);
108
- } finally {
109
- this.processing = false;
110
- }
111
- }
112
-
113
- // 배치 처리
114
- async processBatch(batch) {
115
- const startTime = Date.now();
116
- const concurrencyLimit = Math.min(this.maxConcurrency, batch.length);
117
-
118
- // 작업 타입별로 그룹핑
119
- const groupedOperations = this.groupOperationsByType(batch);
120
-
121
- // 각 타입별로 병렬 처리
122
- for (const [type, operations] of Object.entries(groupedOperations)) {
123
- await this.processOperationsInParallel(operations, concurrencyLimit);
124
- }
125
-
126
- const endTime = Date.now();
127
- this.updateStats(batch.length, endTime - startTime);
128
- }
129
-
130
- // 작업 타입별 그룹핑
131
- groupOperationsByType(operations) {
132
- const grouped = {};
133
-
134
- for (const operation of operations) {
135
- if (!grouped[operation.type]) {
136
- grouped[operation.type] = [];
137
- }
138
- grouped[operation.type].push(operation);
139
- }
140
-
141
- return grouped;
142
- }
143
-
144
- // 병렬 처리
145
- async processOperationsInParallel(operations, concurrencyLimit) {
146
- const semaphore = new Semaphore(concurrencyLimit);
147
-
148
- const promises = operations.map(async (operation) => {
149
- await semaphore.acquire();
150
-
151
- try {
152
- const result = await this.executeOperation(operation);
153
- operation.resolve(result);
154
- this.stats.successfulOperations++;
155
- } catch (error) {
156
- operation.reject(error);
157
- this.stats.failedOperations++;
158
- } finally {
159
- semaphore.release();
160
- }
161
- });
162
-
163
- await Promise.all(promises);
164
- }
165
-
166
- // 개별 작업 실행
167
- async executeOperation(operation) {
168
- const startTime = Date.now();
169
-
170
- try {
171
- let result;
172
-
173
- switch (operation.type) {
174
- case 'read':
175
- result = await this.readFile(operation.filePath, operation.options);
176
- break;
177
- case 'write':
178
- result = await this.writeFile(operation.filePath, operation.content, operation.options);
179
- break;
180
- case 'copy':
181
- result = await this.copyFile(operation.source, operation.destination, operation.options);
182
- break;
183
- case 'mkdir':
184
- result = await this.createDirectory(operation.dirPath, operation.options);
185
- break;
186
- default:
187
- throw new Error(`Unknown operation type: ${operation.type}`);
188
- }
189
-
190
- return result;
191
- } catch (error) {
192
- throw error;
193
- }
194
- }
195
-
196
- // 파일 읽기 (최적화된)
197
- async readFile(filePath, options = {}) {
198
- const stats = await fs.stat(filePath);
199
-
200
- // 큰 파일은 스트리밍으로 처리
201
- if (stats.size > 10 * 1024 * 1024) { // 10MB 이상
202
- return await this.readFileStreaming(filePath, options);
203
- }
204
-
205
- return await fs.readFile(filePath, options.encoding || 'utf8');
206
- }
207
-
208
- // 스트리밍 파일 읽기
209
- async readFileStreaming(filePath, options = {}) {
210
- const chunks = [];
211
- const readStream = createReadStream(filePath, options);
212
-
213
- return new Promise((resolve, reject) => {
214
- readStream.on('data', chunk => chunks.push(chunk));
215
- readStream.on('end', () => resolve(Buffer.concat(chunks).toString()));
216
- readStream.on('error', reject);
217
- });
218
- }
219
-
220
- // 파일 쓰기 (최적화된)
221
- async writeFile(filePath, content, options = {}) {
222
- // 디렉토리 생성
223
- const dirPath = path.dirname(filePath);
224
- await fs.mkdir(dirPath, { recursive: true });
225
-
226
- // 큰 콘텐츠는 스트리밍으로 처리
227
- if (content.length > 10 * 1024 * 1024) { // 10MB 이상
228
- return await this.writeFileStreaming(filePath, content, options);
229
- }
230
-
231
- return await fs.writeFile(filePath, content, options.encoding || 'utf8');
232
- }
233
-
234
- // 스트리밍 파일 쓰기
235
- async writeFileStreaming(filePath, content, options = {}) {
236
- const writeStream = createWriteStream(filePath, options);
237
-
238
- return new Promise((resolve, reject) => {
239
- writeStream.write(content, options.encoding || 'utf8');
240
- writeStream.end();
241
- writeStream.on('finish', resolve);
242
- writeStream.on('error', reject);
243
- });
244
- }
245
-
246
- // 파일 복사 (최적화된)
247
- async copyFile(source, destination, options = {}) {
248
- const destDir = path.dirname(destination);
249
- await fs.mkdir(destDir, { recursive: true });
250
-
251
- // 큰 파일은 스트리밍으로 복사
252
- const stats = await fs.stat(source);
253
- if (stats.size > 10 * 1024 * 1024) { // 10MB 이상
254
- return await this.copyFileStreaming(source, destination, options);
255
- }
256
-
257
- return await fs.copyFile(source, destination);
258
- }
259
-
260
- // 스트리밍 파일 복사
261
- async copyFileStreaming(source, destination, options = {}) {
262
- const readStream = createReadStream(source, options);
263
- const writeStream = createWriteStream(destination, options);
264
-
265
- return await pipeline(readStream, writeStream);
266
- }
267
-
268
- // 디렉토리 생성
269
- async createDirectory(dirPath, options = {}) {
270
- return await fs.mkdir(dirPath, { recursive: true, ...options });
271
- }
272
-
273
- // 통계 업데이트
274
- updateStats(operationCount, processingTime) {
275
- this.stats.totalOperations += operationCount;
276
- this.stats.averageProcessingTime = (
277
- (this.stats.averageProcessingTime * (this.stats.totalOperations - operationCount) + processingTime) /
278
- this.stats.totalOperations
279
- );
280
- this.stats.memoryUsage = process.memoryUsage().heapUsed;
281
- }
282
-
283
- // 통계 정보
284
- getStats() {
285
- return {
286
- ...this.stats,
287
- queueLength: this.queue.length,
288
- isProcessing: this.processing,
289
- successRate: this.stats.totalOperations > 0 ?
290
- (this.stats.successfulOperations / this.stats.totalOperations * 100).toFixed(2) + '%' : '0%'
291
- };
292
- }
293
-
294
- // 큐 정리
295
- clearQueue() {
296
- this.queue.forEach(operation => {
297
- operation.reject(new Error('Queue cleared'));
298
- });
299
- this.queue = [];
300
- }
301
-
302
- // 배치 처리 대기
303
- async waitForCompletion() {
304
- while (this.processing || this.queue.length > 0) {
305
- await new Promise(resolve => setTimeout(resolve, 100));
306
- }
307
- }
308
- }
309
-
310
- // 세마포어 클래스 (동시성 제어)
311
- class Semaphore {
312
- constructor(capacity) {
313
- this.capacity = capacity;
314
- this.current = 0;
315
- this.queue = [];
316
- }
317
-
318
- async acquire() {
319
- if (this.current < this.capacity) {
320
- this.current++;
321
- return;
322
- }
323
-
324
- return new Promise(resolve => {
325
- this.queue.push(resolve);
326
- });
327
- }
328
-
329
- release() {
330
- this.current--;
331
- if (this.queue.length > 0) {
332
- this.current++;
333
- const resolve = this.queue.shift();
334
- resolve();
335
- }
336
- }
337
- }
338
-
339
- // 파일 작업 유틸리티
340
- class FileUtils {
341
- static async readMultipleFiles(filePaths, processor) {
342
- const results = {};
343
-
344
- for (const filePath of filePaths) {
345
- try {
346
- results[filePath] = await processor.addReadOperation(filePath);
347
- } catch (error) {
348
- results[filePath] = { error: error.message };
349
- }
350
- }
351
-
352
- return results;
353
- }
354
-
355
- static async writeMultipleFiles(fileData, processor) {
356
- const results = {};
357
-
358
- for (const [filePath, content] of Object.entries(fileData)) {
359
- try {
360
- await processor.addWriteOperation(filePath, content);
361
- results[filePath] = { success: true };
362
- } catch (error) {
363
- results[filePath] = { error: error.message };
364
- }
365
- }
366
-
367
- return results;
368
- }
369
-
370
- static async copyMultipleFiles(fileMappings, processor) {
371
- const results = {};
372
-
373
- for (const [source, destination] of Object.entries(fileMappings)) {
374
- try {
375
- await processor.addCopyOperation(source, destination);
376
- results[source] = { success: true, destination };
377
- } catch (error) {
378
- results[source] = { error: error.message };
379
- }
380
- }
381
-
382
- return results;
383
- }
384
-
385
- static async createDirectories(dirPaths, processor) {
386
- const results = {};
387
-
388
- for (const dirPath of dirPaths) {
389
- try {
390
- await processor.addMkdirOperation(dirPath);
391
- results[dirPath] = { success: true };
392
- } catch (error) {
393
- results[dirPath] = { error: error.message };
394
- }
395
- }
396
-
397
- return results;
398
- }
399
- }
400
-
401
- export { FileBatchProcessor, FileUtils, Semaphore };