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
@@ -0,0 +1,399 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PluginManager = void 0;
4
+ exports.getGlobalPluginManager = getGlobalPluginManager;
5
+ exports.getGlobalPluginManagerAsync = getGlobalPluginManagerAsync;
6
+ const SLOW_HOOK_THRESHOLD_MS = 100;
7
+ class PluginManager {
8
+ constructor() {
9
+ this.plugins = new Map();
10
+ this.hooks = new Map();
11
+ this.middlewares = [];
12
+ this.context = {};
13
+ this.stats = {
14
+ pluginLoads: 0,
15
+ hookExecutions: 0,
16
+ middlewareExecutions: 0
17
+ };
18
+ this._registerDefaultHooks();
19
+ }
20
+ use(name, plugin) {
21
+ this.registerPlugin(name, plugin);
22
+ }
23
+ _registerDefaultHooks() {
24
+ const defaultHooks = [
25
+ 'before:csvToJson',
26
+ 'after:csvToJson',
27
+ 'before:jsonToCsv',
28
+ 'after:jsonToCsv',
29
+ 'before:parse',
30
+ 'after:parse',
31
+ 'before:serialize',
32
+ 'after:serialize',
33
+ 'error',
34
+ 'validation',
35
+ 'transformation'
36
+ ];
37
+ defaultHooks.forEach(hook => {
38
+ this.hooks.set(hook, []);
39
+ });
40
+ }
41
+ registerPlugin(name, plugin) {
42
+ if (!plugin || typeof plugin !== 'object' || !plugin.name || !plugin.version) {
43
+ throw new Error('Plugin должен иметь name и version');
44
+ }
45
+ if (this.plugins.has(name)) {
46
+ throw new Error(`Plugin "${name}" уже зарегистрирован`);
47
+ }
48
+ if (plugin.hooks && (typeof plugin.hooks !== 'object' || Array.isArray(plugin.hooks))) {
49
+ throw new Error('hooks must be an object');
50
+ }
51
+ if (plugin.hooks) {
52
+ for (const [hookName, handler] of Object.entries(plugin.hooks)) {
53
+ if (typeof handler !== 'function') {
54
+ throw new Error(`Hook handler for "${hookName}" must be a function`);
55
+ }
56
+ }
57
+ }
58
+ if (plugin.middlewares && !Array.isArray(plugin.middlewares)) {
59
+ throw new Error('middlewares must be an array');
60
+ }
61
+ if (plugin.middlewares) {
62
+ plugin.middlewares.forEach((middleware, index) => {
63
+ if (typeof middleware !== 'function') {
64
+ throw new Error(`Middleware ${index} must be a function`);
65
+ }
66
+ });
67
+ }
68
+ const record = {
69
+ id: name,
70
+ enabled: true,
71
+ ...plugin
72
+ };
73
+ this.plugins.set(name, record);
74
+ this.stats.pluginLoads++;
75
+ if (plugin.hooks) {
76
+ Object.entries(plugin.hooks).forEach(([hookName, handler]) => {
77
+ this.registerHook(hookName, handler, name);
78
+ });
79
+ }
80
+ if (plugin.middlewares) {
81
+ plugin.middlewares.forEach(middleware => {
82
+ this.registerMiddleware(middleware, name);
83
+ });
84
+ }
85
+ if (plugin.init) {
86
+ plugin.init(this);
87
+ }
88
+ }
89
+ registerHook(hookName, handler, pluginName) {
90
+ if (typeof handler != 'function') {
91
+ throw new Error('Hook handler must be a function');
92
+ }
93
+ if (!this.hooks.has(hookName)) {
94
+ this.hooks.set(hookName, []);
95
+ }
96
+ const handlers = this.hooks.get(hookName);
97
+ handlers.push({
98
+ handler,
99
+ pluginName,
100
+ executionCount: 0
101
+ });
102
+ }
103
+ registerMiddleware(middleware, pluginName) {
104
+ if (typeof middleware !== 'function') {
105
+ throw new Error('Middleware must be a function');
106
+ }
107
+ this.middlewares.push({
108
+ handler: middleware,
109
+ pluginName,
110
+ executionCount: 0
111
+ });
112
+ }
113
+ _isPluginEnabled(pluginName) {
114
+ if (!pluginName) {
115
+ return true;
116
+ }
117
+ const plugin = this.plugins.get(pluginName);
118
+ if (!plugin) {
119
+ return true;
120
+ }
121
+ return plugin.enabled !== false;
122
+ }
123
+ _runErrorHooks(error, context) {
124
+ const errorHandlers = this.hooks.get('error');
125
+ if (!errorHandlers || errorHandlers.length == 0) {
126
+ return;
127
+ }
128
+ for (const handlerEntry of errorHandlers) {
129
+ try {
130
+ handlerEntry.handler(error, context);
131
+ }
132
+ catch {
133
+ }
134
+ }
135
+ }
136
+ async executeHook(hookName, data, context = {}) {
137
+ const handlers = this.hooks.get(hookName);
138
+ if (!handlers || handlers.length === 0) {
139
+ return data;
140
+ }
141
+ let result = data;
142
+ let executed = false;
143
+ for (const handlerEntry of handlers) {
144
+ if (!this._isPluginEnabled(handlerEntry.pluginName)) {
145
+ continue;
146
+ }
147
+ executed = true;
148
+ const startTime = Date.now();
149
+ try {
150
+ result = await handlerEntry.handler(result, { ...this.context, ...context, hookName, plugin: handlerEntry.pluginName });
151
+ handlerEntry.executionCount++;
152
+ }
153
+ catch (error) {
154
+ this._runErrorHooks(error, { ...this.context, ...context, hookName, data: result });
155
+ }
156
+ finally {
157
+ const duration = Date.now() - startTime;
158
+ if (duration > SLOW_HOOK_THRESHOLD_MS) {
159
+ console.warn(`Slow hook "${hookName}" detected (${duration}ms)`);
160
+ }
161
+ }
162
+ }
163
+ if (executed) {
164
+ this.stats.hookExecutions++;
165
+ }
166
+ return result;
167
+ }
168
+ async executeHooks(hookName, data, context = {}) {
169
+ return this.executeHook(hookName, data, context);
170
+ }
171
+ async executeWithPlugins(operation, input, options, handler) {
172
+ const metadata = options && options.metadata ? options.metadata : {};
173
+ const context = { operation, options, metadata };
174
+ const beforeHook = `before:${operation}`;
175
+ const afterHook = `after:${operation}`;
176
+ const beforeInput = await this.executeHook(beforeHook, input, context);
177
+ const middlewareContext = {
178
+ input: beforeInput,
179
+ options,
180
+ operation,
181
+ metadata
182
+ };
183
+ const resultHolder = { set: false, value: undefined };
184
+ try {
185
+ await this.executeMiddlewares(middlewareContext, context, async (ctx) => {
186
+ const handlerInput = ctx && Object.prototype.hasOwnProperty.call(ctx, 'input')
187
+ ? ctx.input
188
+ : beforeInput;
189
+ const result = await handler(handlerInput, options);
190
+ ctx.result = result;
191
+ resultHolder.set = true;
192
+ resultHolder.value = result;
193
+ return result;
194
+ });
195
+ }
196
+ catch (error) {
197
+ this._runErrorHooks(error, { ...this.context, ...context, data: beforeInput });
198
+ throw error;
199
+ }
200
+ const finalResult = resultHolder.set
201
+ ? resultHolder.value
202
+ : (Object.prototype.hasOwnProperty.call(middlewareContext, 'result') ? middlewareContext.result : undefined);
203
+ return this.executeHook(afterHook, finalResult, context);
204
+ }
205
+ listPlugins() {
206
+ return Array.from(this.plugins.values()).map((plugin) => ({
207
+ id: plugin.id,
208
+ pluginName: plugin.name,
209
+ version: plugin.version,
210
+ description: plugin.description,
211
+ enabled: plugin.enabled
212
+ }));
213
+ }
214
+ listHooks() {
215
+ const result = {};
216
+ for (const [hookName, handlers] of this.hooks.entries()) {
217
+ result[hookName] = {
218
+ count: handlers.length,
219
+ handlers: handlers.map((handlerEntry) => ({
220
+ handler: handlerEntry.handler,
221
+ pluginName: handlerEntry.pluginName,
222
+ executionCount: handlerEntry.executionCount
223
+ }))
224
+ };
225
+ }
226
+ return result;
227
+ }
228
+ setPluginEnabled(name, enabled) {
229
+ const plugin = this.plugins.get(name);
230
+ if (!plugin) {
231
+ throw new Error(`Plugin "${name}" не найден`);
232
+ }
233
+ plugin.enabled = Boolean(enabled);
234
+ }
235
+ removePlugin(name) {
236
+ const plugin = this.plugins.get(name);
237
+ if (!plugin) {
238
+ throw new Error(`Plugin "${name}" не найден`);
239
+ }
240
+ if (plugin.destroy) {
241
+ try {
242
+ plugin.destroy();
243
+ }
244
+ catch (error) {
245
+ console.error(`Error destroying plugin "${name}":`, error);
246
+ }
247
+ }
248
+ this.plugins.delete(name);
249
+ for (const [hookName, handlers] of this.hooks.entries()) {
250
+ if (!handlers.length) {
251
+ continue;
252
+ }
253
+ const remaining = handlers.filter((handlerEntry) => handlerEntry.pluginName !== name);
254
+ this.hooks.set(hookName, remaining);
255
+ }
256
+ this.middlewares = this.middlewares.filter((middleware) => middleware.pluginName !== name);
257
+ return true;
258
+ }
259
+ resetStats() {
260
+ this.stats.pluginLoads = 0;
261
+ this.stats.hookExecutions = 0;
262
+ this.stats.middlewareExecutions = 0;
263
+ }
264
+ async executeMiddlewares(ctx, context = {}, finalHandler) {
265
+ const entries = this.middlewares.filter((entry) => this._isPluginEnabled(entry.pluginName));
266
+ if (entries.length === 0) {
267
+ if (finalHandler) {
268
+ await finalHandler(ctx);
269
+ }
270
+ return ctx;
271
+ }
272
+ let index = -1;
273
+ const dispatch = async (i) => {
274
+ if (i <= index) {
275
+ throw new Error('next() вызван несколько раз');
276
+ }
277
+ index = i;
278
+ const entry = entries[i];
279
+ if (!entry) {
280
+ if (finalHandler) {
281
+ return finalHandler(ctx);
282
+ }
283
+ return;
284
+ }
285
+ const startTime = Date.now();
286
+ try {
287
+ const result = entry.handler(ctx, () => dispatch(i + 1));
288
+ await result;
289
+ entry.executionCount++;
290
+ this.stats.middlewareExecutions++;
291
+ }
292
+ catch (error) {
293
+ this._runErrorHooks(error, { ...this.context, ...context, data: ctx });
294
+ throw error;
295
+ }
296
+ finally {
297
+ const duration = Date.now() - startTime;
298
+ if (duration > SLOW_HOOK_THRESHOLD_MS) {
299
+ console.warn(`Slow middleware "${entry.pluginName || 'anonymous'}" detected (${duration}ms)`);
300
+ }
301
+ }
302
+ };
303
+ await dispatch(0);
304
+ return ctx;
305
+ }
306
+ async executeMiddleware(input, context = {}) {
307
+ return this.executeMiddlewares(input, context);
308
+ }
309
+ setContext(key, value) {
310
+ this.context[key] = value;
311
+ }
312
+ getContext(key) {
313
+ if (key) {
314
+ return this.context[key];
315
+ }
316
+ return { ...this.context };
317
+ }
318
+ getStats() {
319
+ let hookCount = 0;
320
+ for (const handlers of this.hooks.values()) {
321
+ hookCount += handlers.length;
322
+ }
323
+ return {
324
+ ...this.stats,
325
+ plugins: this.plugins.size,
326
+ hooks: hookCount,
327
+ middlewares: this.middlewares.length,
328
+ uniqueHooks: this.hooks.size
329
+ };
330
+ }
331
+ getPlugins() {
332
+ return Array.from(this.plugins.keys());
333
+ }
334
+ getHooks() {
335
+ return Array.from(this.hooks.keys());
336
+ }
337
+ unregisterPlugin(name) {
338
+ try {
339
+ this.removePlugin(name);
340
+ return true;
341
+ }
342
+ catch {
343
+ return false;
344
+ }
345
+ }
346
+ clear() {
347
+ this.plugins.forEach((plugin, name) => {
348
+ if (plugin.destroy) {
349
+ try {
350
+ plugin.destroy();
351
+ }
352
+ catch (error) {
353
+ console.error(`Error destroying plugin "${name}":`, error);
354
+ }
355
+ }
356
+ });
357
+ this.plugins.clear();
358
+ this.hooks.clear();
359
+ this.middlewares = [];
360
+ this.context = {};
361
+ this._registerDefaultHooks();
362
+ console.log('🧹 Plugin system cleared');
363
+ }
364
+ async executeHookAsync(hookName, data, context = {}) {
365
+ return this.executeHook(hookName, data, context);
366
+ }
367
+ async executeMiddlewareAsync(input, context = {}) {
368
+ return this.executeMiddlewares(input, context);
369
+ }
370
+ }
371
+ exports.PluginManager = PluginManager;
372
+ let globalPluginManager = null;
373
+ function getGlobalPluginManager() {
374
+ if (!globalPluginManager) {
375
+ globalPluginManager = new PluginManager();
376
+ }
377
+ return globalPluginManager;
378
+ }
379
+ async function getGlobalPluginManagerAsync() {
380
+ return getGlobalPluginManager();
381
+ }
382
+ exports.default = PluginManager;
383
+ if (typeof module !== 'undefined' && module.exports) {
384
+ const current = module.exports;
385
+ if (current && current.__esModule) {
386
+ current.PluginManager = PluginManager;
387
+ current.getGlobalPluginManager = getGlobalPluginManager;
388
+ current.getGlobalPluginManagerAsync = getGlobalPluginManagerAsync;
389
+ current.default = PluginManager;
390
+ }
391
+ else {
392
+ module.exports = PluginManager;
393
+ module.exports.PluginManager = PluginManager;
394
+ module.exports.getGlobalPluginManager = getGlobalPluginManager;
395
+ module.exports.getGlobalPluginManagerAsync = getGlobalPluginManagerAsync;
396
+ module.exports.default = PluginManager;
397
+ }
398
+ }
399
+ //# sourceMappingURL=plugin-system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-system.js","sourceRoot":"","sources":["../../../src/core/plugin-system.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Plugin System для JTCSV\r\n * Middleware-like архитектура с поддержкой hooks и плагинов\r\n * \r\n * @version 1.0.0\r\n * @date 2026-01-22\r\n */\r\n\r\ninterface PluginStatsCounters {\r\n pluginLoads: number;\r\n hookExecutions: number;\r\n middlewareExecutions: number;\r\n}\r\n\r\ninterface PluginStats extends PluginStatsCounters {\r\n plugins: number;\r\n hooks: number;\r\n middlewares: number;\r\n uniqueHooks: number;\r\n}\r\n\r\ninterface Plugin {\r\n name: string;\r\n version: string;\r\n description?: string;\r\n hooks?: Record<string, Function>;\r\n middlewares?: Function[];\r\n init?: (manager: PluginManager) => void;\r\n destroy?: () => void;\r\n}\r\n\r\ninterface PluginRecord extends Plugin {\r\n id: string;\r\n enabled: boolean;\r\n}\r\n\r\ninterface HookHandlerEntry {\r\n handler: Function;\r\n pluginName?: string;\r\n executionCount: number;\r\n}\r\n\r\ninterface MiddlewareEntry {\r\n handler: Function;\r\n pluginName?: string;\r\n executionCount: number;\r\n}\r\n\r\ntype HookName = \r\n | 'before:csvToJson'\r\n | 'after:csvToJson'\r\n | 'before:jsonToCsv'\r\n | 'after:jsonToCsv'\r\n | 'before:parse'\r\n | 'after:parse'\r\n | 'before:serialize'\r\n | 'after:serialize'\r\n | 'error'\r\n | 'validation'\r\n | 'transformation'\r\n | string;\r\n\r\nconst SLOW_HOOK_THRESHOLD_MS = 100;\r\n\r\nexport class PluginManager {\r\n private plugins: Map<string, PluginRecord>;\r\n private hooks: Map<HookName, HookHandlerEntry[]>;\r\n private middlewares: MiddlewareEntry[];\r\n private context: Record<string, any>;\r\n private stats: PluginStatsCounters;\r\n\r\n constructor() {\r\n this.plugins = new Map();\r\n this.hooks = new Map();\r\n this.middlewares = [];\r\n this.context = {};\r\n this.stats = {\r\n pluginLoads: 0,\r\n hookExecutions: 0,\r\n middlewareExecutions: 0\r\n };\r\n\r\n // Регистрируем стандартные hooks\r\n this._registerDefaultHooks();\r\n }\r\n\r\n /**\r\n * Backwards-compatible alias for registerPlugin.\r\n */\r\n use(name: string, plugin: Plugin): void {\r\n this.registerPlugin(name, plugin);\r\n }\r\n\r\n /**\r\n * Регистрирует стандартные hooks\r\n */\r\n private _registerDefaultHooks(): void {\r\n const defaultHooks: HookName[] = [\r\n 'before:csvToJson',\r\n 'after:csvToJson',\r\n 'before:jsonToCsv',\r\n 'after:jsonToCsv',\r\n 'before:parse',\r\n 'after:parse',\r\n 'before:serialize',\r\n 'after:serialize',\r\n 'error',\r\n 'validation',\r\n 'transformation'\r\n ];\r\n\r\n defaultHooks.forEach(hook => {\r\n this.hooks.set(hook, []);\r\n });\r\n }\r\n\r\n /**\r\n * Регистрирует плагин\r\n * @param name - Уникальное имя плагина\r\n * @param plugin - Объект плагина\r\n */\r\n registerPlugin(name: string, plugin: Plugin): void {\r\n if (!plugin || typeof plugin !== 'object' || !plugin.name || !plugin.version) {\r\n throw new Error('Plugin должен иметь name и version');\r\n }\r\n\r\n if (this.plugins.has(name)) {\r\n throw new Error(`Plugin \"${name}\" уже зарегистрирован`);\r\n }\r\n\r\n if (plugin.hooks && (typeof plugin.hooks !== 'object' || Array.isArray(plugin.hooks))) {\r\n throw new Error('hooks must be an object');\r\n }\r\n\r\n if (plugin.hooks) {\r\n for (const [hookName, handler] of Object.entries(plugin.hooks)) {\r\n if (typeof handler !== 'function') {\r\n throw new Error(`Hook handler for \"${hookName}\" must be a function`);\r\n }\r\n }\r\n }\r\n\r\n if (plugin.middlewares && !Array.isArray(plugin.middlewares)) {\r\n throw new Error('middlewares must be an array');\r\n }\r\n\r\n if (plugin.middlewares) {\r\n plugin.middlewares.forEach((middleware, index) => {\r\n if (typeof middleware !== 'function') {\r\n throw new Error(`Middleware ${index} must be a function`);\r\n }\r\n });\r\n }\r\n\r\n const record: PluginRecord = {\r\n id: name,\r\n enabled: true,\r\n ...plugin\r\n };\r\n\r\n // ?????????????????? ????????????\r\n this.plugins.set(name, record);\r\n this.stats.pluginLoads++;\r\n\r\n // ?????????????????????? hooks ??????????????\r\n if (plugin.hooks) {\r\n Object.entries(plugin.hooks).forEach(([hookName, handler]) => {\r\n this.registerHook(hookName as HookName, handler, name);\r\n });\r\n }\r\n\r\n // ?????????????????????? middleware ??????????????\r\n if (plugin.middlewares) {\r\n plugin.middlewares.forEach(middleware => {\r\n this.registerMiddleware(middleware, name);\r\n });\r\n }\r\n\r\n // ???????????????? init ???????? ????????\r\n if (plugin.init) {\r\n plugin.init(this);\r\n }\r\n }\r\n\r\n registerHook(hookName: HookName, handler: Function, pluginName?: string): void {\r\n if (typeof handler != 'function') {\r\n throw new Error('Hook handler must be a function');\r\n }\r\n if (!this.hooks.has(hookName)) {\r\n this.hooks.set(hookName, []);\r\n }\r\n\r\n const handlers = this.hooks.get(hookName)!;\r\n handlers.push({\r\n handler,\r\n pluginName,\r\n executionCount: 0\r\n });\r\n }\r\n\r\n registerMiddleware(middleware: Function, pluginName?: string): void {\r\n if (typeof middleware !== 'function') {\r\n throw new Error('Middleware must be a function');\r\n }\r\n this.middlewares.push({\r\n handler: middleware,\r\n pluginName,\r\n executionCount: 0\r\n });\r\n }\r\n\r\n private _isPluginEnabled(pluginName?: string): boolean {\r\n if (!pluginName) {\r\n return true;\r\n }\r\n const plugin = this.plugins.get(pluginName);\r\n if (!plugin) {\r\n return true;\r\n }\r\n return plugin.enabled !== false;\r\n }\r\n\r\n private _runErrorHooks(error: any, context: any): void {\r\n const errorHandlers = this.hooks.get('error');\r\n if (!errorHandlers || errorHandlers.length == 0) {\r\n return;\r\n }\r\n for (const handlerEntry of errorHandlers) {\r\n try {\r\n handlerEntry.handler(error, context);\r\n } catch {\r\n // ignore errors in error handlers\r\n }\r\n }\r\n }\r\n\r\n async executeHook(hookName: HookName, data: any, context: any = {}): Promise<any> {\r\n const handlers = this.hooks.get(hookName);\r\n\r\n if (!handlers || handlers.length === 0) {\r\n return data;\r\n }\r\n\r\n let result = data;\r\n let executed = false;\r\n\r\n for (const handlerEntry of handlers) {\r\n if (!this._isPluginEnabled(handlerEntry.pluginName)) {\r\n continue;\r\n }\r\n\r\n executed = true;\r\n const startTime = Date.now();\r\n try {\r\n result = await handlerEntry.handler(result, { ...this.context, ...context, hookName, plugin: handlerEntry.pluginName });\r\n handlerEntry.executionCount++;\r\n } catch (error) {\r\n this._runErrorHooks(error, { ...this.context, ...context, hookName, data: result });\r\n } finally {\r\n const duration = Date.now() - startTime;\r\n if (duration > SLOW_HOOK_THRESHOLD_MS) {\r\n console.warn(`Slow hook \"${hookName}\" detected (${duration}ms)`);\r\n }\r\n }\r\n }\r\n\r\n if (executed) {\r\n this.stats.hookExecutions++;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Backwards-compatible alias for executeHook.\r\n */\r\n async executeHooks(hookName: HookName, data: any, context: any = {}): Promise<any> {\r\n return this.executeHook(hookName, data, context);\r\n }\r\n\r\n /**\r\n * Executes an operation with before/after hooks and middleware.\r\n */\r\n async executeWithPlugins(\r\n operation: string,\r\n input: any,\r\n options: any,\r\n handler: (input: any, options: any) => any | Promise<any>\r\n ): Promise<any> {\r\n const metadata = options && options.metadata ? options.metadata : {};\r\n const context = { operation, options, metadata };\r\n const beforeHook = `before:${operation}` as HookName;\r\n const afterHook = `after:${operation}` as HookName;\r\n\r\n const beforeInput = await this.executeHook(beforeHook, input, context);\r\n const middlewareContext: { input: any; options: any; operation: string; metadata: any; result?: any } = {\n input: beforeInput,\n options,\n operation,\n metadata\n };\n const resultHolder = { set: false, value: undefined as any };\r\n\r\n try {\r\n await this.executeMiddlewares(middlewareContext, context, async (ctx: any) => {\r\n const handlerInput = ctx && Object.prototype.hasOwnProperty.call(ctx, 'input')\r\n ? ctx.input\r\n : beforeInput;\r\n const result = await handler(handlerInput, options);\r\n ctx.result = result;\r\n resultHolder.set = true;\r\n resultHolder.value = result;\r\n return result;\r\n });\r\n } catch (error) {\r\n this._runErrorHooks(error, { ...this.context, ...context, data: beforeInput });\r\n throw error;\r\n }\r\n\r\n const finalResult = resultHolder.set\r\n ? resultHolder.value\r\n : (Object.prototype.hasOwnProperty.call(middlewareContext, 'result') ? middlewareContext.result : undefined);\r\n\r\n return this.executeHook(afterHook, finalResult, context);\r\n }\r\n\r\n /**\r\n * Returns registered plugin names.\r\n */\r\n listPlugins(): Array<{ id: string; pluginName: string; version: string; description?: string; enabled: boolean }> {\r\n return Array.from(this.plugins.values()).map((plugin) => ({\r\n id: plugin.id,\r\n pluginName: plugin.name,\r\n version: plugin.version,\r\n description: plugin.description,\r\n enabled: plugin.enabled\r\n }));\r\n }\r\n\r\n listHooks(): Record<string, { count: number; handlers: Array<{ handler: Function; pluginName?: string; executionCount: number }> }> {\r\n const result: Record<string, { count: number; handlers: Array<{ handler: Function; pluginName?: string; executionCount: number }> }> = {};\r\n for (const [hookName, handlers] of this.hooks.entries()) {\r\n result[hookName] = {\r\n count: handlers.length,\r\n handlers: handlers.map((handlerEntry) => ({\r\n handler: handlerEntry.handler,\r\n pluginName: handlerEntry.pluginName,\r\n executionCount: handlerEntry.executionCount\r\n }))\r\n };\r\n }\r\n return result;\r\n }\r\n\r\n\r\n setPluginEnabled(name: string, enabled: boolean): void {\r\n const plugin = this.plugins.get(name);\r\n if (!plugin) {\r\n throw new Error(`Plugin \"${name}\" не найден`);\r\n }\r\n plugin.enabled = Boolean(enabled);\r\n }\r\n\r\n removePlugin(name: string): boolean {\r\n const plugin = this.plugins.get(name);\r\n if (!plugin) {\r\n throw new Error(`Plugin \"${name}\" не найден`);\r\n }\r\n\r\n if (plugin.destroy) {\r\n try {\r\n plugin.destroy();\r\n } catch (error) {\r\n console.error(`Error destroying plugin \"${name}\":`, error);\r\n }\r\n }\r\n\r\n this.plugins.delete(name);\r\n\r\n for (const [hookName, handlers] of this.hooks.entries()) {\r\n if (!handlers.length) {\r\n continue;\r\n }\r\n const remaining = handlers.filter((handlerEntry) => handlerEntry.pluginName !== name);\r\n this.hooks.set(hookName, remaining);\r\n }\r\n\r\n this.middlewares = this.middlewares.filter((middleware) => middleware.pluginName !== name);\r\n\r\n return true;\r\n }\r\n\r\n resetStats(): void {\r\n this.stats.pluginLoads = 0;\r\n this.stats.hookExecutions = 0;\r\n this.stats.middlewareExecutions = 0;\r\n }\r\n\r\n async executeMiddlewares(ctx: any, context: any = {}, finalHandler?: (ctx: any) => any | Promise<any>): Promise<any> {\r\n const entries = this.middlewares.filter((entry) => this._isPluginEnabled(entry.pluginName));\r\n if (entries.length === 0) {\r\n if (finalHandler) {\r\n await finalHandler(ctx);\r\n }\r\n return ctx;\r\n }\r\n\r\n let index = -1;\r\n const dispatch = async (i: number): Promise<any> => {\r\n if (i <= index) {\r\n throw new Error('next() вызван несколько раз');\r\n }\r\n index = i;\r\n const entry = entries[i];\r\n if (!entry) {\r\n if (finalHandler) {\r\n return finalHandler(ctx);\r\n }\r\n return;\r\n }\r\n\r\n const startTime = Date.now();\r\n try {\r\n const result = entry.handler(ctx, () => dispatch(i + 1));\r\n await result;\r\n entry.executionCount++;\r\n this.stats.middlewareExecutions++;\r\n } catch (error) {\r\n this._runErrorHooks(error, { ...this.context, ...context, data: ctx });\r\n throw error;\r\n } finally {\r\n const duration = Date.now() - startTime;\r\n if (duration > SLOW_HOOK_THRESHOLD_MS) {\r\n console.warn(`Slow middleware \"${entry.pluginName || 'anonymous'}\" detected (${duration}ms)`);\r\n }\r\n }\r\n };\r\n\r\n await dispatch(0);\r\n return ctx;\r\n }\r\n\r\n /**\r\n * Backwards-compatible alias for executeMiddlewares.\r\n */\r\n async executeMiddleware(input: any, context: any = {}): Promise<any> {\r\n return this.executeMiddlewares(input, context);\r\n }\r\n\r\n setContext(key: string, value: any): void {\r\n this.context[key] = value;\r\n }\r\n\r\n /**\r\n * Получает контекст\r\n * @param key - Ключ контекста (опционально)\r\n */\r\n getContext(key?: string): any {\r\n if (key) {\r\n return this.context[key];\r\n }\r\n return { ...this.context };\r\n }\r\n\r\n /**\r\n * Возвращает статистику\r\n */\r\n getStats(): PluginStats {\r\n let hookCount = 0;\r\n for (const handlers of this.hooks.values()) {\r\n hookCount += handlers.length;\r\n }\r\n\r\n return {\r\n ...this.stats,\r\n plugins: this.plugins.size,\r\n hooks: hookCount,\r\n middlewares: this.middlewares.length,\r\n uniqueHooks: this.hooks.size\r\n };\r\n }\r\n\r\n /**\r\n * Возвращает список зарегистрированных плагинов\r\n */\r\n getPlugins(): string[] {\r\n return Array.from(this.plugins.keys());\r\n }\r\n\r\n /**\r\n * Возвращает список зарегистрированных hooks\r\n */\r\n getHooks(): HookName[] {\r\n return Array.from(this.hooks.keys());\r\n }\r\n\r\n /**\r\n * Удаляет плагин\r\n * @param name - Имя плагина\r\n */\r\n unregisterPlugin(name: string): boolean {\r\n try {\r\n this.removePlugin(name);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Очищает все плагины и hooks\r\n */\r\n clear(): void {\r\n // Вызываем destroy для всех плагинов\r\n this.plugins.forEach((plugin, name) => {\r\n if (plugin.destroy) {\r\n try {\r\n plugin.destroy();\r\n } catch (error) {\r\n console.error(`Error destroying plugin \"${name}\":`, error);\r\n }\r\n }\r\n });\r\n\r\n this.plugins.clear();\r\n this.hooks.clear();\r\n this.middlewares = [];\r\n this.context = {};\r\n \r\n // Регистрируем стандартные hooks заново\r\n this._registerDefaultHooks();\r\n \r\n console.log('🧹 Plugin system cleared');\r\n }\r\n\r\n /**\r\n * Асинхронная версия executeHook\r\n */\r\n async executeHookAsync(hookName: HookName, data: any, context: any = {}): Promise<any> {\r\n return this.executeHook(hookName, data, context);\r\n }\r\n\r\n /**\r\n * Асинхронная версия executeMiddleware\r\n */\r\n async executeMiddlewareAsync(input: any, context: any = {}): Promise<any> {\r\n return this.executeMiddlewares(input, context);\r\n }\r\n}\r\n\r\n// Создание глобального экземпляра PluginManager\r\nlet globalPluginManager: PluginManager | null = null;\r\n\r\n/**\r\n * Возвращает глобальный экземпляр PluginManager\r\n */\r\nexport function getGlobalPluginManager(): PluginManager {\r\n if (!globalPluginManager) {\r\n globalPluginManager = new PluginManager();\r\n }\r\n return globalPluginManager;\r\n}\r\n\r\n/**\r\n * Асинхронная версия getGlobalPluginManager\r\n */\r\nexport async function getGlobalPluginManagerAsync(): Promise<PluginManager> {\r\n return getGlobalPluginManager();\r\n}\r\n\r\nexport default PluginManager;\r\n\r\n// Экспорт для CommonJS\r\nif (typeof module !== 'undefined' && module.exports) {\r\n const current = module.exports;\r\n if (current && current.__esModule) {\r\n current.PluginManager = PluginManager;\r\n current.getGlobalPluginManager = getGlobalPluginManager;\r\n current.getGlobalPluginManagerAsync = getGlobalPluginManagerAsync;\r\n current.default = PluginManager;\r\n } else {\r\n module.exports = PluginManager;\r\n module.exports.PluginManager = PluginManager;\r\n module.exports.getGlobalPluginManager = getGlobalPluginManager;\r\n module.exports.getGlobalPluginManagerAsync = getGlobalPluginManagerAsync;\r\n module.exports.default = PluginManager;\r\n }\r\n}\r\n"]}