jtcsv 3.0.0 → 3.1.1

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 (258) hide show
  1. package/README.md +205 -146
  2. package/bin/jtcsv.ts +280 -202
  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 +1261 -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 +336 -7
  23. package/dist/jtcsv-core.cjs.js.map +1 -1
  24. package/dist/jtcsv-core.esm.js +336 -7
  25. package/dist/jtcsv-core.esm.js.map +1 -1
  26. package/dist/jtcsv-core.umd.js +336 -7
  27. package/dist/jtcsv-core.umd.js.map +1 -1
  28. package/dist/jtcsv-full.cjs.js +336 -7
  29. package/dist/jtcsv-full.cjs.js.map +1 -1
  30. package/dist/jtcsv-full.esm.js +336 -7
  31. package/dist/jtcsv-full.esm.js.map +1 -1
  32. package/dist/jtcsv-full.umd.js +336 -7
  33. package/dist/jtcsv-full.umd.js.map +1 -1
  34. package/dist/jtcsv-workers.esm.js +9 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -1
  36. package/dist/jtcsv-workers.umd.js +9 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -1
  38. package/dist/jtcsv.cjs.js +1998 -2092
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1994 -2092
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2251
  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 +192 -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/{src → dist/src}/web-server/index.js +251 -286
  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 +664 -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 +2 -2
  131. package/examples/advanced/performance-optimization.ts +2 -2
  132. package/examples/cli-advanced-usage.md +2 -0
  133. package/examples/cli-tool.ts +1 -1
  134. package/examples/large-dataset-example.ts +2 -2
  135. package/examples/simple-usage.ts +2 -2
  136. package/examples/streaming-example.ts +1 -1
  137. package/index.d.ts +186 -15
  138. package/package.json +243 -305
  139. package/plugins.d.ts +37 -0
  140. package/schema.d.ts +103 -0
  141. package/src/browser/csv-to-json-browser.ts +233 -3
  142. package/src/browser/errors-browser.ts +45 -28
  143. package/src/browser/json-to-csv-browser.ts +81 -5
  144. package/src/browser/streams.ts +73 -6
  145. package/src/core/delimiter-cache.ts +21 -11
  146. package/src/core/plugin-system.ts +343 -155
  147. package/src/core/transform-hooks.ts +20 -12
  148. package/src/engines/fast-path-engine.ts +48 -32
  149. package/src/errors.ts +1 -72
  150. package/src/formats/ndjson-parser.ts +6 -0
  151. package/src/formats/tsv-parser.ts +6 -0
  152. package/src/types/index.ts +21 -1
  153. package/src/utils/validators.ts +35 -0
  154. package/src/web-server/index.ts +1 -1
  155. package/bin/jtcsv.js +0 -2532
  156. package/csv-to-json.js +0 -711
  157. package/errors.js +0 -394
  158. package/examples/advanced/conditional-transformations.js +0 -446
  159. package/examples/advanced/csv-parser.worker.js +0 -89
  160. package/examples/advanced/nested-objects-example.js +0 -306
  161. package/examples/advanced/performance-optimization.js +0 -504
  162. package/examples/advanced/run-demo-server.js +0 -116
  163. package/examples/cli-batch-processing.js +0 -38
  164. package/examples/cli-tool.js +0 -183
  165. package/examples/error-handling.js +0 -338
  166. package/examples/express-api.js +0 -164
  167. package/examples/large-dataset-example.js +0 -182
  168. package/examples/ndjson-processing.js +0 -434
  169. package/examples/plugin-excel-exporter.js +0 -406
  170. package/examples/schema-validation.js +0 -640
  171. package/examples/simple-usage.js +0 -282
  172. package/examples/streaming-example.js +0 -418
  173. package/examples/web-workers-advanced.js +0 -28
  174. package/index.js +0 -82
  175. package/json-save.js +0 -255
  176. package/json-to-csv.js +0 -668
  177. package/plugins/README.md +0 -91
  178. package/plugins/express-middleware/README.md +0 -83
  179. package/plugins/express-middleware/example.js +0 -135
  180. package/plugins/express-middleware/example.ts +0 -135
  181. package/plugins/express-middleware/index.d.ts +0 -114
  182. package/plugins/express-middleware/index.js +0 -512
  183. package/plugins/express-middleware/index.ts +0 -557
  184. package/plugins/express-middleware/package.json +0 -52
  185. package/plugins/fastify-plugin/index.js +0 -404
  186. package/plugins/fastify-plugin/index.ts +0 -443
  187. package/plugins/fastify-plugin/package.json +0 -55
  188. package/plugins/hono/README.md +0 -28
  189. package/plugins/hono/index.d.ts +0 -12
  190. package/plugins/hono/index.js +0 -36
  191. package/plugins/hono/index.ts +0 -226
  192. package/plugins/hono/package.json +0 -35
  193. package/plugins/nestjs/README.md +0 -35
  194. package/plugins/nestjs/index.d.ts +0 -25
  195. package/plugins/nestjs/index.js +0 -77
  196. package/plugins/nestjs/index.ts +0 -201
  197. package/plugins/nestjs/package.json +0 -37
  198. package/plugins/nextjs-api/README.md +0 -57
  199. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  200. package/plugins/nextjs-api/examples/ConverterComponent.tsx +0 -386
  201. package/plugins/nextjs-api/examples/api-convert.js +0 -67
  202. package/plugins/nextjs-api/examples/api-convert.ts +0 -67
  203. package/plugins/nextjs-api/index.js +0 -387
  204. package/plugins/nextjs-api/index.tsx +0 -339
  205. package/plugins/nextjs-api/package.json +0 -63
  206. package/plugins/nextjs-api/route.js +0 -370
  207. package/plugins/nextjs-api/route.ts +0 -370
  208. package/plugins/nuxt/README.md +0 -24
  209. package/plugins/nuxt/index.js +0 -21
  210. package/plugins/nuxt/index.ts +0 -94
  211. package/plugins/nuxt/package.json +0 -35
  212. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  213. package/plugins/nuxt/runtime/composables/useJtcsv.ts +0 -100
  214. package/plugins/nuxt/runtime/plugin.js +0 -6
  215. package/plugins/nuxt/runtime/plugin.ts +0 -71
  216. package/plugins/remix/README.md +0 -26
  217. package/plugins/remix/index.d.ts +0 -16
  218. package/plugins/remix/index.js +0 -62
  219. package/plugins/remix/index.ts +0 -260
  220. package/plugins/remix/package.json +0 -35
  221. package/plugins/sveltekit/README.md +0 -28
  222. package/plugins/sveltekit/index.d.ts +0 -17
  223. package/plugins/sveltekit/index.js +0 -54
  224. package/plugins/sveltekit/index.ts +0 -301
  225. package/plugins/sveltekit/package.json +0 -33
  226. package/plugins/trpc/README.md +0 -25
  227. package/plugins/trpc/index.d.ts +0 -7
  228. package/plugins/trpc/index.js +0 -32
  229. package/plugins/trpc/index.ts +0 -267
  230. package/plugins/trpc/package.json +0 -34
  231. package/src/browser/browser-functions.js +0 -219
  232. package/src/browser/core.js +0 -92
  233. package/src/browser/csv-to-json-browser.js +0 -722
  234. package/src/browser/errors-browser.js +0 -212
  235. package/src/browser/extensions/plugins.js +0 -92
  236. package/src/browser/extensions/workers.js +0 -39
  237. package/src/browser/index.js +0 -113
  238. package/src/browser/json-to-csv-browser.js +0 -319
  239. package/src/browser/streams.js +0 -403
  240. package/src/browser/workers/csv-parser.worker.js +0 -377
  241. package/src/browser/workers/worker-pool.js +0 -527
  242. package/src/core/delimiter-cache.js +0 -200
  243. package/src/core/node-optimizations.js +0 -408
  244. package/src/core/plugin-system.js +0 -494
  245. package/src/core/transform-hooks.js +0 -350
  246. package/src/engines/fast-path-engine-new.js +0 -338
  247. package/src/engines/fast-path-engine.js +0 -844
  248. package/src/errors.js +0 -26
  249. package/src/formats/ndjson-parser.js +0 -467
  250. package/src/formats/tsv-parser.js +0 -339
  251. package/src/index-with-plugins.js +0 -378
  252. package/src/utils/bom-utils.js +0 -259
  253. package/src/utils/encoding-support.js +0 -124
  254. package/src/utils/schema-validator.js +0 -594
  255. package/src/utils/transform-loader.js +0 -205
  256. package/src/utils/zod-adapter.js +0 -170
  257. package/stream-csv-to-json.js +0 -560
  258. package/stream-json-to-csv.js +0 -465
@@ -1,28 +0,0 @@
1
- // Advanced Web Workers usage (browser example)
2
- // Requires jtcsv loaded in the browser (UMD or ESM).
3
-
4
- async function runWorkerDemo(file) {
5
- if (!window.jtcsv) {
6
- throw new Error('jtcsv is not available on window');
7
- }
8
-
9
- const pool = window.jtcsv.createWorkerPool({
10
- workerCount: 4,
11
- maxQueueSize: 50,
12
- autoScale: true
13
- });
14
-
15
- const result = await window.jtcsv.parseCSVWithWorker(file, {
16
- delimiter: ',',
17
- parseNumbers: true
18
- }, (progress) => {
19
- console.log(`Processed ${progress.processed} rows (${progress.percentage.toFixed(1)}%)`);
20
- }, pool);
21
-
22
- console.log('Rows:', result.length);
23
- return result;
24
- }
25
-
26
- // Example usage in the browser:
27
- // const file = document.querySelector('input[type="file"]').files[0];
28
- // runWorkerDemo(file);
package/index.js DELETED
@@ -1,82 +0,0 @@
1
- // @ts-nocheck
2
- // Main entry point for the jtcsv module
3
- // Exports both JSON→CSV and CSV→JSON functions
4
-
5
- const jsonToCsvModule = require('./json-to-csv');
6
- const csvToJsonModule = require('./csv-to-json');
7
- const errorsModule = require('./errors');
8
- const jsonSaveModule = require('./json-save');
9
- const streamJsonToCsvModule = require('./stream-json-to-csv');
10
- const streamCsvToJsonModule = require('./stream-csv-to-json');
11
- const ndjsonParser = require('./src/formats/ndjson-parser');
12
- const tsvParser = require('./src/formats/tsv-parser');
13
- const zodAdapter = require('./src/utils/zod-adapter');
14
- const encodingSupport = require('./src/utils/encoding-support');
15
-
16
- // Combine all exports
17
- module.exports = {
18
- // JSON to CSV functions
19
- jsonToCsv: jsonToCsvModule.jsonToCsv,
20
- preprocessData: jsonToCsvModule.preprocessData,
21
- saveAsCsv: jsonToCsvModule.saveAsCsv,
22
- deepUnwrap: jsonToCsvModule.deepUnwrap,
23
- validateFilePath: jsonToCsvModule.validateFilePath,
24
-
25
- // CSV to JSON functions
26
- csvToJson: csvToJsonModule.csvToJson,
27
- csvToJsonIterator: csvToJsonModule.csvToJsonIterator,
28
- readCsvAsJson: csvToJsonModule.readCsvAsJson,
29
- readCsvAsJsonSync: csvToJsonModule.readCsvAsJsonSync,
30
- autoDetectDelimiter: csvToJsonModule.autoDetectDelimiter,
31
-
32
- // JSON save functions
33
- saveAsJson: jsonSaveModule.saveAsJson,
34
- saveAsJsonSync: jsonSaveModule.saveAsJsonSync,
35
-
36
- // Streaming JSON to CSV functions
37
- createJsonToCsvStream: streamJsonToCsvModule.createJsonToCsvStream,
38
- streamJsonToCsv: streamJsonToCsvModule.streamJsonToCsv,
39
- saveJsonStreamAsCsv: streamJsonToCsvModule.saveJsonStreamAsCsv,
40
- createJsonReadableStream: streamJsonToCsvModule.createJsonReadableStream,
41
- createCsvCollectorStream: streamJsonToCsvModule.createCsvCollectorStream,
42
-
43
- // Streaming CSV to JSON functions
44
- createCsvToJsonStream: streamCsvToJsonModule.createCsvToJsonStream,
45
- streamCsvToJson: streamCsvToJsonModule.streamCsvToJson,
46
- createCsvFileToJsonStream: streamCsvToJsonModule.createCsvFileToJsonStream,
47
- createJsonCollectorStream: streamCsvToJsonModule.createJsonCollectorStream,
48
-
49
- // NDJSON format support
50
- jsonToNdjson: ndjsonParser.toNdjson,
51
- ndjsonToJson: ndjsonParser.fromNdjson,
52
- parseNdjsonStream: ndjsonParser.parseStream,
53
- createNdjsonToCsvStream: ndjsonParser.createNdjsonToCsvStream,
54
- createCsvToNdjsonStream: ndjsonParser.createCsvToNdjsonStream,
55
- getNdjsonStats: ndjsonParser.getStats,
56
-
57
- // TSV format support
58
- jsonToTsv: tsvParser.jsonToTsv,
59
- tsvToJson: tsvParser.tsvToJson,
60
- isTsv: tsvParser.isTsv,
61
- validateTsv: tsvParser.validateTsv,
62
- readTsvAsJson: tsvParser.readTsvAsJson,
63
- readTsvAsJsonSync: tsvParser.readTsvAsJsonSync,
64
- saveAsTsv: tsvParser.saveAsTsv,
65
- saveAsTsvSync: tsvParser.saveAsTsvSync,
66
- createJsonToTsvStream: tsvParser.createJsonToTsvStream,
67
- createTsvToJsonStream: tsvParser.createTsvToJsonStream,
68
-
69
- // Error classes
70
- ...errorsModule,
71
-
72
- // Schema validation adapters (optional dependencies)
73
- createZodValidationHook: zodAdapter.createZodValidationHook,
74
- createYupValidationHook: zodAdapter.createYupValidationHook,
75
- createValidatedParser: zodAdapter.createValidatedParser,
76
-
77
- // Encoding detection and conversion
78
- detectEncoding: encodingSupport.detectEncoding,
79
- convertToUtf8: encodingSupport.convertToUtf8,
80
- autoDetectAndConvert: encodingSupport.autoDetectAndConvert,
81
- csvToJsonWithEncoding: encodingSupport.csvToJsonWithEncoding
82
- };
package/json-save.js DELETED
@@ -1,255 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * JSON Save Module - Node.js Module
4
- *
5
- * A lightweight module for saving JSON data to files with security validation.
6
- *
7
- * @module json-save
8
- */
9
-
10
- const {
11
- ValidationError,
12
- SecurityError,
13
- FileSystemError,
14
- LimitError,
15
- ConfigurationError,
16
- safeExecute
17
- } = require('./errors');
18
-
19
- /**
20
- * Validates file path for JSON saving
21
- * @private
22
- */
23
- function validateJsonFilePath(filePath) {
24
- const path = require('path');
25
-
26
- // Basic validation
27
- if (typeof filePath !== 'string' || filePath.trim() === '') {
28
- throw new ValidationError('File path must be a non-empty string');
29
- }
30
-
31
- // Ensure file has .json extension
32
- if (!filePath.toLowerCase().endsWith('.json')) {
33
- throw new ValidationError('File must have .json extension');
34
- }
35
-
36
- // Block UNC paths BEFORE path.resolve() to avoid network lookup timeouts
37
- if (filePath.startsWith('\\\\') || filePath.startsWith('//')) {
38
- throw new SecurityError('UNC paths are not allowed');
39
- }
40
-
41
- // Get absolute path and check for traversal
42
- const absolutePath = path.resolve(filePath);
43
- const normalizedPath = path.normalize(filePath);
44
-
45
- // Prevent directory traversal attacks
46
- if (normalizedPath.includes('..') ||
47
- /\\\.\.\\|\/\.\.\//.test(filePath) ||
48
- filePath.startsWith('..') ||
49
- filePath.includes('/..')) {
50
- throw new SecurityError('Directory traversal detected in file path');
51
- }
52
-
53
- return absolutePath;
54
- }
55
-
56
- /**
57
- * Validates JSON data and options
58
- * @private
59
- */
60
- function validateJsonData(data, options) {
61
- // Validate data
62
- if (data === undefined || data === null) {
63
- throw new ValidationError('Data cannot be null or undefined');
64
- }
65
-
66
- // Validate options
67
- if (options && typeof options !== 'object') {
68
- throw new ConfigurationError('Options must be an object');
69
- }
70
-
71
- // Validate prettyPrint
72
- if (options?.prettyPrint !== undefined && typeof options.prettyPrint !== 'boolean') {
73
- throw new ConfigurationError('prettyPrint must be a boolean');
74
- }
75
-
76
- // Validate maxSize
77
- if (options?.maxSize && (typeof options.maxSize !== 'number' || options.maxSize <= 0)) {
78
- throw new ConfigurationError('maxSize must be a positive number');
79
- }
80
-
81
- return true;
82
- }
83
-
84
- /**
85
- * Saves JSON data to a file
86
- *
87
- * @param {*} data - Data to save as JSON
88
- * @param {string} filePath - Path to save the JSON file
89
- * @param {Object} [options] - Configuration options
90
- * @param {boolean} [options.prettyPrint=false] - Format JSON with indentation
91
- * @param {number} [options.maxSize=10485760] - Maximum file size in bytes (default: 10MB)
92
- * @returns {Promise<void>}
93
- *
94
- * @example
95
- * const { saveAsJson } = require('./json-save');
96
- *
97
- * const data = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
98
- * await saveAsJson(data, './output.json', { prettyPrint: true });
99
- */
100
- async function saveAsJson(data, filePath, options = {}) {
101
- return safeExecute(async () => {
102
- const fs = require('fs').promises;
103
-
104
- // Validate file path
105
- const safePath = validateJsonFilePath(filePath);
106
-
107
- // Validate data and options
108
- validateJsonData(data, options);
109
-
110
- const opts = options && typeof options === 'object' ? options : {};
111
- const {
112
- prettyPrint = false,
113
- maxSize = 10485760 // 10MB default limit
114
- } = opts;
115
-
116
- // Convert data to JSON string
117
- let jsonString;
118
- try {
119
- if (prettyPrint) {
120
- jsonString = JSON.stringify(data, null, 2);
121
- } else {
122
- jsonString = JSON.stringify(data);
123
- }
124
- } catch (error) {
125
- if (error.message.includes('circular') || error.message.includes('Converting circular')) {
126
- throw new ValidationError('Data contains circular references');
127
- }
128
- throw new ValidationError(`Failed to stringify JSON: ${error.message}`);
129
- }
130
-
131
- // Check size limit
132
- const byteSize = Buffer.byteLength(jsonString, 'utf8');
133
- if (byteSize > maxSize) {
134
- throw new LimitError(
135
- `JSON size exceeds maximum limit of ${maxSize} bytes`,
136
- maxSize,
137
- byteSize
138
- );
139
- }
140
-
141
- // Ensure directory exists
142
- const dir = require('path').dirname(safePath);
143
-
144
- try {
145
- await fs.mkdir(dir, { recursive: true });
146
-
147
- // Write file
148
- await fs.writeFile(safePath, jsonString, 'utf8');
149
-
150
- return safePath;
151
- } catch (error) {
152
- if (error.code === 'ENOENT') {
153
- throw new FileSystemError(`Directory does not exist: ${dir}`, error);
154
- }
155
- if (error.code === 'EACCES') {
156
- throw new FileSystemError(`Permission denied: ${safePath}`, error);
157
- }
158
- if (error.code === 'ENOSPC') {
159
- throw new FileSystemError(`No space left on device: ${safePath}`, error);
160
- }
161
-
162
- throw new FileSystemError(`Failed to write JSON file: ${error.message}`, error);
163
- }
164
- }, 'FILE_SYSTEM_ERROR', { function: 'saveAsJson' });
165
- }
166
-
167
- /**
168
- * Synchronously saves JSON data to a file
169
- *
170
- * @param {*} data - Data to save as JSON
171
- * @param {string} filePath - Path to save the JSON file
172
- * @param {Object} [options] - Configuration options (same as saveAsJson)
173
- * @returns {string} Path to saved file
174
- */
175
- function saveAsJsonSync(data, filePath, options = {}) {
176
- return safeExecute(() => {
177
- const fs = require('fs');
178
-
179
- // Validate file path
180
- const safePath = validateJsonFilePath(filePath);
181
-
182
- // Validate data and options
183
- validateJsonData(data, options);
184
-
185
- const opts = options && typeof options === 'object' ? options : {};
186
- const {
187
- prettyPrint = false,
188
- maxSize = 10485760 // 10MB default limit
189
- } = opts;
190
-
191
- // Convert data to JSON string
192
- let jsonString;
193
- try {
194
- if (prettyPrint) {
195
- jsonString = JSON.stringify(data, null, 2);
196
- } else {
197
- jsonString = JSON.stringify(data);
198
- }
199
- } catch (error) {
200
- if (error.message.includes('circular') || error.message.includes('Converting circular')) {
201
- throw new ValidationError('Data contains circular references');
202
- }
203
- throw new ValidationError(`Failed to stringify JSON: ${error.message}`);
204
- }
205
-
206
- // Check size limit
207
- const byteSize = Buffer.byteLength(jsonString, 'utf8');
208
- if (byteSize > maxSize) {
209
- throw new LimitError(
210
- `JSON size exceeds maximum limit of ${maxSize} bytes`,
211
- maxSize,
212
- byteSize
213
- );
214
- }
215
-
216
- // Ensure directory exists
217
- const dir = require('path').dirname(safePath);
218
-
219
- try {
220
- if (!fs.existsSync(dir)) {
221
- fs.mkdirSync(dir, { recursive: true });
222
- }
223
-
224
- // Write file
225
- fs.writeFileSync(safePath, jsonString, 'utf8');
226
-
227
- return safePath;
228
- } catch (error) {
229
- if (error.code === 'ENOENT') {
230
- throw new FileSystemError(`Directory does not exist: ${dir}`, error);
231
- }
232
- if (error.code === 'EACCES') {
233
- throw new FileSystemError(`Permission denied: ${safePath}`, error);
234
- }
235
- if (error.code === 'ENOSPC') {
236
- throw new FileSystemError(`No space left on device: ${safePath}`, error);
237
- }
238
-
239
- throw new FileSystemError(`Failed to write JSON file: ${error.message}`, error);
240
- }
241
- }, 'FILE_SYSTEM_ERROR', { function: 'saveAsJsonSync' });
242
- }
243
-
244
- // Export the functions
245
- module.exports = {
246
- saveAsJson,
247
- saveAsJsonSync,
248
- validateJsonFilePath
249
- };
250
-
251
- // For ES6 module compatibility
252
- /* istanbul ignore next */
253
- if (typeof module !== 'undefined' && module.exports) {
254
- module.exports.default = saveAsJson;
255
- }