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.
- package/README.md +204 -115
- package/bin/jtcsv.ts +2612 -0
- package/browser.d.ts +142 -0
- package/dist/benchmark.js +446 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/bin/jtcsv.js +1940 -0
- package/dist/bin/jtcsv.js.map +1 -0
- package/dist/csv-to-json.js +1262 -0
- package/dist/csv-to-json.js.map +1 -0
- package/dist/errors.js +291 -0
- package/dist/errors.js.map +1 -0
- package/dist/eslint.config.js +147 -0
- package/dist/eslint.config.js.map +1 -0
- package/dist/index-core.js +95 -0
- package/dist/index-core.js.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/json-save.js +229 -0
- package/dist/json-save.js.map +1 -0
- package/dist/json-to-csv.js +576 -0
- package/dist/json-to-csv.js.map +1 -0
- package/dist/jtcsv-core.cjs.js +1736 -0
- package/dist/jtcsv-core.cjs.js.map +1 -0
- package/dist/jtcsv-core.esm.js +1708 -0
- package/dist/jtcsv-core.esm.js.map +1 -0
- package/dist/jtcsv-core.umd.js +1742 -0
- package/dist/jtcsv-core.umd.js.map +1 -0
- package/dist/jtcsv-full.cjs.js +2241 -0
- package/dist/jtcsv-full.cjs.js.map +1 -0
- package/dist/jtcsv-full.esm.js +2209 -0
- package/dist/jtcsv-full.esm.js.map +1 -0
- package/dist/jtcsv-full.umd.js +2247 -0
- package/dist/jtcsv-full.umd.js.map +1 -0
- package/dist/jtcsv-workers.esm.js +768 -0
- package/dist/jtcsv-workers.esm.js.map +1 -0
- package/dist/jtcsv-workers.umd.js +782 -0
- package/dist/jtcsv-workers.umd.js.map +1 -0
- package/dist/jtcsv.cjs.js +1996 -2048
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +1992 -2048
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +2157 -2209
- package/dist/jtcsv.umd.js.map +1 -1
- package/dist/plugins/express-middleware/index.js +350 -0
- package/dist/plugins/express-middleware/index.js.map +1 -0
- package/dist/plugins/fastify-plugin/index.js +315 -0
- package/dist/plugins/fastify-plugin/index.js.map +1 -0
- package/dist/plugins/hono/index.js +111 -0
- package/dist/plugins/hono/index.js.map +1 -0
- package/dist/plugins/nestjs/index.js +112 -0
- package/dist/plugins/nestjs/index.js.map +1 -0
- package/dist/plugins/nuxt/index.js +53 -0
- package/dist/plugins/nuxt/index.js.map +1 -0
- package/dist/plugins/remix/index.js +133 -0
- package/dist/plugins/remix/index.js.map +1 -0
- package/dist/plugins/sveltekit/index.js +155 -0
- package/dist/plugins/sveltekit/index.js.map +1 -0
- package/dist/plugins/trpc/index.js +136 -0
- package/dist/plugins/trpc/index.js.map +1 -0
- package/dist/run-demo.js +49 -0
- package/dist/run-demo.js.map +1 -0
- package/dist/src/browser/browser-functions.js +193 -0
- package/dist/src/browser/browser-functions.js.map +1 -0
- package/dist/src/browser/core.js +123 -0
- package/dist/src/browser/core.js.map +1 -0
- package/dist/src/browser/csv-to-json-browser.js +353 -0
- package/dist/src/browser/csv-to-json-browser.js.map +1 -0
- package/dist/src/browser/errors-browser.js +219 -0
- package/dist/src/browser/errors-browser.js.map +1 -0
- package/dist/src/browser/extensions/plugins.js +106 -0
- package/dist/src/browser/extensions/plugins.js.map +1 -0
- package/dist/src/browser/extensions/workers.js +66 -0
- package/dist/src/browser/extensions/workers.js.map +1 -0
- package/dist/src/browser/index.js +140 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/browser/json-to-csv-browser.js +225 -0
- package/dist/src/browser/json-to-csv-browser.js.map +1 -0
- package/dist/src/browser/streams.js +340 -0
- package/dist/src/browser/streams.js.map +1 -0
- package/dist/src/browser/workers/csv-parser.worker.js +264 -0
- package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/browser/workers/worker-pool.js +338 -0
- package/dist/src/browser/workers/worker-pool.js.map +1 -0
- package/dist/src/core/delimiter-cache.js +196 -0
- package/dist/src/core/delimiter-cache.js.map +1 -0
- package/dist/src/core/node-optimizations.js +279 -0
- package/dist/src/core/node-optimizations.js.map +1 -0
- package/dist/src/core/plugin-system.js +399 -0
- package/dist/src/core/plugin-system.js.map +1 -0
- package/dist/src/core/transform-hooks.js +348 -0
- package/dist/src/core/transform-hooks.js.map +1 -0
- package/dist/src/engines/fast-path-engine-new.js +262 -0
- package/dist/src/engines/fast-path-engine-new.js.map +1 -0
- package/dist/src/engines/fast-path-engine.js +671 -0
- package/dist/src/engines/fast-path-engine.js.map +1 -0
- package/dist/src/errors.js +18 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/formats/ndjson-parser.js +332 -0
- package/dist/src/formats/ndjson-parser.js.map +1 -0
- package/dist/src/formats/tsv-parser.js +230 -0
- package/dist/src/formats/tsv-parser.js.map +1 -0
- package/dist/src/index-with-plugins.js +259 -0
- package/dist/src/index-with-plugins.js.map +1 -0
- package/dist/src/types/index.js +3 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/bom-utils.js +267 -0
- package/dist/src/utils/bom-utils.js.map +1 -0
- package/dist/src/utils/encoding-support.js +77 -0
- package/dist/src/utils/encoding-support.js.map +1 -0
- package/dist/src/utils/schema-validator.js +609 -0
- package/dist/src/utils/schema-validator.js.map +1 -0
- package/dist/src/utils/transform-loader.js +281 -0
- package/dist/src/utils/transform-loader.js.map +1 -0
- package/dist/src/utils/validators.js +40 -0
- package/dist/src/utils/validators.js.map +1 -0
- package/dist/src/utils/zod-adapter.js +144 -0
- package/dist/src/utils/zod-adapter.js.map +1 -0
- package/dist/src/web-server/index.js +648 -0
- package/dist/src/web-server/index.js.map +1 -0
- package/dist/src/workers/csv-multithreaded.js +211 -0
- package/dist/src/workers/csv-multithreaded.js.map +1 -0
- package/dist/src/workers/csv-parser.worker.js +179 -0
- package/dist/src/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/workers/worker-pool.js +228 -0
- package/dist/src/workers/worker-pool.js.map +1 -0
- package/dist/stream-csv-to-json.js +665 -0
- package/dist/stream-csv-to-json.js.map +1 -0
- package/dist/stream-json-to-csv.js +389 -0
- package/dist/stream-json-to-csv.js.map +1 -0
- package/examples/advanced/conditional-transformations.ts +446 -0
- package/examples/advanced/csv-parser.worker.ts +89 -0
- package/examples/advanced/nested-objects-example.ts +306 -0
- package/examples/advanced/performance-optimization.ts +504 -0
- package/examples/advanced/run-demo-server.ts +116 -0
- package/examples/advanced/web-worker-usage.html +874 -0
- package/examples/async-multithreaded-example.ts +335 -0
- package/examples/cli-advanced-usage.md +290 -0
- package/examples/{cli-batch-processing.js ā cli-batch-processing.ts} +38 -38
- package/examples/{cli-tool.js ā cli-tool.ts} +5 -8
- package/examples/{error-handling.js ā error-handling.ts} +356 -324
- package/examples/{express-api.js ā express-api.ts} +161 -164
- package/examples/{large-dataset-example.js ā large-dataset-example.ts} +201 -182
- package/examples/{ndjson-processing.js ā ndjson-processing.ts} +456 -434
- package/examples/{plugin-excel-exporter.js ā plugin-excel-exporter.ts} +6 -7
- package/examples/react-integration.tsx +637 -0
- package/examples/{schema-validation.js ā schema-validation.ts} +2 -2
- package/examples/simple-usage.ts +194 -0
- package/examples/{streaming-example.js ā streaming-example.ts} +12 -12
- package/index.d.ts +187 -18
- package/package.json +75 -81
- package/plugins.d.ts +37 -0
- package/schema.d.ts +103 -0
- package/src/browser/browser-functions.ts +402 -0
- package/src/browser/core.ts +152 -0
- package/src/browser/csv-to-json-browser.d.ts +3 -0
- package/src/browser/csv-to-json-browser.ts +494 -0
- package/src/browser/{errors-browser.js ā errors-browser.ts} +305 -197
- package/src/browser/extensions/plugins.ts +93 -0
- package/src/browser/extensions/workers.ts +39 -0
- package/src/browser/globals.d.ts +5 -0
- package/src/browser/index.ts +192 -0
- package/src/browser/json-to-csv-browser.d.ts +3 -0
- package/src/browser/json-to-csv-browser.ts +338 -0
- package/src/browser/streams.ts +403 -0
- package/src/browser/workers/{csv-parser.worker.js ā csv-parser.worker.ts} +3 -3
- package/src/browser/workers/{worker-pool.js ā worker-pool.ts} +51 -30
- package/src/core/delimiter-cache.ts +320 -0
- package/src/core/{node-optimizations.js ā node-optimizations.ts} +448 -407
- package/src/core/plugin-system.ts +588 -0
- package/src/core/transform-hooks.ts +566 -0
- package/src/engines/{fast-path-engine-new.js ā fast-path-engine-new.ts} +11 -2
- package/src/engines/{fast-path-engine.js ā fast-path-engine.ts} +79 -53
- package/src/errors.ts +1 -0
- package/src/formats/{ndjson-parser.js ā ndjson-parser.ts} +24 -16
- package/src/formats/{tsv-parser.js ā tsv-parser.ts} +18 -17
- package/src/{index-with-plugins.js ā index-with-plugins.ts} +381 -357
- package/src/types/index.ts +275 -0
- package/src/utils/bom-utils.ts +373 -0
- package/src/utils/encoding-support.ts +155 -0
- package/src/utils/{schema-validator.js ā schema-validator.ts} +814 -589
- package/src/utils/transform-loader.ts +389 -0
- package/src/utils/validators.ts +35 -0
- package/src/utils/zod-adapter.ts +280 -0
- package/src/web-server/{index.js ā index.ts} +19 -19
- package/src/workers/csv-multithreaded.ts +310 -0
- package/src/workers/csv-parser.worker.ts +227 -0
- package/src/workers/worker-pool.ts +409 -0
- package/bin/jtcsv.js +0 -2462
- package/csv-to-json.js +0 -688
- package/errors.js +0 -208
- package/examples/simple-usage.js +0 -282
- package/index.js +0 -68
- package/json-save.js +0 -254
- package/json-to-csv.js +0 -526
- package/plugins/README.md +0 -91
- package/plugins/express-middleware/README.md +0 -64
- package/plugins/express-middleware/example.js +0 -136
- package/plugins/express-middleware/index.d.ts +0 -114
- package/plugins/express-middleware/index.js +0 -360
- package/plugins/express-middleware/package.json +0 -52
- package/plugins/fastify-plugin/index.js +0 -406
- package/plugins/fastify-plugin/package.json +0 -55
- package/plugins/hono/README.md +0 -28
- package/plugins/hono/index.d.ts +0 -12
- package/plugins/hono/index.js +0 -36
- package/plugins/hono/package.json +0 -35
- package/plugins/nestjs/README.md +0 -35
- package/plugins/nestjs/index.d.ts +0 -25
- package/plugins/nestjs/index.js +0 -77
- package/plugins/nestjs/package.json +0 -37
- package/plugins/nextjs-api/README.md +0 -57
- package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
- package/plugins/nextjs-api/examples/api-convert.js +0 -69
- package/plugins/nextjs-api/index.js +0 -387
- package/plugins/nextjs-api/package.json +0 -63
- package/plugins/nextjs-api/route.js +0 -371
- package/plugins/nuxt/README.md +0 -24
- package/plugins/nuxt/index.js +0 -21
- package/plugins/nuxt/package.json +0 -35
- package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
- package/plugins/nuxt/runtime/plugin.js +0 -6
- package/plugins/remix/README.md +0 -26
- package/plugins/remix/index.d.ts +0 -16
- package/plugins/remix/index.js +0 -62
- package/plugins/remix/package.json +0 -35
- package/plugins/sveltekit/README.md +0 -28
- package/plugins/sveltekit/index.d.ts +0 -17
- package/plugins/sveltekit/index.js +0 -54
- package/plugins/sveltekit/package.json +0 -33
- package/plugins/trpc/README.md +0 -25
- package/plugins/trpc/index.d.ts +0 -7
- package/plugins/trpc/index.js +0 -32
- package/plugins/trpc/package.json +0 -34
- package/src/browser/browser-functions.js +0 -219
- package/src/browser/csv-to-json-browser.js +0 -700
- package/src/browser/index.js +0 -113
- package/src/browser/json-to-csv-browser.js +0 -309
- package/src/browser/streams.js +0 -393
- package/src/core/delimiter-cache.js +0 -186
- package/src/core/plugin-system.js +0 -476
- package/src/core/transform-hooks.js +0 -350
- package/src/errors.js +0 -26
- package/src/utils/transform-loader.js +0 -205
- package/stream-csv-to-json.js +0 -542
- package/stream-json-to-csv.js +0 -464
- /package/examples/{web-workers-advanced.js ā web-workers-advanced.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-adapter.js","sourceRoot":"","sources":["../../../src/utils/zod-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Zod adapter for JTCSV schema validation.\r\n * \r\n * Provides integration with Zod schemas for CSV validation.\r\n * \r\n * @example\r\n * const { z } = require('zod');\r\n * const { createZodValidationHook } = require('./zod-adapter');\r\n * \r\n * const schema = z.object({\r\n * name: z.string().min(1),\r\n * age: z.number().int().min(0).max(150),\r\n * email: z.string().email()\r\n * });\r\n * \r\n * const validationHook = createZodValidationHook(schema);\r\n * \r\n * // Use with csvToJson\r\n * const data = await csvToJson(csv, {\r\n * hooks: { perRow: validationHook }\r\n * });\r\n */\r\n\r\nimport { ValidationError } from '../errors';\r\n\r\n// Conditional imports for optional dependencies\r\ntype ZodSchema = any;\r\ntype YupSchema = any;\r\n\r\nexport interface ZodValidationOptions {\r\n coerce?: boolean;\r\n mode?: 'strict' | 'collect';\r\n}\r\n\r\nexport interface YupValidationOptions {\r\n abortEarly?: boolean;\r\n stripUnknown?: boolean;\r\n}\r\n\r\nexport interface ValidatedParserOptions {\r\n library?: 'zod' | 'yup';\r\n [key: string]: any;\r\n}\r\n\r\nexport type RowHook = (row: any, index: number, context: any) => any | Promise<any>;\r\n\r\n/**\r\n * Creates a validation hook from a Zod schema.\r\n * \r\n * @param zodSchema - Zod schema instance\r\n * @param options - Validation options\r\n * @param options.coerce - Whether to coerce values according to Zod's coerce (default: true)\r\n * @param options.mode - 'strict' (throw on first error) or 'collect' (collect all errors)\r\n * @returns Validation hook compatible with JTCSV hooks.perRow\r\n */\r\nexport function createZodValidationHook(\r\n zodSchema: ZodSchema,\r\n options: ZodValidationOptions = {}\r\n): RowHook {\r\n const { coerce = true, mode = 'strict' } = options;\r\n \r\n // Check if Zod is available\r\n let zod: any;\r\n try {\r\n zod = require('zod');\r\n } catch (error) {\r\n throw new Error(\r\n 'Zod is not installed. Please install zod: npm install zod'\r\n );\r\n }\r\n \r\n // Ensure the passed schema is a Zod schema\r\n if (!zodSchema || typeof zodSchema.safeParse !== 'function') {\r\n throw new ValidationError('Provided schema is not a valid Zod schema');\r\n }\r\n \r\n // Return hook function\r\n return function (row: any, index: number, context: any): any {\r\n try {\r\n const result = zodSchema.safeParse(row);\r\n \r\n if (!result.success) {\r\n const errors = result.error.errors;\r\n const firstError = errors[0];\r\n const path = firstError.path?.join('.') || '';\r\n const message = firstError.message;\r\n \r\n if (mode === 'strict') {\r\n throw new ValidationError(\r\n `Row ${index + 1}: ${path ? `Field \"${path}\": ` : ''}${message}`\r\n );\r\n } else {\r\n // In collect mode, we attach errors to row metadata\r\n // For simplicity, we still throw but could be extended\r\n console.warn(`Row ${index + 1}: ${path ? `Field \"${path}\": ` : ''}${message}`);\r\n return row;\r\n }\r\n }\r\n \r\n // Return validated (and possibly coerced) data\r\n return result.data;\r\n } catch (error: any) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n // Unexpected error - log and return original row\r\n console.error(`Zod validation error at row ${index}: ${error.message}`);\r\n if (process.env['NODE_ENV'] === 'development') {\r\n console.error(error.stack);\r\n }\r\n return row;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Creates a Yup validation hook.\r\n * \r\n * @param yupSchema - Yup schema instance\r\n * @param options - Validation options\r\n * @returns Validation hook\r\n */\r\nexport function createYupValidationHook(\r\n yupSchema: YupSchema,\r\n options: YupValidationOptions = {}\r\n): RowHook {\r\n const { abortEarly = false, stripUnknown = true } = options;\r\n \r\n // Check if Yup is available\r\n let yup: any;\r\n try {\r\n yup = require('yup');\r\n } catch (error) {\r\n throw new Error(\r\n 'Yup is not installed. Please install yup: npm install yup'\r\n );\r\n }\r\n \r\n if (!yupSchema || typeof yupSchema.validate !== 'function') {\r\n throw new ValidationError('Provided schema is not a valid Yup schema');\r\n }\r\n \r\n return async function (row: any, index: number, context: any): Promise<any> {\r\n try {\r\n const validated = await yupSchema.validate(row, { abortEarly, stripUnknown });\r\n return validated;\r\n } catch (error: any) {\r\n if (error.name === 'ValidationError') {\r\n throw new ValidationError(`Row ${index + 1}: ${error.message}`);\r\n }\r\n console.error(`Yup validation error at row ${index}: ${error.message}`);\r\n return row;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Higher-order function that creates a csvToJson wrapper with schema validation.\r\n * \r\n * @param schema - Zod or Yup schema\r\n * @param adapterOptions - Adapter-specific options\r\n * @returns Function that takes csv and options, returns validated data\r\n */\r\nexport function createValidatedParser(\r\n schema: ZodSchema | YupSchema,\r\n adapterOptions: ValidatedParserOptions = {}\r\n): (csv: string, parseOptions?: any) => Promise<any[]> {\r\n const { library = 'zod', ...options } = adapterOptions;\r\n \r\n let validationHook: RowHook;\r\n if (library === 'zod') {\r\n validationHook = createZodValidationHook(schema as ZodSchema, options);\r\n } else if (library === 'yup') {\r\n validationHook = createYupValidationHook(schema as YupSchema, options);\r\n } else {\r\n throw new ValidationError(`Unsupported validation library: ${library}`);\r\n }\r\n \r\n return async function (csv: string, parseOptions: any = {}): Promise<any[]> {\r\n const { csvToJson } = require('../index');\r\n const hooks = parseOptions.hooks || {};\r\n // Merge validation hook with existing perRow hook\r\n const existingPerRow = hooks.perRow;\r\n hooks.perRow = function (row: any, index: number, context: any): any {\r\n let validated = row;\r\n if (existingPerRow) {\r\n validated = existingPerRow(validated, index, context);\r\n }\r\n return validationHook(validated, index, context);\r\n };\r\n \r\n return csvToJson(csv, { ...parseOptions, hooks });\r\n };\r\n}\r\n\r\n/**\r\n * Async version of createValidatedParser that uses worker threads for validation.\r\n * \r\n * @param schema - Zod or Yup schema\r\n * @param adapterOptions - Adapter-specific options\r\n * @returns Async function that validates CSV data in parallel\r\n */\r\nexport function createAsyncValidatedParser(\r\n schema: ZodSchema | YupSchema,\r\n adapterOptions: ValidatedParserOptions = {}\r\n): (csv: string, parseOptions?: any) => Promise<any[]> {\r\n const { library = 'zod', ...options } = adapterOptions;\r\n \r\n return async function (csv: string, parseOptions: any = {}): Promise<any[]> {\r\n const { csvToJson } = require('../index');\r\n const { createWorkerPool } = require('../workers/worker-pool');\r\n \r\n // Create worker pool for parallel validation\r\n const pool = createWorkerPool({\r\n workerCount: Math.min(4, require('os').cpus().length),\r\n workerScript: require.resolve('./validation-worker.js')\r\n });\r\n \r\n try {\r\n // Parse CSV without validation first\r\n const data = await csvToJson(csv, parseOptions);\r\n \r\n // Validate in parallel using worker pool\r\n const validationPromises = data.map((row: any, index: number) => \r\n pool.execute({ row, index, schema, library, options })\r\n );\r\n \r\n const validatedRows = await Promise.all(validationPromises);\r\n return validatedRows;\r\n } finally {\r\n await pool.terminate();\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Creates a validation hook that works asynchronously with Zod schemas.\r\n * \r\n * @param zodSchema - Zod schema instance\r\n * @param options - Validation options\r\n * @returns Async validation hook\r\n */\r\nexport function createAsyncZodValidationHook(\r\n zodSchema: ZodSchema,\r\n options: ZodValidationOptions = {}\r\n): RowHook {\r\n const hook = createZodValidationHook(zodSchema, options);\r\n \r\n return async function (row: any, index: number, context: any): Promise<any> {\r\n // For async compatibility, wrap in Promise\r\n return Promise.resolve(hook(row, index, context));\r\n };\r\n}\r\n\r\n/**\r\n * Creates a validation hook that works asynchronously with Yup schemas.\r\n * \r\n * @param yupSchema - Yup schema instance\r\n * @param options - Validation options\r\n * @returns Async validation hook\r\n */\r\nexport function createAsyncYupValidationHook(\r\n yupSchema: YupSchema,\r\n options: YupValidationOptions = {}\r\n): RowHook {\r\n const hook = createYupValidationHook(yupSchema, options);\r\n \r\n return async function (row: any, index: number, context: any): Promise<any> {\r\n return hook(row, index, context);\r\n };\r\n}\r\n\r\nexport default {\r\n createZodValidationHook,\r\n createYupValidationHook,\r\n createValidatedParser,\r\n createAsyncValidatedParser,\r\n createAsyncZodValidationHook,\r\n createAsyncYupValidationHook\r\n};"]}
|
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const http_1 = __importDefault(require("http"));
|
|
40
|
+
const url_1 = __importDefault(require("url"));
|
|
41
|
+
const jtcsv = __importStar(require("../../index"));
|
|
42
|
+
const PORT = process.env.PORT || 3000;
|
|
43
|
+
const HOST = process.env.HOST || 'localhost';
|
|
44
|
+
function parseBody(req) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
let body = '';
|
|
47
|
+
req.on('data', chunk => {
|
|
48
|
+
body += chunk.toString();
|
|
49
|
+
});
|
|
50
|
+
req.on('end', () => {
|
|
51
|
+
try {
|
|
52
|
+
resolve(JSON.parse(body));
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
reject(new Error('Invalid JSON'));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
req.on('error', reject);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function sendJson(res, statusCode, data) {
|
|
62
|
+
res.statusCode = statusCode;
|
|
63
|
+
res.setHeader('Content-Type', 'application/json');
|
|
64
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
65
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
66
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
67
|
+
res.end(JSON.stringify(data));
|
|
68
|
+
}
|
|
69
|
+
function sendError(res, statusCode, message) {
|
|
70
|
+
sendJson(res, statusCode, {
|
|
71
|
+
success: false,
|
|
72
|
+
error: message
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function handleJsonToCsv(req, res) {
|
|
76
|
+
try {
|
|
77
|
+
const body = await parseBody(req);
|
|
78
|
+
const { data, options = {} } = body;
|
|
79
|
+
if (!Array.isArray(data)) {
|
|
80
|
+
return sendError(res, 400, 'Data must be an array of objects');
|
|
81
|
+
}
|
|
82
|
+
const csv = jtcsv.jsonToCsv(data, {
|
|
83
|
+
delimiter: options.delimiter || ',',
|
|
84
|
+
includeHeaders: options.includeHeaders !== false,
|
|
85
|
+
preventCsvInjection: options.preventCsvInjection !== false,
|
|
86
|
+
rfc4180Compliant: options.rfc4180Compliant !== false
|
|
87
|
+
});
|
|
88
|
+
sendJson(res, 200, {
|
|
89
|
+
success: true,
|
|
90
|
+
result: csv,
|
|
91
|
+
records: data.length,
|
|
92
|
+
bytes: csv.length
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
sendError(res, 500, error.message);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function handleCsvToJson(req, res) {
|
|
100
|
+
try {
|
|
101
|
+
const body = await parseBody(req);
|
|
102
|
+
const { data, options = {} } = body;
|
|
103
|
+
if (typeof data !== 'string') {
|
|
104
|
+
return sendError(res, 400, 'Data must be a CSV string');
|
|
105
|
+
}
|
|
106
|
+
const json = jtcsv.csvToJson(data, {
|
|
107
|
+
delimiter: options.delimiter,
|
|
108
|
+
autoDetect: options.autoDetect !== false,
|
|
109
|
+
hasHeaders: options.hasHeaders !== false,
|
|
110
|
+
trim: options.trim !== false,
|
|
111
|
+
parseNumbers: options.parseNumbers === true,
|
|
112
|
+
parseBooleans: options.parseBooleans === true
|
|
113
|
+
});
|
|
114
|
+
sendJson(res, 200, {
|
|
115
|
+
success: true,
|
|
116
|
+
result: json,
|
|
117
|
+
rows: json.length
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
sendError(res, 500, error.message);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function handleValidate(req, res) {
|
|
125
|
+
try {
|
|
126
|
+
const body = await parseBody(req);
|
|
127
|
+
const { data, format } = body;
|
|
128
|
+
let isValid = false;
|
|
129
|
+
const errors = [];
|
|
130
|
+
if (format === 'json') {
|
|
131
|
+
if (Array.isArray(data)) {
|
|
132
|
+
isValid = data.every(item => typeof item === 'object' && item !== null);
|
|
133
|
+
if (!isValid) {
|
|
134
|
+
errors.push('All items must be objects');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
errors.push('Data must be an array');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (format === 'csv') {
|
|
142
|
+
if (typeof data === 'string') {
|
|
143
|
+
try {
|
|
144
|
+
const parsed = jtcsv.csvToJson(data);
|
|
145
|
+
isValid = Array.isArray(parsed) && parsed.length > 0;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
errors.push(error.message);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
errors.push('Data must be a string');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
errors.push('Format must be "json" or "csv"');
|
|
157
|
+
}
|
|
158
|
+
sendJson(res, 200, {
|
|
159
|
+
success: true,
|
|
160
|
+
valid: isValid,
|
|
161
|
+
errors: errors
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
sendError(res, 500, error.message);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function handleNdjsonToCsv(req, res) {
|
|
169
|
+
try {
|
|
170
|
+
const body = await parseBody(req);
|
|
171
|
+
const { data, options = {} } = body;
|
|
172
|
+
if (typeof data !== 'string') {
|
|
173
|
+
return sendError(res, 400, 'Data must be an NDJSON string');
|
|
174
|
+
}
|
|
175
|
+
const json = jtcsv.ndjsonToJson(data);
|
|
176
|
+
const csv = jtcsv.jsonToCsv(json, {
|
|
177
|
+
delimiter: options.delimiter || ',',
|
|
178
|
+
includeHeaders: options.includeHeaders !== false
|
|
179
|
+
});
|
|
180
|
+
sendJson(res, 200, {
|
|
181
|
+
success: true,
|
|
182
|
+
result: csv,
|
|
183
|
+
records: json.length
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
sendError(res, 500, error.message);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function handleCsvToNdjson(req, res) {
|
|
191
|
+
try {
|
|
192
|
+
const body = await parseBody(req);
|
|
193
|
+
const { data, options = {} } = body;
|
|
194
|
+
if (typeof data !== 'string') {
|
|
195
|
+
return sendError(res, 400, 'Data must be a CSV string');
|
|
196
|
+
}
|
|
197
|
+
const json = jtcsv.csvToJson(data, {
|
|
198
|
+
delimiter: options.delimiter,
|
|
199
|
+
autoDetect: options.autoDetect !== false,
|
|
200
|
+
hasHeaders: options.hasHeaders !== false
|
|
201
|
+
});
|
|
202
|
+
const ndjson = jtcsv.jsonToNdjson(json);
|
|
203
|
+
sendJson(res, 200, {
|
|
204
|
+
success: true,
|
|
205
|
+
result: ndjson,
|
|
206
|
+
records: json.length
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
sendError(res, 500, error.message);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function serveHomePage(res) {
|
|
214
|
+
const html = `<!DOCTYPE html>
|
|
215
|
+
<html lang="en">
|
|
216
|
+
<head>
|
|
217
|
+
<meta charset="UTF-8">
|
|
218
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
219
|
+
<title>JTCSV Web Interface</title>
|
|
220
|
+
<style>
|
|
221
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
222
|
+
body {
|
|
223
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
224
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
225
|
+
min-height: 100vh;
|
|
226
|
+
padding: 20px;
|
|
227
|
+
}
|
|
228
|
+
.container {
|
|
229
|
+
max-width: 1200px;
|
|
230
|
+
margin: 0 auto;
|
|
231
|
+
background: white;
|
|
232
|
+
border-radius: 12px;
|
|
233
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
234
|
+
overflow: hidden;
|
|
235
|
+
}
|
|
236
|
+
.header {
|
|
237
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
238
|
+
color: white;
|
|
239
|
+
padding: 30px;
|
|
240
|
+
text-align: center;
|
|
241
|
+
}
|
|
242
|
+
.header h1 { font-size: 2.5em; margin-bottom: 10px; }
|
|
243
|
+
.header p { font-size: 1.1em; opacity: 0.9; }
|
|
244
|
+
.main { padding: 30px; }
|
|
245
|
+
.controls {
|
|
246
|
+
display: grid;
|
|
247
|
+
grid-template-columns: 1fr 1fr;
|
|
248
|
+
gap: 20px;
|
|
249
|
+
margin-bottom: 20px;
|
|
250
|
+
}
|
|
251
|
+
.control-group {
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-direction: column;
|
|
254
|
+
gap: 8px;
|
|
255
|
+
}
|
|
256
|
+
label {
|
|
257
|
+
font-weight: 600;
|
|
258
|
+
color: #333;
|
|
259
|
+
font-size: 0.9em;
|
|
260
|
+
}
|
|
261
|
+
select, input, button {
|
|
262
|
+
padding: 12px;
|
|
263
|
+
border: 2px solid #e0e0e0;
|
|
264
|
+
border-radius: 6px;
|
|
265
|
+
font-size: 1em;
|
|
266
|
+
transition: border-color 0.3s;
|
|
267
|
+
}
|
|
268
|
+
select:focus, input:focus {
|
|
269
|
+
outline: none;
|
|
270
|
+
border-color: #667eea;
|
|
271
|
+
}
|
|
272
|
+
.textarea-group {
|
|
273
|
+
display: grid;
|
|
274
|
+
grid-template-columns: 1fr 1fr;
|
|
275
|
+
gap: 20px;
|
|
276
|
+
margin-bottom: 20px;
|
|
277
|
+
}
|
|
278
|
+
.textarea-wrapper { display: flex; flex-direction: column; }
|
|
279
|
+
.textarea-wrapper label { margin-bottom: 8px; }
|
|
280
|
+
textarea {
|
|
281
|
+
width: 100%;
|
|
282
|
+
height: 300px;
|
|
283
|
+
padding: 12px;
|
|
284
|
+
border: 2px solid #e0e0e0;
|
|
285
|
+
border-radius: 6px;
|
|
286
|
+
font-family: 'Courier New', monospace;
|
|
287
|
+
font-size: 0.9em;
|
|
288
|
+
resize: vertical;
|
|
289
|
+
transition: border-color 0.3s;
|
|
290
|
+
}
|
|
291
|
+
textarea:focus {
|
|
292
|
+
outline: none;
|
|
293
|
+
border-color: #667eea;
|
|
294
|
+
}
|
|
295
|
+
.button-group {
|
|
296
|
+
display: flex;
|
|
297
|
+
gap: 15px;
|
|
298
|
+
justify-content: center;
|
|
299
|
+
margin-bottom: 20px;
|
|
300
|
+
}
|
|
301
|
+
button {
|
|
302
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
303
|
+
color: white;
|
|
304
|
+
border: none;
|
|
305
|
+
padding: 14px 30px;
|
|
306
|
+
font-weight: 600;
|
|
307
|
+
cursor: pointer;
|
|
308
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
309
|
+
}
|
|
310
|
+
button:hover {
|
|
311
|
+
transform: translateY(-2px);
|
|
312
|
+
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
|
313
|
+
}
|
|
314
|
+
button:disabled {
|
|
315
|
+
opacity: 0.6;
|
|
316
|
+
cursor: not-allowed;
|
|
317
|
+
transform: none;
|
|
318
|
+
}
|
|
319
|
+
.info-box {
|
|
320
|
+
background: #f5f5f5;
|
|
321
|
+
padding: 15px;
|
|
322
|
+
border-radius: 6px;
|
|
323
|
+
border-left: 4px solid #667eea;
|
|
324
|
+
margin-bottom: 20px;
|
|
325
|
+
font-size: 0.9em;
|
|
326
|
+
color: #666;
|
|
327
|
+
}
|
|
328
|
+
.error {
|
|
329
|
+
background: #fee;
|
|
330
|
+
border-left-color: #f44;
|
|
331
|
+
color: #c33;
|
|
332
|
+
}
|
|
333
|
+
.success {
|
|
334
|
+
background: #efe;
|
|
335
|
+
border-left-color: #4a4;
|
|
336
|
+
color: #363;
|
|
337
|
+
}
|
|
338
|
+
.stats {
|
|
339
|
+
display: grid;
|
|
340
|
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
341
|
+
gap: 15px;
|
|
342
|
+
margin-top: 20px;
|
|
343
|
+
}
|
|
344
|
+
.stat-card {
|
|
345
|
+
background: #f9f9f9;
|
|
346
|
+
padding: 15px;
|
|
347
|
+
border-radius: 6px;
|
|
348
|
+
text-align: center;
|
|
349
|
+
}
|
|
350
|
+
.stat-value {
|
|
351
|
+
font-size: 2em;
|
|
352
|
+
font-weight: bold;
|
|
353
|
+
color: #667eea;
|
|
354
|
+
}
|
|
355
|
+
.stat-label {
|
|
356
|
+
font-size: 0.85em;
|
|
357
|
+
color: #666;
|
|
358
|
+
margin-top: 5px;
|
|
359
|
+
}
|
|
360
|
+
</style>
|
|
361
|
+
</head>
|
|
362
|
+
<body>
|
|
363
|
+
<div class="container">
|
|
364
|
+
<div class="header">
|
|
365
|
+
<h1>š JTCSV Web Interface</h1>
|
|
366
|
+
<p>High-performance CSV ā JSON converter</p>
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<div class="main">
|
|
370
|
+
<div class="controls">
|
|
371
|
+
<div class="control-group">
|
|
372
|
+
<label for="operation">Operation:</label>
|
|
373
|
+
<select id="operation">
|
|
374
|
+
<option value="json-to-csv">JSON ā CSV</option>
|
|
375
|
+
<option value="csv-to-json">CSV ā JSON</option>
|
|
376
|
+
<option value="ndjson-to-csv">NDJSON ā CSV</option>
|
|
377
|
+
<option value="csv-to-ndjson">CSV ā NDJSON</option>
|
|
378
|
+
</select>
|
|
379
|
+
</div>
|
|
380
|
+
|
|
381
|
+
<div class="control-group">
|
|
382
|
+
<label for="delimiter">CSV Delimiter:</label>
|
|
383
|
+
<select id="delimiter">
|
|
384
|
+
<option value=",">Comma (,)</option>
|
|
385
|
+
<option value=";">Semicolon (;)</option>
|
|
386
|
+
<option value="\t">Tab</option>
|
|
387
|
+
<option value="|">Pipe (|)</option>
|
|
388
|
+
</select>
|
|
389
|
+
</div>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
<div class="control-group" style="margin-bottom: 20px;">
|
|
393
|
+
<label>
|
|
394
|
+
<input type="checkbox" id="parseNumbers" style="width: auto; margin-right: 8px;">
|
|
395
|
+
Parse Numbers (CSV ā JSON)
|
|
396
|
+
</label>
|
|
397
|
+
<label>
|
|
398
|
+
<input type="checkbox" id="parseBooleans" style="width: auto; margin-right: 8px;">
|
|
399
|
+
Parse Booleans (CSV ā JSON)
|
|
400
|
+
</label>
|
|
401
|
+
<label>
|
|
402
|
+
<input type="checkbox" id="includeHeaders" checked style="width: auto; margin-right: 8px;">
|
|
403
|
+
Include Headers (JSON ā CSV)
|
|
404
|
+
</label>
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<div class="textarea-group">
|
|
408
|
+
<div class="textarea-wrapper">
|
|
409
|
+
<label for="input">Input:</label>
|
|
410
|
+
<textarea id="input" placeholder="Paste your JSON or CSV data here..."></textarea>
|
|
411
|
+
</div>
|
|
412
|
+
|
|
413
|
+
<div class="textarea-wrapper">
|
|
414
|
+
<label for="output">Output:</label>
|
|
415
|
+
<textarea id="output" placeholder="Converted data will appear here..." readonly></textarea>
|
|
416
|
+
</div>
|
|
417
|
+
</div>
|
|
418
|
+
|
|
419
|
+
<div class="button-group">
|
|
420
|
+
<button id="convertBtn">Convert</button>
|
|
421
|
+
<button id="clearBtn" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">Clear</button>
|
|
422
|
+
<button id="copyBtn" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">Copy Output</button>
|
|
423
|
+
</div>
|
|
424
|
+
|
|
425
|
+
<div id="messageBox" style="display: none;"></div>
|
|
426
|
+
|
|
427
|
+
<div class="stats" id="stats" style="display: none;">
|
|
428
|
+
<div class="stat-card">
|
|
429
|
+
<div class="stat-value" id="recordsCount">0</div>
|
|
430
|
+
<div class="stat-label">Records</div>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="stat-card">
|
|
433
|
+
<div class="stat-value" id="bytesCount">0</div>
|
|
434
|
+
<div class="stat-label">Bytes</div>
|
|
435
|
+
</div>
|
|
436
|
+
<div class="stat-card">
|
|
437
|
+
<div class="stat-value" id="timeCount">0</div>
|
|
438
|
+
<div class="stat-label">ms</div>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
|
|
444
|
+
<script>
|
|
445
|
+
const API_URL = 'http://${HOST}:${PORT}/api';
|
|
446
|
+
|
|
447
|
+
const elements = {
|
|
448
|
+
operation: document.getElementById('operation'),
|
|
449
|
+
delimiter: document.getElementById('delimiter'),
|
|
450
|
+
parseNumbers: document.getElementById('parseNumbers'),
|
|
451
|
+
parseBooleans: document.getElementById('parseBooleans'),
|
|
452
|
+
includeHeaders: document.getElementById('includeHeaders'),
|
|
453
|
+
input: document.getElementById('input'),
|
|
454
|
+
output: document.getElementById('output'),
|
|
455
|
+
convertBtn: document.getElementById('convertBtn'),
|
|
456
|
+
clearBtn: document.getElementById('clearBtn'),
|
|
457
|
+
copyBtn: document.getElementById('copyBtn'),
|
|
458
|
+
messageBox: document.getElementById('messageBox'),
|
|
459
|
+
stats: document.getElementById('stats'),
|
|
460
|
+
recordsCount: document.getElementById('recordsCount'),
|
|
461
|
+
bytesCount: document.getElementById('bytesCount'),
|
|
462
|
+
timeCount: document.getElementById('timeCount')
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
function showMessage(message, type = 'info') {
|
|
466
|
+
elements.messageBox.textContent = message;
|
|
467
|
+
elements.messageBox.className = 'info-box ' + type;
|
|
468
|
+
elements.messageBox.style.display = 'block';
|
|
469
|
+
setTimeout(() => {
|
|
470
|
+
elements.messageBox.style.display = 'none';
|
|
471
|
+
}, 5000);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function updateStats(records, bytes, time) {
|
|
475
|
+
elements.recordsCount.textContent = records || 0;
|
|
476
|
+
elements.bytesCount.textContent = bytes || 0;
|
|
477
|
+
elements.timeCount.textContent = time || 0;
|
|
478
|
+
elements.stats.style.display = 'grid';
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
async function convert() {
|
|
482
|
+
const input = elements.input.value.trim();
|
|
483
|
+
if (!input) {
|
|
484
|
+
showMessage('Please enter input data', 'error');
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
elements.convertBtn.disabled = true;
|
|
489
|
+
elements.convertBtn.textContent = 'Converting...';
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
const operation = elements.operation.value;
|
|
493
|
+
const options = {
|
|
494
|
+
delimiter: elements.delimiter.value,
|
|
495
|
+
parseNumbers: elements.parseNumbers.checked,
|
|
496
|
+
parseBooleans: elements.parseBooleans.checked,
|
|
497
|
+
includeHeaders: elements.includeHeaders.checked
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
let endpoint = '';
|
|
501
|
+
let requestData = {};
|
|
502
|
+
|
|
503
|
+
if (operation === 'json-to-csv') {
|
|
504
|
+
endpoint = '/json-to-csv';
|
|
505
|
+
requestData = { data: JSON.parse(input), options };
|
|
506
|
+
} else if (operation === 'csv-to-json') {
|
|
507
|
+
endpoint = '/csv-to-json';
|
|
508
|
+
requestData = { data: input, options };
|
|
509
|
+
} else if (operation === 'ndjson-to-csv') {
|
|
510
|
+
endpoint = '/ndjson-to-csv';
|
|
511
|
+
requestData = { data: input, options };
|
|
512
|
+
} else if (operation === 'csv-to-ndjson') {
|
|
513
|
+
endpoint = '/csv-to-ndjson';
|
|
514
|
+
requestData = { data: input, options };
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const startTime = Date.now();
|
|
518
|
+
const response = await fetch(API_URL + endpoint, {
|
|
519
|
+
method: 'POST',
|
|
520
|
+
headers: { 'Content-Type': 'application/json' },
|
|
521
|
+
body: JSON.stringify(requestData)
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
const result = await response.json();
|
|
525
|
+
const elapsed = Date.now() - startTime;
|
|
526
|
+
|
|
527
|
+
if (result.success) {
|
|
528
|
+
if (operation.includes('json')) {
|
|
529
|
+
elements.output.value = JSON.stringify(result.result, null, 2);
|
|
530
|
+
} else {
|
|
531
|
+
elements.output.value = result.result;
|
|
532
|
+
}
|
|
533
|
+
showMessage('Conversion successful!', 'success');
|
|
534
|
+
updateStats(result.records || result.rows || 0, result.bytes || 0, elapsed);
|
|
535
|
+
} else {
|
|
536
|
+
showMessage('Error: ' + result.error, 'error');
|
|
537
|
+
}
|
|
538
|
+
} catch (error) {
|
|
539
|
+
showMessage('Error: ' + error.message, 'error');
|
|
540
|
+
} finally {
|
|
541
|
+
elements.convertBtn.disabled = false;
|
|
542
|
+
elements.convertBtn.textContent = 'Convert';
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function clear() {
|
|
547
|
+
elements.input.value = '';
|
|
548
|
+
elements.output.value = '';
|
|
549
|
+
elements.stats.style.display = 'none';
|
|
550
|
+
elements.messageBox.style.display = 'none';
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function copyToClipboard() {
|
|
554
|
+
const output = elements.output.value;
|
|
555
|
+
if (!output) {
|
|
556
|
+
showMessage('Nothing to copy', 'error');
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
navigator.clipboard.writeText(output).then(() => {
|
|
561
|
+
showMessage('Copied to clipboard!', 'success');
|
|
562
|
+
}).catch(() => {
|
|
563
|
+
showMessage('Failed to copy', 'error');
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
elements.convertBtn.addEventListener('click', convert);
|
|
568
|
+
elements.clearBtn.addEventListener('click', clear);
|
|
569
|
+
elements.copyBtn.addEventListener('click', copyToClipboard);
|
|
570
|
+
|
|
571
|
+
// Load example data
|
|
572
|
+
elements.input.value = JSON.stringify([
|
|
573
|
+
{ name: "Alice", age: 30, city: "New York" },
|
|
574
|
+
{ name: "Bob", age: 25, city: "London" },
|
|
575
|
+
{ name: "Charlie", age: 35, city: "Paris" }
|
|
576
|
+
], null, 2);
|
|
577
|
+
</script>
|
|
578
|
+
</body>
|
|
579
|
+
</html>`;
|
|
580
|
+
res.statusCode = 200;
|
|
581
|
+
res.setHeader('Content-Type', 'text/html');
|
|
582
|
+
res.end(html);
|
|
583
|
+
}
|
|
584
|
+
function handleRequest(req, res) {
|
|
585
|
+
const parsedUrl = url_1.default.parse(req.url, true);
|
|
586
|
+
const pathname = parsedUrl.pathname;
|
|
587
|
+
if (req.method === 'OPTIONS') {
|
|
588
|
+
res.statusCode = 204;
|
|
589
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
590
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
591
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
592
|
+
res.end();
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (pathname === '/' && req.method === 'GET') {
|
|
596
|
+
return serveHomePage(res);
|
|
597
|
+
}
|
|
598
|
+
if (req.method === 'POST') {
|
|
599
|
+
if (pathname === '/api/json-to-csv') {
|
|
600
|
+
return handleJsonToCsv(req, res);
|
|
601
|
+
}
|
|
602
|
+
if (pathname === '/api/csv-to-json') {
|
|
603
|
+
return handleCsvToJson(req, res);
|
|
604
|
+
}
|
|
605
|
+
if (pathname === '/api/validate') {
|
|
606
|
+
return handleValidate(req, res);
|
|
607
|
+
}
|
|
608
|
+
if (pathname === '/api/ndjson-to-csv') {
|
|
609
|
+
return handleNdjsonToCsv(req, res);
|
|
610
|
+
}
|
|
611
|
+
if (pathname === '/api/csv-to-ndjson') {
|
|
612
|
+
return handleCsvToNdjson(req, res);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
sendError(res, 404, 'Not found');
|
|
616
|
+
}
|
|
617
|
+
function startServer(options = {}) {
|
|
618
|
+
const port = options.port || PORT;
|
|
619
|
+
const host = options.host || HOST;
|
|
620
|
+
const server = http_1.default.createServer(handleRequest);
|
|
621
|
+
server.listen(port, host, () => {
|
|
622
|
+
console.log('\nš JTCSV Web Server started!');
|
|
623
|
+
console.log(`\nš URL: http://${host}:${port}`);
|
|
624
|
+
console.log('\nš” API Endpoints:');
|
|
625
|
+
console.log(' POST /api/json-to-csv');
|
|
626
|
+
console.log(' POST /api/csv-to-json');
|
|
627
|
+
console.log(' POST /api/ndjson-to-csv');
|
|
628
|
+
console.log(' POST /api/csv-to-ndjson');
|
|
629
|
+
console.log(' POST /api/validate');
|
|
630
|
+
console.log('\n⨠Press Ctrl+C to stop\n');
|
|
631
|
+
});
|
|
632
|
+
server.on('error', (error) => {
|
|
633
|
+
if (error.code === 'EADDRINUSE') {
|
|
634
|
+
console.error(`\nā Error: Port ${port} is already in use`);
|
|
635
|
+
console.error(' Try a different port: jtcsv web --port=3001\n');
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
console.error(`\nā Server error: ${error.message}\n`);
|
|
639
|
+
}
|
|
640
|
+
process.exit(1);
|
|
641
|
+
});
|
|
642
|
+
return server;
|
|
643
|
+
}
|
|
644
|
+
exports.default = { startServer };
|
|
645
|
+
if (require.main === module) {
|
|
646
|
+
startServer();
|
|
647
|
+
}
|
|
648
|
+
//# sourceMappingURL=index.js.map
|