jtcsv 2.1.1 → 2.1.3
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 +20 -2
- package/bin/jtcsv.js +7 -24
- package/examples/simple-usage.js +2 -3
- package/package.json +34 -18
- package/plugins/README.md +146 -2
- package/plugins/hono/README.md +25 -0
- package/plugins/hono/index.d.ts +12 -0
- package/plugins/hono/index.js +36 -0
- package/plugins/hono/package.json +35 -0
- package/plugins/nestjs/README.md +33 -0
- package/plugins/nestjs/index.d.ts +25 -0
- package/plugins/nestjs/index.js +77 -0
- package/plugins/nestjs/package.json +37 -0
- package/plugins/nuxt/README.md +25 -0
- package/plugins/nuxt/index.js +21 -0
- package/plugins/nuxt/package.json +35 -0
- package/plugins/nuxt/runtime/composables/useJtcsv.js +6 -0
- package/plugins/nuxt/runtime/plugin.js +6 -0
- package/plugins/remix/README.md +26 -0
- package/plugins/remix/index.d.ts +16 -0
- package/plugins/remix/index.js +62 -0
- package/plugins/remix/package.json +35 -0
- package/plugins/sveltekit/README.md +28 -0
- package/plugins/sveltekit/index.d.ts +17 -0
- package/plugins/sveltekit/index.js +54 -0
- package/plugins/sveltekit/package.json +33 -0
- package/plugins/trpc/README.md +22 -0
- package/plugins/trpc/index.d.ts +7 -0
- package/plugins/trpc/index.js +32 -0
- package/plugins/trpc/package.json +34 -0
- package/cli-tui.js +0 -1498
package/README.md
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
[jtcsv
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](https://www.npmjs.com/package/jtcsv
|
|
8
8
|
|
|
9
9
|
A lightweight, efficient, and secure library for converting between JSON and CSV formats with full browser support, Web Workers for large files, and streaming capabilities.
|
|
10
|
+
Zero-deps core with optional add-ons (TUI, Excel) for advanced workflows.
|
|
10
11
|
|
|
11
12
|
## ✨ Features
|
|
12
13
|
|
|
13
14
|
### 🚀 Core Features
|
|
14
15
|
- **Bidirectional Conversion**: JSON ↔ CSV with full type preservation
|
|
15
|
-
- **Zero
|
|
16
|
+
- **Zero-Deps Core**: Pure JavaScript/TypeScript core with optional add-ons
|
|
16
17
|
- **TypeScript Support**: Full type definitions included
|
|
17
18
|
- **Security First**: Built-in CSV injection protection
|
|
18
19
|
- **RFC 4180 Compliant**: Proper CSV formatting and escaping
|
|
@@ -37,6 +38,14 @@ A lightweight, efficient, and secure library for converting between JSON and CSV
|
|
|
37
38
|
- **Multiple Formats**: CSV, TSV, Excel-compatible output
|
|
38
39
|
- **Error Handling**: Comprehensive error reporting and recovery
|
|
39
40
|
|
|
41
|
+
### 🔌 Framework Integrations (Optional)
|
|
42
|
+
- **NestJS**: `@jtcsv/nestjs`
|
|
43
|
+
- **Remix**: `@jtcsv/remix`
|
|
44
|
+
- **Nuxt**: `@jtcsv/nuxt`
|
|
45
|
+
- **SvelteKit**: `@jtcsv/sveltekit`
|
|
46
|
+
- **Hono**: `@jtcsv/hono`
|
|
47
|
+
- **tRPC**: `@jtcsv/trpc`
|
|
48
|
+
|
|
40
49
|
## 📦 Installation
|
|
41
50
|
|
|
42
51
|
### Node.js
|
|
@@ -44,6 +53,15 @@ A lightweight, efficient, and secure library for converting between JSON and CSV
|
|
|
44
53
|
npm install jtcsv
|
|
45
54
|
```
|
|
46
55
|
|
|
56
|
+
### Optional add-ons
|
|
57
|
+
```bash
|
|
58
|
+
# Terminal UI
|
|
59
|
+
npm install @jtcsv/tui
|
|
60
|
+
|
|
61
|
+
# Excel plugin
|
|
62
|
+
npm install @jtcsv/excel exceljs
|
|
63
|
+
```
|
|
64
|
+
|
|
47
65
|
### Browser (CDN)
|
|
48
66
|
```html
|
|
49
67
|
<!-- UMD version (global jtcsv variable) -->
|
package/bin/jtcsv.js
CHANGED
|
@@ -47,7 +47,7 @@ ${color('MAIN COMMANDS:', 'bright')}
|
|
|
47
47
|
${color('stream', 'yellow')} Streaming conversion for large files
|
|
48
48
|
${color('batch', 'yellow')} Batch process multiple files
|
|
49
49
|
${color('preprocess', 'magenta')} Preprocess JSON with deep unwrapping
|
|
50
|
-
${color('tui', 'magenta')} Launch Terminal User Interface
|
|
50
|
+
${color('tui', 'magenta')} Launch Terminal User Interface (@jtcsv/tui)
|
|
51
51
|
${color('help', 'blue')} Show this help message
|
|
52
52
|
${color('version', 'blue')} Show version information
|
|
53
53
|
|
|
@@ -1038,34 +1038,17 @@ function parseOptions(args) {
|
|
|
1038
1038
|
|
|
1039
1039
|
async function launchTUI() {
|
|
1040
1040
|
try {
|
|
1041
|
-
// Check if blessed is installed
|
|
1042
|
-
require.resolve('blessed');
|
|
1043
|
-
|
|
1044
1041
|
console.log(color('Launching Terminal User Interface...', 'cyan'));
|
|
1045
1042
|
console.log(color('Press Ctrl+Q to exit', 'dim'));
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
if (stats.size < 100) {
|
|
1052
|
-
console.log(color('⚠️ TUI interface is not fully implemented yet', 'yellow'));
|
|
1053
|
-
console.log(color(' Basic TUI will be started...', 'dim'));
|
|
1054
|
-
|
|
1055
|
-
// Start basic TUI
|
|
1056
|
-
await startBasicTUI();
|
|
1057
|
-
} else {
|
|
1058
|
-
// Import and launch full TUI
|
|
1059
|
-
const JtcsvTUI = require('../cli-tui.js');
|
|
1060
|
-
const tui = new JtcsvTUI();
|
|
1061
|
-
tui.start();
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1043
|
+
|
|
1044
|
+
const JtcsvTUI = require('@jtcsv/tui');
|
|
1045
|
+
const tui = new JtcsvTUI();
|
|
1046
|
+
tui.start();
|
|
1064
1047
|
} catch (error) {
|
|
1065
1048
|
if (error.code === 'MODULE_NOT_FOUND') {
|
|
1066
|
-
console.error(color('Error:
|
|
1049
|
+
console.error(color('Error: @jtcsv/tui is not installed', 'red'));
|
|
1067
1050
|
console.log(color('Install it with:', 'dim'));
|
|
1068
|
-
console.log(color(' npm install
|
|
1051
|
+
console.log(color(' npm install @jtcsv/tui', 'cyan'));
|
|
1069
1052
|
console.log(color('\nOr use the CLI interface instead:', 'dim'));
|
|
1070
1053
|
console.log(color(' jtcsv help', 'cyan'));
|
|
1071
1054
|
} else {
|
package/examples/simple-usage.js
CHANGED
|
@@ -238,8 +238,8 @@ try {
|
|
|
238
238
|
console.log(' examples/plugin-excel-exporter.js');
|
|
239
239
|
} catch (error) {
|
|
240
240
|
console.log('⚠️ Полная интеграция требует дополнительных зависимостей');
|
|
241
|
-
console.log('Установите exceljs для демонстрации Excel плагина:');
|
|
242
|
-
console.log(' npm install exceljs
|
|
241
|
+
console.log('Установите @jtcsv/excel и exceljs для демонстрации Excel плагина:');
|
|
242
|
+
console.log(' npm install @jtcsv/excel exceljs');
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// ============================================================================
|
|
@@ -277,4 +277,3 @@ console.log('✨ JTCSV 2.1.0 - Next Generation JSON/CSV Converter ✨');
|
|
|
277
277
|
console.log('✨'.repeat(30));
|
|
278
278
|
|
|
279
279
|
|
|
280
|
-
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jtcsv",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "Complete JSON
|
|
3
|
+
"version": "2.1.3",
|
|
4
|
+
"description": "Complete JSON<->CSV and CSV<->JSON converter for Node.js and Browser with streaming, security, Web Workers, TypeScript support, and optional ecosystem (zero-deps core)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"browser": "dist/jtcsv.umd.js",
|
|
7
7
|
"module": "dist/jtcsv.esm.js",
|
|
@@ -46,6 +46,36 @@
|
|
|
46
46
|
"require": "./plugins/nextjs-api/route.js",
|
|
47
47
|
"import": "./plugins/nextjs-api/route.js",
|
|
48
48
|
"default": "./plugins/nextjs-api/route.js"
|
|
49
|
+
},
|
|
50
|
+
"./nestjs": {
|
|
51
|
+
"require": "./plugins/nestjs/index.js",
|
|
52
|
+
"import": "./plugins/nestjs/index.js",
|
|
53
|
+
"default": "./plugins/nestjs/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./remix": {
|
|
56
|
+
"require": "./plugins/remix/index.js",
|
|
57
|
+
"import": "./plugins/remix/index.js",
|
|
58
|
+
"default": "./plugins/remix/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./nuxt": {
|
|
61
|
+
"require": "./plugins/nuxt/index.js",
|
|
62
|
+
"import": "./plugins/nuxt/index.js",
|
|
63
|
+
"default": "./plugins/nuxt/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./sveltekit": {
|
|
66
|
+
"require": "./plugins/sveltekit/index.js",
|
|
67
|
+
"import": "./plugins/sveltekit/index.js",
|
|
68
|
+
"default": "./plugins/sveltekit/index.js"
|
|
69
|
+
},
|
|
70
|
+
"./hono": {
|
|
71
|
+
"require": "./plugins/hono/index.js",
|
|
72
|
+
"import": "./plugins/hono/index.js",
|
|
73
|
+
"default": "./plugins/hono/index.js"
|
|
74
|
+
},
|
|
75
|
+
"./trpc": {
|
|
76
|
+
"require": "./plugins/trpc/index.js",
|
|
77
|
+
"import": "./plugins/trpc/index.js",
|
|
78
|
+
"default": "./plugins/trpc/index.js"
|
|
49
79
|
}
|
|
50
80
|
},
|
|
51
81
|
"scripts": {
|
|
@@ -65,7 +95,7 @@
|
|
|
65
95
|
"lint:plugins": "eslint plugins/",
|
|
66
96
|
"security-check": "npm audit",
|
|
67
97
|
"prepublishOnly": "npm test && npm run build && eslint index.js json-to-csv.js csv-to-json.js errors.js stream-json-to-csv.js stream-csv-to-json.js json-save.js src/browser src/engines src/formats src/core",
|
|
68
|
-
"tui": "node
|
|
98
|
+
"tui": "node packages/jtcsv-tui/bin/jtcsv-tui.js",
|
|
69
99
|
"cli": "node bin/jtcsv.js",
|
|
70
100
|
"build": "rollup -c rollup.config.mjs",
|
|
71
101
|
"build:watch": "rollup -c rollup.config.mjs -w",
|
|
@@ -156,7 +186,6 @@
|
|
|
156
186
|
"json-save.js",
|
|
157
187
|
"index.d.ts",
|
|
158
188
|
"bin/",
|
|
159
|
-
"cli-tui.js",
|
|
160
189
|
"dist/",
|
|
161
190
|
"src/",
|
|
162
191
|
"examples/",
|
|
@@ -175,14 +204,6 @@
|
|
|
175
204
|
"rollup": "^4.0.0",
|
|
176
205
|
"size-limit": "12.0.0"
|
|
177
206
|
},
|
|
178
|
-
"optionalDependencies": {
|
|
179
|
-
"blessed": "^0.1.81",
|
|
180
|
-
"blessed-contrib": "4.11.0",
|
|
181
|
-
"exceljs": "^4.4.0"
|
|
182
|
-
},
|
|
183
|
-
"overrides": {
|
|
184
|
-
"xml2js": "0.6.2"
|
|
185
|
-
},
|
|
186
207
|
"type": "commonjs",
|
|
187
208
|
"size-limit": [
|
|
188
209
|
{
|
|
@@ -204,10 +225,5 @@
|
|
|
204
225
|
"defaults",
|
|
205
226
|
"not IE 11",
|
|
206
227
|
"maintained node versions"
|
|
207
|
-
]
|
|
208
|
-
"dependencies": {
|
|
209
|
-
"csv-parser": "3.2.0",
|
|
210
|
-
"json2csv": "6.0.0-alpha.2",
|
|
211
|
-
"papaparse": "5.5.3"
|
|
212
|
-
}
|
|
228
|
+
]
|
|
213
229
|
}
|
package/plugins/README.md
CHANGED
|
@@ -78,6 +78,152 @@ export default function Converter() {
|
|
|
78
78
|
|
|
79
79
|
[📚 Документация](./nextjs-api/README.md)
|
|
80
80
|
|
|
81
|
+
### 4. NestJS Integration (@jtcsv/nestjs)
|
|
82
|
+
|
|
83
|
+
**NestJS interceptors and decorators for CSV upload/download.**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install @jtcsv/nestjs jtcsv
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { CsvParserInterceptor, CsvDownloadDecorator } from 'jtcsv/nestjs';
|
|
91
|
+
|
|
92
|
+
@Controller('data')
|
|
93
|
+
export class DataController {
|
|
94
|
+
@Post('upload')
|
|
95
|
+
@CsvParserInterceptor({ delimiter: ',' })
|
|
96
|
+
uploadCsv(@Body() jsonData: any[]) {
|
|
97
|
+
return { parsed: jsonData };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Get('export')
|
|
101
|
+
@CsvDownloadDecorator({ filename: 'export.csv' })
|
|
102
|
+
exportData() {
|
|
103
|
+
return [{ id: 1, name: 'John' }];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
[📚 Документация](./nestjs/README.md)
|
|
109
|
+
|
|
110
|
+
### 5. Remix Integration (@jtcsv/remix)
|
|
111
|
+
|
|
112
|
+
**Helpers for form-data parsing and CSV downloads in Remix.**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm install @jtcsv/remix jtcsv
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { parseFormData, generateCsvResponse } from 'jtcsv/remix';
|
|
120
|
+
|
|
121
|
+
export async function action({ request }) {
|
|
122
|
+
const rows = await parseFormData(request, { delimiter: ',' });
|
|
123
|
+
return { parsed: rows };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function loader() {
|
|
127
|
+
return generateCsvResponse([{ id: 1, name: 'John' }], 'export.csv');
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
[📚 Документация](./remix/README.md)
|
|
132
|
+
|
|
133
|
+
### 6. Nuxt Integration (@jtcsv/nuxt)
|
|
134
|
+
|
|
135
|
+
**Nuxt module with auto-imported composable.**
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npm install @jtcsv/nuxt jtcsv
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
export default defineNuxtConfig({
|
|
143
|
+
modules: ['@jtcsv/nuxt'],
|
|
144
|
+
jtcsv: { autoimport: true }
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```vue
|
|
149
|
+
<script setup>
|
|
150
|
+
const { csvToJson, jsonToCsv } = useJtcsv();
|
|
151
|
+
</script>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
[📚 Документация](./nuxt/README.md)
|
|
155
|
+
|
|
156
|
+
### 7. SvelteKit Integration (@jtcsv/sveltekit)
|
|
157
|
+
|
|
158
|
+
**Request helpers for SvelteKit actions/endpoints.**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm install @jtcsv/sveltekit jtcsv
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { parseCsv, generateCsv } from 'jtcsv/sveltekit';
|
|
166
|
+
|
|
167
|
+
export const actions = {
|
|
168
|
+
upload: async ({ request }) => {
|
|
169
|
+
const rows = await parseCsv(request, { delimiter: ',' });
|
|
170
|
+
return { rows };
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export async function GET() {
|
|
175
|
+
return generateCsv([{ id: 1 }], 'export.csv');
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
[📚 Документация](./sveltekit/README.md)
|
|
180
|
+
|
|
181
|
+
### 8. Hono Integration (@jtcsv/hono)
|
|
182
|
+
|
|
183
|
+
**Minimal middleware for CSV parsing with Hono.**
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm install @jtcsv/hono jtcsv
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { Hono } from 'hono';
|
|
191
|
+
import { csvMiddleware, createCsvResponse } from 'jtcsv/hono';
|
|
192
|
+
|
|
193
|
+
const app = new Hono()
|
|
194
|
+
.use('/upload', csvMiddleware())
|
|
195
|
+
.post('/upload', (c) => c.json({ rows: c.get('csv') }))
|
|
196
|
+
.get('/export', (c) => {
|
|
197
|
+
const { csv, headers } = createCsvResponse([{ id: 1 }], 'export.csv');
|
|
198
|
+
return c.text(csv, 200, headers);
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
[📚 Документация](./hono/README.md)
|
|
203
|
+
|
|
204
|
+
### 9. tRPC Integration (@jtcsv/trpc)
|
|
205
|
+
|
|
206
|
+
**Middleware helper for CSV input parsing in tRPC procedures.**
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npm install @jtcsv/trpc jtcsv
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { initTRPC } from '@trpc/server';
|
|
214
|
+
import { z } from 'zod';
|
|
215
|
+
import { createCsvProcedure } from 'jtcsv/trpc';
|
|
216
|
+
|
|
217
|
+
const t = initTRPC.create();
|
|
218
|
+
|
|
219
|
+
export const router = t.router({
|
|
220
|
+
parseCsv: createCsvProcedure(t, z.string())
|
|
221
|
+
.mutation(async ({ input }) => ({ parsed: input }))
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
[📚 Документация](./trpc/README.md)
|
|
226
|
+
|
|
81
227
|
## 🎯 Особенности
|
|
82
228
|
|
|
83
229
|
### Единый API
|
|
@@ -369,5 +515,3 @@ node api-convert.js
|
|
|
369
515
|
---
|
|
370
516
|
|
|
371
517
|
**JTCSV Плагины** - делаем работу с CSV/JSON проще в любом фреймворке! 🚀
|
|
372
|
-
|
|
373
|
-
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @jtcsv/hono
|
|
2
|
+
|
|
3
|
+
Hono middleware for JTCSV.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
```bash
|
|
7
|
+
npm install @jtcsv/hono jtcsv
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```typescript
|
|
12
|
+
import { Hono } from 'hono';
|
|
13
|
+
import { csvMiddleware, createCsvResponse } from 'jtcsv/hono';
|
|
14
|
+
|
|
15
|
+
const app = new Hono()
|
|
16
|
+
.use('/upload', csvMiddleware({ delimiter: ',' }))
|
|
17
|
+
.post('/upload', (c) => {
|
|
18
|
+
const rows = c.get('csv');
|
|
19
|
+
return c.json({ rows });
|
|
20
|
+
})
|
|
21
|
+
.get('/export', (c) => {
|
|
22
|
+
const { csv, headers } = createCsvResponse([{ id: 1 }], 'export.csv');
|
|
23
|
+
return c.text(csv, 200, headers);
|
|
24
|
+
});
|
|
25
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CsvToJsonOptions, JsonToCsvOptions } from 'jtcsv';
|
|
2
|
+
import type { Context } from 'hono';
|
|
3
|
+
|
|
4
|
+
export function csvMiddleware(
|
|
5
|
+
options?: CsvToJsonOptions
|
|
6
|
+
): (c: Context, next: () => Promise<void>) => Promise<void>;
|
|
7
|
+
|
|
8
|
+
export function createCsvResponse(
|
|
9
|
+
data: unknown[] | Record<string, unknown>,
|
|
10
|
+
filename?: string,
|
|
11
|
+
options?: JsonToCsvOptions
|
|
12
|
+
): { csv: string; headers: Record<string, string> };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const jtcsv = require('jtcsv');
|
|
2
|
+
|
|
3
|
+
function normalizeFilename(filename) {
|
|
4
|
+
if (!filename || typeof filename !== 'string') {
|
|
5
|
+
return 'export.csv';
|
|
6
|
+
}
|
|
7
|
+
return filename.includes('.') ? filename : `${filename}.csv`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function csvMiddleware(options = {}) {
|
|
11
|
+
return async (c, next) => {
|
|
12
|
+
const csvText = await c.req.text();
|
|
13
|
+
const rows = jtcsv.csvToJson(csvText, options);
|
|
14
|
+
c.set('csv', rows);
|
|
15
|
+
await next();
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function createCsvResponse(data, filename = 'export.csv', options = {}) {
|
|
20
|
+
const safeName = normalizeFilename(filename);
|
|
21
|
+
const rows = Array.isArray(data) ? data : [data];
|
|
22
|
+
const csv = jtcsv.jsonToCsv(rows, options);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
csv,
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'text/csv; charset=utf-8',
|
|
28
|
+
'Content-Disposition': `attachment; filename="${safeName}"`
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
csvMiddleware,
|
|
35
|
+
createCsvResponse
|
|
36
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jtcsv/hono",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Hono middleware for JTCSV",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"hono",
|
|
9
|
+
"csv",
|
|
10
|
+
"json",
|
|
11
|
+
"converter",
|
|
12
|
+
"jtcsv",
|
|
13
|
+
"middleware"
|
|
14
|
+
],
|
|
15
|
+
"author": "Ruslan Fomenko",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/Linol-Hamelton/jtcsv.git",
|
|
20
|
+
"directory": "plugins/hono"
|
|
21
|
+
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/Linol-Hamelton/jtcsv/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/Linol-Hamelton/jtcsv/tree/main/plugins/hono#readme",
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"hono": "^4.0.0",
|
|
28
|
+
"jtcsv": "^2.1.3"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"index.js",
|
|
32
|
+
"index.d.ts",
|
|
33
|
+
"README.md"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @jtcsv/nestjs
|
|
2
|
+
|
|
3
|
+
NestJS interceptors and decorators for JTCSV.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
```bash
|
|
7
|
+
npm install @jtcsv/nestjs jtcsv
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```typescript
|
|
12
|
+
import { CsvParserInterceptor, CsvDownloadDecorator } from 'jtcsv/nestjs';
|
|
13
|
+
import { Body, Controller, Get, Post } from '@nestjs/common';
|
|
14
|
+
|
|
15
|
+
@Controller('data')
|
|
16
|
+
export class DataController {
|
|
17
|
+
@Post('upload')
|
|
18
|
+
@CsvParserInterceptor({ delimiter: ',' })
|
|
19
|
+
uploadCsv(@Body() jsonData: any[]) {
|
|
20
|
+
return { parsed: jsonData };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Get('export')
|
|
24
|
+
@CsvDownloadDecorator({ filename: 'export.csv' })
|
|
25
|
+
exportData() {
|
|
26
|
+
return [{ id: 1, name: 'John' }];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Notes
|
|
32
|
+
- `CsvParserInterceptor` expects CSV text in the request body.
|
|
33
|
+
- `CsvDownloadDecorator` converts the handler result to CSV and sets download headers.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Type } from '@nestjs/common';
|
|
2
|
+
import type { NestInterceptor } from '@nestjs/common';
|
|
3
|
+
import type { CsvToJsonOptions, JsonToCsvOptions } from 'jtcsv';
|
|
4
|
+
|
|
5
|
+
export interface CsvParserOptions extends CsvToJsonOptions {}
|
|
6
|
+
|
|
7
|
+
export interface CsvDownloadOptions extends JsonToCsvOptions {
|
|
8
|
+
filename?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function createCsvParserInterceptor(
|
|
12
|
+
options?: CsvParserOptions
|
|
13
|
+
): Type<NestInterceptor>;
|
|
14
|
+
|
|
15
|
+
export function createCsvDownloadInterceptor(
|
|
16
|
+
options?: CsvDownloadOptions
|
|
17
|
+
): Type<NestInterceptor>;
|
|
18
|
+
|
|
19
|
+
export function CsvParserInterceptor(
|
|
20
|
+
options?: CsvParserOptions
|
|
21
|
+
): MethodDecorator & ClassDecorator;
|
|
22
|
+
|
|
23
|
+
export function CsvDownloadDecorator(
|
|
24
|
+
options?: CsvDownloadOptions
|
|
25
|
+
): MethodDecorator & ClassDecorator;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { Injectable, UseInterceptors } = require('@nestjs/common');
|
|
2
|
+
const { map } = require('rxjs/operators');
|
|
3
|
+
const jtcsv = require('jtcsv');
|
|
4
|
+
|
|
5
|
+
function normalizeFilename(filename) {
|
|
6
|
+
if (!filename || typeof filename !== 'string') {
|
|
7
|
+
return 'export.csv';
|
|
8
|
+
}
|
|
9
|
+
return filename.includes('.') ? filename : `${filename}.csv`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function createCsvParserInterceptor(options = {}) {
|
|
13
|
+
class CsvParserInterceptorImpl {
|
|
14
|
+
intercept(context, next) {
|
|
15
|
+
const req = context.switchToHttp().getRequest();
|
|
16
|
+
const body = req && req.body;
|
|
17
|
+
|
|
18
|
+
if (typeof body === 'string' || Buffer.isBuffer(body)) {
|
|
19
|
+
const csv = Buffer.isBuffer(body) ? body.toString('utf8') : body;
|
|
20
|
+
req.body = jtcsv.csvToJson(csv, options);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return next.handle();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Injectable()(CsvParserInterceptorImpl);
|
|
28
|
+
return CsvParserInterceptorImpl;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createCsvDownloadInterceptor(options = {}) {
|
|
32
|
+
class CsvDownloadInterceptorImpl {
|
|
33
|
+
intercept(context, next) {
|
|
34
|
+
const res = context.switchToHttp().getResponse();
|
|
35
|
+
const filename = normalizeFilename(options.filename);
|
|
36
|
+
const csvOptions = { ...options };
|
|
37
|
+
delete csvOptions.filename;
|
|
38
|
+
|
|
39
|
+
return next.handle().pipe(
|
|
40
|
+
map(data => {
|
|
41
|
+
const rows = Array.isArray(data) ? data : [data];
|
|
42
|
+
const csv = jtcsv.jsonToCsv(rows, csvOptions);
|
|
43
|
+
|
|
44
|
+
if (res && typeof res.setHeader === 'function') {
|
|
45
|
+
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
|
46
|
+
res.setHeader(
|
|
47
|
+
'Content-Disposition',
|
|
48
|
+
`attachment; filename="${filename}"`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return csv;
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
Injectable()(CsvDownloadInterceptorImpl);
|
|
59
|
+
return CsvDownloadInterceptorImpl;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function CsvParserInterceptor(options = {}) {
|
|
63
|
+
const Interceptor = createCsvParserInterceptor(options);
|
|
64
|
+
return UseInterceptors(new Interceptor());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function CsvDownloadDecorator(options = {}) {
|
|
68
|
+
const Interceptor = createCsvDownloadInterceptor(options);
|
|
69
|
+
return UseInterceptors(new Interceptor());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
CsvParserInterceptor,
|
|
74
|
+
CsvDownloadDecorator,
|
|
75
|
+
createCsvParserInterceptor,
|
|
76
|
+
createCsvDownloadInterceptor
|
|
77
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jtcsv/nestjs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NestJS interceptors and decorators for JTCSV",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"nestjs",
|
|
9
|
+
"csv",
|
|
10
|
+
"json",
|
|
11
|
+
"converter",
|
|
12
|
+
"jtcsv",
|
|
13
|
+
"interceptor",
|
|
14
|
+
"decorator"
|
|
15
|
+
],
|
|
16
|
+
"author": "Ruslan Fomenko",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/Linol-Hamelton/jtcsv.git",
|
|
21
|
+
"directory": "plugins/nestjs"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/Linol-Hamelton/jtcsv/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/Linol-Hamelton/jtcsv/tree/main/plugins/nestjs#readme",
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@nestjs/common": "^9.0.0 || ^10.0.0",
|
|
29
|
+
"jtcsv": "^2.1.3",
|
|
30
|
+
"rxjs": "^7.0.0"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"index.js",
|
|
34
|
+
"index.d.ts",
|
|
35
|
+
"README.md"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @jtcsv/nuxt
|
|
2
|
+
|
|
3
|
+
Nuxt module for JTCSV.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
```bash
|
|
7
|
+
npm install @jtcsv/nuxt jtcsv
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
```typescript
|
|
12
|
+
export default defineNuxtConfig({
|
|
13
|
+
modules: ['@jtcsv/nuxt'],
|
|
14
|
+
jtcsv: {
|
|
15
|
+
autoimport: true
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
```vue
|
|
22
|
+
<script setup>
|
|
23
|
+
const { csvToJson, jsonToCsv } = useJtcsv();
|
|
24
|
+
</script>
|
|
25
|
+
```
|