jtcsv 2.2.8 → 3.1.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.
Files changed (246) hide show
  1. package/README.md +204 -115
  2. package/bin/jtcsv.ts +2612 -0
  3. package/browser.d.ts +142 -0
  4. package/dist/benchmark.js +446 -0
  5. package/dist/benchmark.js.map +1 -0
  6. package/dist/bin/jtcsv.js +1940 -0
  7. package/dist/bin/jtcsv.js.map +1 -0
  8. package/dist/csv-to-json.js +1262 -0
  9. package/dist/csv-to-json.js.map +1 -0
  10. package/dist/errors.js +291 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/eslint.config.js +147 -0
  13. package/dist/eslint.config.js.map +1 -0
  14. package/dist/index-core.js +95 -0
  15. package/dist/index-core.js.map +1 -0
  16. package/dist/index.js +93 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/json-save.js +229 -0
  19. package/dist/json-save.js.map +1 -0
  20. package/dist/json-to-csv.js +576 -0
  21. package/dist/json-to-csv.js.map +1 -0
  22. package/dist/jtcsv-core.cjs.js +1736 -0
  23. package/dist/jtcsv-core.cjs.js.map +1 -0
  24. package/dist/jtcsv-core.esm.js +1708 -0
  25. package/dist/jtcsv-core.esm.js.map +1 -0
  26. package/dist/jtcsv-core.umd.js +1742 -0
  27. package/dist/jtcsv-core.umd.js.map +1 -0
  28. package/dist/jtcsv-full.cjs.js +2241 -0
  29. package/dist/jtcsv-full.cjs.js.map +1 -0
  30. package/dist/jtcsv-full.esm.js +2209 -0
  31. package/dist/jtcsv-full.esm.js.map +1 -0
  32. package/dist/jtcsv-full.umd.js +2247 -0
  33. package/dist/jtcsv-full.umd.js.map +1 -0
  34. package/dist/jtcsv-workers.esm.js +768 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -0
  36. package/dist/jtcsv-workers.umd.js +782 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -0
  38. package/dist/jtcsv.cjs.js +1996 -2048
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1992 -2048
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2209
  43. package/dist/jtcsv.umd.js.map +1 -1
  44. package/dist/plugins/express-middleware/index.js +350 -0
  45. package/dist/plugins/express-middleware/index.js.map +1 -0
  46. package/dist/plugins/fastify-plugin/index.js +315 -0
  47. package/dist/plugins/fastify-plugin/index.js.map +1 -0
  48. package/dist/plugins/hono/index.js +111 -0
  49. package/dist/plugins/hono/index.js.map +1 -0
  50. package/dist/plugins/nestjs/index.js +112 -0
  51. package/dist/plugins/nestjs/index.js.map +1 -0
  52. package/dist/plugins/nuxt/index.js +53 -0
  53. package/dist/plugins/nuxt/index.js.map +1 -0
  54. package/dist/plugins/remix/index.js +133 -0
  55. package/dist/plugins/remix/index.js.map +1 -0
  56. package/dist/plugins/sveltekit/index.js +155 -0
  57. package/dist/plugins/sveltekit/index.js.map +1 -0
  58. package/dist/plugins/trpc/index.js +136 -0
  59. package/dist/plugins/trpc/index.js.map +1 -0
  60. package/dist/run-demo.js +49 -0
  61. package/dist/run-demo.js.map +1 -0
  62. package/dist/src/browser/browser-functions.js +193 -0
  63. package/dist/src/browser/browser-functions.js.map +1 -0
  64. package/dist/src/browser/core.js +123 -0
  65. package/dist/src/browser/core.js.map +1 -0
  66. package/dist/src/browser/csv-to-json-browser.js +353 -0
  67. package/dist/src/browser/csv-to-json-browser.js.map +1 -0
  68. package/dist/src/browser/errors-browser.js +219 -0
  69. package/dist/src/browser/errors-browser.js.map +1 -0
  70. package/dist/src/browser/extensions/plugins.js +106 -0
  71. package/dist/src/browser/extensions/plugins.js.map +1 -0
  72. package/dist/src/browser/extensions/workers.js +66 -0
  73. package/dist/src/browser/extensions/workers.js.map +1 -0
  74. package/dist/src/browser/index.js +140 -0
  75. package/dist/src/browser/index.js.map +1 -0
  76. package/dist/src/browser/json-to-csv-browser.js +225 -0
  77. package/dist/src/browser/json-to-csv-browser.js.map +1 -0
  78. package/dist/src/browser/streams.js +340 -0
  79. package/dist/src/browser/streams.js.map +1 -0
  80. package/dist/src/browser/workers/csv-parser.worker.js +264 -0
  81. package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
  82. package/dist/src/browser/workers/worker-pool.js +338 -0
  83. package/dist/src/browser/workers/worker-pool.js.map +1 -0
  84. package/dist/src/core/delimiter-cache.js +196 -0
  85. package/dist/src/core/delimiter-cache.js.map +1 -0
  86. package/dist/src/core/node-optimizations.js +279 -0
  87. package/dist/src/core/node-optimizations.js.map +1 -0
  88. package/dist/src/core/plugin-system.js +399 -0
  89. package/dist/src/core/plugin-system.js.map +1 -0
  90. package/dist/src/core/transform-hooks.js +348 -0
  91. package/dist/src/core/transform-hooks.js.map +1 -0
  92. package/dist/src/engines/fast-path-engine-new.js +262 -0
  93. package/dist/src/engines/fast-path-engine-new.js.map +1 -0
  94. package/dist/src/engines/fast-path-engine.js +671 -0
  95. package/dist/src/engines/fast-path-engine.js.map +1 -0
  96. package/dist/src/errors.js +18 -0
  97. package/dist/src/errors.js.map +1 -0
  98. package/dist/src/formats/ndjson-parser.js +332 -0
  99. package/dist/src/formats/ndjson-parser.js.map +1 -0
  100. package/dist/src/formats/tsv-parser.js +230 -0
  101. package/dist/src/formats/tsv-parser.js.map +1 -0
  102. package/dist/src/index-with-plugins.js +259 -0
  103. package/dist/src/index-with-plugins.js.map +1 -0
  104. package/dist/src/types/index.js +3 -0
  105. package/dist/src/types/index.js.map +1 -0
  106. package/dist/src/utils/bom-utils.js +267 -0
  107. package/dist/src/utils/bom-utils.js.map +1 -0
  108. package/dist/src/utils/encoding-support.js +77 -0
  109. package/dist/src/utils/encoding-support.js.map +1 -0
  110. package/dist/src/utils/schema-validator.js +609 -0
  111. package/dist/src/utils/schema-validator.js.map +1 -0
  112. package/dist/src/utils/transform-loader.js +281 -0
  113. package/dist/src/utils/transform-loader.js.map +1 -0
  114. package/dist/src/utils/validators.js +40 -0
  115. package/dist/src/utils/validators.js.map +1 -0
  116. package/dist/src/utils/zod-adapter.js +144 -0
  117. package/dist/src/utils/zod-adapter.js.map +1 -0
  118. package/dist/src/web-server/index.js +648 -0
  119. package/dist/src/web-server/index.js.map +1 -0
  120. package/dist/src/workers/csv-multithreaded.js +211 -0
  121. package/dist/src/workers/csv-multithreaded.js.map +1 -0
  122. package/dist/src/workers/csv-parser.worker.js +179 -0
  123. package/dist/src/workers/csv-parser.worker.js.map +1 -0
  124. package/dist/src/workers/worker-pool.js +228 -0
  125. package/dist/src/workers/worker-pool.js.map +1 -0
  126. package/dist/stream-csv-to-json.js +665 -0
  127. package/dist/stream-csv-to-json.js.map +1 -0
  128. package/dist/stream-json-to-csv.js +389 -0
  129. package/dist/stream-json-to-csv.js.map +1 -0
  130. package/examples/advanced/conditional-transformations.ts +446 -0
  131. package/examples/advanced/csv-parser.worker.ts +89 -0
  132. package/examples/advanced/nested-objects-example.ts +306 -0
  133. package/examples/advanced/performance-optimization.ts +504 -0
  134. package/examples/advanced/run-demo-server.ts +116 -0
  135. package/examples/advanced/web-worker-usage.html +874 -0
  136. package/examples/async-multithreaded-example.ts +335 -0
  137. package/examples/cli-advanced-usage.md +290 -0
  138. package/examples/{cli-batch-processing.js → cli-batch-processing.ts} +38 -38
  139. package/examples/{cli-tool.js → cli-tool.ts} +5 -8
  140. package/examples/{error-handling.js → error-handling.ts} +356 -324
  141. package/examples/{express-api.js → express-api.ts} +161 -164
  142. package/examples/{large-dataset-example.js → large-dataset-example.ts} +201 -182
  143. package/examples/{ndjson-processing.js → ndjson-processing.ts} +456 -434
  144. package/examples/{plugin-excel-exporter.js → plugin-excel-exporter.ts} +6 -7
  145. package/examples/react-integration.tsx +637 -0
  146. package/examples/{schema-validation.js → schema-validation.ts} +2 -2
  147. package/examples/simple-usage.ts +194 -0
  148. package/examples/{streaming-example.js → streaming-example.ts} +12 -12
  149. package/index.d.ts +187 -18
  150. package/package.json +75 -81
  151. package/plugins.d.ts +37 -0
  152. package/schema.d.ts +103 -0
  153. package/src/browser/browser-functions.ts +402 -0
  154. package/src/browser/core.ts +152 -0
  155. package/src/browser/csv-to-json-browser.d.ts +3 -0
  156. package/src/browser/csv-to-json-browser.ts +494 -0
  157. package/src/browser/{errors-browser.js → errors-browser.ts} +305 -197
  158. package/src/browser/extensions/plugins.ts +93 -0
  159. package/src/browser/extensions/workers.ts +39 -0
  160. package/src/browser/globals.d.ts +5 -0
  161. package/src/browser/index.ts +192 -0
  162. package/src/browser/json-to-csv-browser.d.ts +3 -0
  163. package/src/browser/json-to-csv-browser.ts +338 -0
  164. package/src/browser/streams.ts +403 -0
  165. package/src/browser/workers/{csv-parser.worker.js → csv-parser.worker.ts} +3 -3
  166. package/src/browser/workers/{worker-pool.js → worker-pool.ts} +51 -30
  167. package/src/core/delimiter-cache.ts +320 -0
  168. package/src/core/{node-optimizations.js → node-optimizations.ts} +448 -407
  169. package/src/core/plugin-system.ts +588 -0
  170. package/src/core/transform-hooks.ts +566 -0
  171. package/src/engines/{fast-path-engine-new.js → fast-path-engine-new.ts} +11 -2
  172. package/src/engines/{fast-path-engine.js → fast-path-engine.ts} +79 -53
  173. package/src/errors.ts +1 -0
  174. package/src/formats/{ndjson-parser.js → ndjson-parser.ts} +24 -16
  175. package/src/formats/{tsv-parser.js → tsv-parser.ts} +18 -17
  176. package/src/{index-with-plugins.js → index-with-plugins.ts} +381 -357
  177. package/src/types/index.ts +275 -0
  178. package/src/utils/bom-utils.ts +373 -0
  179. package/src/utils/encoding-support.ts +155 -0
  180. package/src/utils/{schema-validator.js → schema-validator.ts} +814 -589
  181. package/src/utils/transform-loader.ts +389 -0
  182. package/src/utils/validators.ts +35 -0
  183. package/src/utils/zod-adapter.ts +280 -0
  184. package/src/web-server/{index.js → index.ts} +19 -19
  185. package/src/workers/csv-multithreaded.ts +310 -0
  186. package/src/workers/csv-parser.worker.ts +227 -0
  187. package/src/workers/worker-pool.ts +409 -0
  188. package/bin/jtcsv.js +0 -2462
  189. package/csv-to-json.js +0 -688
  190. package/errors.js +0 -208
  191. package/examples/simple-usage.js +0 -282
  192. package/index.js +0 -68
  193. package/json-save.js +0 -254
  194. package/json-to-csv.js +0 -526
  195. package/plugins/README.md +0 -91
  196. package/plugins/express-middleware/README.md +0 -64
  197. package/plugins/express-middleware/example.js +0 -136
  198. package/plugins/express-middleware/index.d.ts +0 -114
  199. package/plugins/express-middleware/index.js +0 -360
  200. package/plugins/express-middleware/package.json +0 -52
  201. package/plugins/fastify-plugin/index.js +0 -406
  202. package/plugins/fastify-plugin/package.json +0 -55
  203. package/plugins/hono/README.md +0 -28
  204. package/plugins/hono/index.d.ts +0 -12
  205. package/plugins/hono/index.js +0 -36
  206. package/plugins/hono/package.json +0 -35
  207. package/plugins/nestjs/README.md +0 -35
  208. package/plugins/nestjs/index.d.ts +0 -25
  209. package/plugins/nestjs/index.js +0 -77
  210. package/plugins/nestjs/package.json +0 -37
  211. package/plugins/nextjs-api/README.md +0 -57
  212. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  213. package/plugins/nextjs-api/examples/api-convert.js +0 -69
  214. package/plugins/nextjs-api/index.js +0 -387
  215. package/plugins/nextjs-api/package.json +0 -63
  216. package/plugins/nextjs-api/route.js +0 -371
  217. package/plugins/nuxt/README.md +0 -24
  218. package/plugins/nuxt/index.js +0 -21
  219. package/plugins/nuxt/package.json +0 -35
  220. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  221. package/plugins/nuxt/runtime/plugin.js +0 -6
  222. package/plugins/remix/README.md +0 -26
  223. package/plugins/remix/index.d.ts +0 -16
  224. package/plugins/remix/index.js +0 -62
  225. package/plugins/remix/package.json +0 -35
  226. package/plugins/sveltekit/README.md +0 -28
  227. package/plugins/sveltekit/index.d.ts +0 -17
  228. package/plugins/sveltekit/index.js +0 -54
  229. package/plugins/sveltekit/package.json +0 -33
  230. package/plugins/trpc/README.md +0 -25
  231. package/plugins/trpc/index.d.ts +0 -7
  232. package/plugins/trpc/index.js +0 -32
  233. package/plugins/trpc/package.json +0 -34
  234. package/src/browser/browser-functions.js +0 -219
  235. package/src/browser/csv-to-json-browser.js +0 -700
  236. package/src/browser/index.js +0 -113
  237. package/src/browser/json-to-csv-browser.js +0 -309
  238. package/src/browser/streams.js +0 -393
  239. package/src/core/delimiter-cache.js +0 -186
  240. package/src/core/plugin-system.js +0 -476
  241. package/src/core/transform-hooks.js +0 -350
  242. package/src/errors.js +0 -26
  243. package/src/utils/transform-loader.js +0 -205
  244. package/stream-csv-to-json.js +0 -542
  245. package/stream-json-to-csv.js +0 -464
  246. /package/examples/{web-workers-advanced.js → web-workers-advanced.ts} +0 -0
@@ -1,476 +0,0 @@
1
- /**
2
- * Plugin System для JTCSV
3
- * Middleware-like архитектура с поддержкой hooks и плагинов
4
- *
5
- * @version 1.0.0
6
- * @date 2026-01-22
7
- */
8
-
9
- class PluginManager {
10
- constructor() {
11
- this.plugins = new Map();
12
- this.hooks = new Map();
13
- this.middlewares = [];
14
- this.context = {};
15
- this.stats = {
16
- pluginLoads: 0,
17
- hookExecutions: 0,
18
- middlewareExecutions: 0
19
- };
20
-
21
- // Регистрируем стандартные hooks
22
- this._registerDefaultHooks();
23
- }
24
-
25
- /**
26
- * Регистрирует стандартные hooks
27
- */
28
- _registerDefaultHooks() {
29
- const defaultHooks = [
30
- 'before:csvToJson',
31
- 'after:csvToJson',
32
- 'before:jsonToCsv',
33
- 'after:jsonToCsv',
34
- 'before:parse',
35
- 'after:parse',
36
- 'before:serialize',
37
- 'after:serialize',
38
- 'error',
39
- 'validation',
40
- 'transformation'
41
- ];
42
-
43
- defaultHooks.forEach(hook => {
44
- this.hooks.set(hook, []);
45
- });
46
- }
47
-
48
- /**
49
- * Регистрирует плагин
50
- * @param {string} name - Уникальное имя плагина
51
- * @param {Object} plugin - Конфигурация плагина
52
- * @returns {PluginManager} this для chaining
53
- *
54
- * @example
55
- * pluginManager.use('excel-exporter', {
56
- * name: 'Excel Exporter',
57
- * version: '1.0.0',
58
- * description: 'Экспорт в Excel формат',
59
- * hooks: {
60
- * 'after:jsonToCsv': (csv) => convertToExcel(csv)
61
- * },
62
- * middlewares: [
63
- * async (ctx, next) => {
64
- * console.log('Before conversion:', ctx);
65
- * await next();
66
- * console.log('After conversion:', ctx);
67
- * }
68
- * ]
69
- * });
70
- */
71
- use(name, plugin) {
72
- if (this.plugins.has(name)) {
73
- throw new Error(`Plugin "${name}" уже зарегистрирован`);
74
- }
75
-
76
- this._validatePlugin(plugin);
77
-
78
- // Сохраняем плагин
79
- this.plugins.set(name, {
80
- ...plugin,
81
- registeredAt: new Date(),
82
- enabled: true
83
- });
84
-
85
- // Регистрируем hooks
86
- if (plugin.hooks) {
87
- Object.entries(plugin.hooks).forEach(([hookName, handler]) => {
88
- this.registerHook(hookName, handler, name);
89
- });
90
- }
91
-
92
- // Регистрируем middlewares
93
- if (plugin.middlewares) {
94
- plugin.middlewares.forEach((middleware, index) => {
95
- this.registerMiddleware(middleware, `${name}:${index}`);
96
- });
97
- }
98
-
99
- this.stats.pluginLoads++;
100
- console.log(`✅ Plugin "${name}" зарегистрирован`);
101
- return this;
102
- }
103
-
104
- /**
105
- * Валидирует плагин
106
- */
107
- _validatePlugin(plugin) {
108
- if (!plugin.name || !plugin.version) {
109
- throw new Error('Plugin должен иметь name и version');
110
- }
111
-
112
- // Проверяем обязательные поля
113
- const required = ['name', 'version'];
114
- required.forEach(field => {
115
- /* istanbul ignore next */
116
- if (!plugin[field]) {
117
- /* istanbul ignore next */
118
- throw new Error(`Plugin missing required field: ${field}`);
119
- }
120
- });
121
-
122
- // Проверяем hooks если есть
123
- if (plugin.hooks) {
124
- if (typeof plugin.hooks !== 'object') {
125
- throw new Error('Plugin hooks должен быть объектом');
126
- }
127
-
128
- Object.entries(plugin.hooks).forEach(([hookName, handler]) => {
129
- if (typeof handler !== 'function') {
130
- throw new Error(`Hook handler для "${hookName}" должен быть функцией`);
131
- }
132
- });
133
- }
134
-
135
- // Проверяем middlewares если есть
136
- if (plugin.middlewares) {
137
- if (!Array.isArray(plugin.middlewares)) {
138
- throw new Error('Plugin middlewares должен быть массивом');
139
- }
140
-
141
- plugin.middlewares.forEach((middleware, index) => {
142
- if (typeof middleware !== 'function') {
143
- throw new Error(`Middleware ${index} должен быть функцией`);
144
- }
145
- });
146
- }
147
- }
148
-
149
- /**
150
- * Регистрирует hook
151
- * @param {string} hookName - Имя hook
152
- * @param {Function} handler - Обработчик hook
153
- * @param {string} pluginName - Имя плагина (опционально)
154
- */
155
- registerHook(hookName, handler, pluginName = null) {
156
- if (!this.hooks.has(hookName)) {
157
- this.hooks.set(hookName, []);
158
- }
159
-
160
- this.hooks.get(hookName).push({
161
- handler,
162
- pluginName,
163
- registeredAt: new Date()
164
- });
165
-
166
- console.log(`📌 Hook "${hookName}" зарегистрирован${pluginName ? ` для плагина "${pluginName}"` : ''}`);
167
- }
168
-
169
- /**
170
- * Регистрирует middleware
171
- * @param {Function} middleware - Middleware функция
172
- * @param {string} name - Имя middleware (опционально)
173
- */
174
- registerMiddleware(middleware, name = null) {
175
- this.middlewares.push({
176
- middleware,
177
- name,
178
- registeredAt: new Date()
179
- });
180
-
181
- console.log(`🔄 Middleware "${name || 'anonymous'}" зарегистрирован`);
182
- }
183
-
184
- /**
185
- * Выполняет все handlers для конкретного hook
186
- * @param {string} hookName - Имя hook
187
- * @param {any} data - Данные для обработки
188
- * @param {Object} context - Контекст выполнения
189
- * @returns {Promise<any>} Результат обработки
190
- */
191
- async executeHooks(hookName, data, context = {}) {
192
- const handlers = this.hooks.get(hookName) || [];
193
-
194
- if (handlers.length === 0) {
195
- return data;
196
- }
197
-
198
- console.log(`⚡ Выполнение hook "${hookName}" с ${handlers.length} обработчиками`);
199
-
200
- let result = data;
201
-
202
- for (const { handler, pluginName } of handlers) {
203
- try {
204
- const startTime = Date.now();
205
- result = await handler(result, { ...context, pluginName });
206
- const duration = Date.now() - startTime;
207
-
208
- if (duration > 100) {
209
- console.warn(`⚠️ Hook "${hookName}" от плагина "${pluginName}" выполнился за ${duration}ms`);
210
- }
211
- } catch (error) {
212
- console.error(`❌ Ошибка в hook "${hookName}" от плагина "${pluginName}":`, error.message);
213
-
214
- // Выполняем error hook если есть
215
- await this.executeHooks('error', {
216
- hook: hookName,
217
- plugin: pluginName,
218
- error,
219
- data: result
220
- }, context);
221
-
222
- // Продолжаем выполнение с другими обработчиками
223
- continue;
224
- }
225
- }
226
-
227
- this.stats.hookExecutions++;
228
- return result;
229
- }
230
-
231
- /**
232
- * Выполняет middleware pipeline
233
- * @param {Object} ctx - Контекст выполнения
234
- * @returns {Promise<Object>} Обработанный контекст
235
- */
236
- async executeMiddlewares(ctx) {
237
- if (this.middlewares.length === 0) {
238
- return ctx;
239
- }
240
-
241
- console.log(`🚀 Запуск middleware pipeline с ${this.middlewares.length} middleware`);
242
-
243
- let index = -1;
244
- const middlewares = this.middlewares.map(m => m.middleware);
245
-
246
- const dispatch = async (i) => {
247
- if (i <= index) {
248
- throw new Error('next() вызван несколько раз');
249
- }
250
-
251
- index = i;
252
- const middleware = middlewares[i];
253
-
254
- if (!middleware) {
255
- return ctx;
256
- }
257
-
258
- try {
259
- const startTime = Date.now();
260
- await middleware(ctx, () => dispatch(i + 1));
261
- const duration = Date.now() - startTime;
262
-
263
- if (duration > 50) {
264
- console.warn(`⚠️ Middleware ${i} выполнился за ${duration}ms`);
265
- }
266
- } catch (error) {
267
- console.error(`❌ Ошибка в middleware ${i}:`, error.message);
268
-
269
- // Выполняем error hook
270
- await this.executeHooks('error', {
271
- middleware: i,
272
- error,
273
- context: ctx
274
- }, ctx);
275
-
276
- throw error;
277
- }
278
- };
279
-
280
- await dispatch(0);
281
- this.stats.middlewareExecutions++;
282
- return ctx;
283
- }
284
-
285
- /**
286
- * Создает контекст для операции
287
- * @param {string} operation - Тип операции
288
- * @param {any} input - Входные данные
289
- * @param {Object} options - Опции
290
- * @returns {Object} Контекст
291
- */
292
- /* istanbul ignore next */
293
- createContext(operation, input, options = {}) {
294
- return {
295
- operation,
296
- input,
297
- options,
298
- startTime: Date.now(),
299
- metadata: {
300
- version: '1.0.0',
301
- timestamp: new Date().toISOString(),
302
- ...options.metadata
303
- },
304
- state: {},
305
- result: null,
306
- errors: [],
307
- warnings: []
308
- };
309
- }
310
-
311
- /**
312
- * Выполняет операцию с поддержкой плагинов
313
- * @param {string} operation - Тип операции
314
- * @param {any} input - Входные данные
315
- * @param {Object} options - Опции
316
- * @param {Function} coreFunction - Основная функция
317
- * @returns {Promise<any>} Результат
318
- */
319
- async executeWithPlugins(operation, input, options, coreFunction) {
320
- // Создаем контекст
321
- const ctx = this.createContext(operation, input, options);
322
-
323
- try {
324
- // Выполняем before hooks
325
- ctx.input = await this.executeHooks(`before:${operation}`, ctx.input, ctx);
326
-
327
- // Выполняем middlewares
328
- await this.executeMiddlewares(ctx);
329
-
330
- // Выполняем основную функцию
331
- ctx.result = await coreFunction(ctx.input, ctx.options);
332
-
333
- // Выполняем after hooks
334
- ctx.result = await this.executeHooks(`after:${operation}`, ctx.result, ctx);
335
-
336
- // Записываем время выполнения
337
- ctx.duration = Date.now() - ctx.startTime;
338
-
339
- // Логируем успешное выполнение
340
- console.log(`✅ Операция "${operation}" выполнена за ${ctx.duration}ms`);
341
-
342
- return ctx.result;
343
- } catch (error) {
344
- // Записываем ошибку
345
- ctx.errors.push(error);
346
- ctx.duration = Date.now() - ctx.startTime;
347
-
348
- // Выполняем error hooks
349
- await this.executeHooks('error', {
350
- operation,
351
- error,
352
- context: ctx
353
- }, ctx);
354
-
355
- console.error(`❌ Ошибка в операции "${operation}":`, error.message);
356
- throw error;
357
- }
358
- }
359
-
360
- /**
361
- * Возвращает список всех зарегистрированных плагинов
362
- * @returns {Array} Список плагинов
363
- */
364
- listPlugins() {
365
- return Array.from(this.plugins.entries()).map(([name, plugin]) => ({
366
- name,
367
- pluginName: plugin.name,
368
- version: plugin.version,
369
- description: plugin.description || '',
370
- enabled: plugin.enabled,
371
- registeredAt: plugin.registeredAt,
372
- hooks: Object.keys(plugin.hooks || {}).length,
373
- middlewares: (plugin.middlewares || []).length
374
- }));
375
- }
376
-
377
- /**
378
- * Возвращает список всех hooks
379
- * @returns {Object} Статистика hooks
380
- */
381
- listHooks() {
382
- const result = {};
383
-
384
- for (const [hookName, handlers] of this.hooks.entries()) {
385
- result[hookName] = {
386
- count: handlers.length,
387
- handlers: handlers.map(h => ({
388
- pluginName: h.pluginName,
389
- registeredAt: h.registeredAt
390
- }))
391
- };
392
- }
393
-
394
- return result;
395
- }
396
-
397
- /**
398
- * Включает/выключает плагин
399
- * @param {string} pluginName - Имя плагина
400
- * @param {boolean} enabled - Состояние
401
- */
402
- setPluginEnabled(pluginName, enabled) {
403
- const plugin = this.plugins.get(pluginName);
404
- if (!plugin) {
405
- throw new Error(`Plugin "${pluginName}" не найден`);
406
- }
407
-
408
- plugin.enabled = enabled;
409
- /* istanbul ignore next */
410
- console.log(`🔧 Plugin "${pluginName}" ${enabled ? 'включен' : 'выключен'}`);
411
- }
412
-
413
- /**
414
- * Удаляет плагин
415
- * @param {string} pluginName - Имя плагина
416
- */
417
- removePlugin(pluginName) {
418
- if (!this.plugins.has(pluginName)) {
419
- throw new Error(`Plugin "${pluginName}" не найден`);
420
- }
421
-
422
- // Удаляем связанные hooks
423
- for (const [hookName, handlers] of this.hooks.entries()) {
424
- const filtered = handlers.filter(h => h.pluginName !== pluginName);
425
- this.hooks.set(hookName, filtered);
426
- }
427
-
428
- // Удаляем связанные middlewares
429
- this.middlewares = this.middlewares.filter(m => !m.name?.startsWith(`${pluginName}:`));
430
-
431
- // Удаляем плагин
432
- this.plugins.delete(pluginName);
433
-
434
- console.log(`🗑️ Plugin "${pluginName}" удален`);
435
- }
436
-
437
- /**
438
- * Возвращает статистику
439
- * @returns {Object} Статистика
440
- */
441
- getStats() {
442
- return {
443
- ...this.stats,
444
- plugins: this.plugins.size,
445
- hooks: Array.from(this.hooks.values()).reduce((sum, handlers) => sum + handlers.length, 0),
446
- middlewares: this.middlewares.length,
447
- uniqueHooks: this.hooks.size
448
- };
449
- }
450
-
451
- /**
452
- * Сбрасывает статистику
453
- */
454
- resetStats() {
455
- this.stats = {
456
- pluginLoads: 0,
457
- hookExecutions: 0,
458
- middlewareExecutions: 0
459
- };
460
- }
461
-
462
- /**
463
- * Очищает все плагины и hooks
464
- */
465
- clear() {
466
- this.plugins.clear();
467
- this.hooks.clear();
468
- this.middlewares = [];
469
- this.resetStats();
470
- this._registerDefaultHooks();
471
-
472
- console.log('🧹 Все плагины и hooks очищены');
473
- }
474
- }
475
-
476
- module.exports = PluginManager;