jtcsv 2.1.3 → 2.2.2
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/LICENSE +1 -1
- package/README.md +60 -341
- package/bin/jtcsv.js +2462 -1372
- package/csv-to-json.js +35 -26
- package/dist/jtcsv.cjs.js +807 -133
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +800 -134
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +807 -133
- package/dist/jtcsv.umd.js.map +1 -1
- package/errors.js +20 -0
- package/examples/browser-vanilla.html +37 -0
- package/examples/cli-batch-processing.js +38 -0
- package/examples/error-handling.js +324 -0
- package/examples/ndjson-processing.js +434 -0
- package/examples/react-integration.jsx +637 -0
- package/examples/schema-validation.js +640 -0
- package/examples/simple-usage.js +10 -7
- package/examples/typescript-example.ts +486 -0
- package/examples/web-workers-advanced.js +28 -0
- package/index.d.ts +2 -0
- package/json-save.js +2 -1
- package/json-to-csv.js +171 -131
- package/package.json +20 -4
- package/plugins/README.md +41 -467
- package/plugins/express-middleware/README.md +32 -274
- package/plugins/hono/README.md +16 -13
- package/plugins/nestjs/README.md +13 -11
- package/plugins/nextjs-api/README.md +28 -423
- package/plugins/nextjs-api/index.js +1 -2
- package/plugins/nextjs-api/route.js +1 -2
- package/plugins/nuxt/README.md +6 -7
- package/plugins/remix/README.md +9 -9
- package/plugins/sveltekit/README.md +8 -8
- package/plugins/trpc/README.md +8 -5
- package/src/browser/browser-functions.js +33 -3
- package/src/browser/csv-to-json-browser.js +269 -11
- package/src/browser/errors-browser.js +19 -1
- package/src/browser/index.js +39 -5
- package/src/browser/streams.js +393 -0
- package/src/browser/workers/csv-parser.worker.js +20 -2
- package/src/browser/workers/worker-pool.js +507 -447
- package/src/core/plugin-system.js +4 -0
- package/src/engines/fast-path-engine.js +31 -23
- package/src/errors.js +26 -0
- package/src/formats/ndjson-parser.js +54 -5
- package/src/formats/tsv-parser.js +4 -1
- package/src/utils/schema-validator.js +594 -0
- package/src/utils/transform-loader.js +205 -0
- package/src/web-server/index.js +683 -0
- package/stream-csv-to-json.js +16 -87
- package/stream-json-to-csv.js +18 -86
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Validation Examples for jtcsv
|
|
3
|
+
*
|
|
4
|
+
* jtcsv supports JSON Schema validation for ensuring
|
|
5
|
+
* data integrity during CSV/JSON conversions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
jsonToCsv,
|
|
10
|
+
csvToJson,
|
|
11
|
+
ValidationError
|
|
12
|
+
} = require('jtcsv');
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Example 1: Basic Schema Validation
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
function basicSchemaValidation() {
|
|
19
|
+
console.log('\n=== Basic Schema Validation ===\n');
|
|
20
|
+
|
|
21
|
+
// Define schema for user data
|
|
22
|
+
const userSchema = {
|
|
23
|
+
type: 'object',
|
|
24
|
+
required: ['name', 'email'],
|
|
25
|
+
properties: {
|
|
26
|
+
name: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
minLength: 1,
|
|
29
|
+
maxLength: 100
|
|
30
|
+
},
|
|
31
|
+
email: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'
|
|
34
|
+
},
|
|
35
|
+
age: {
|
|
36
|
+
type: 'number',
|
|
37
|
+
minimum: 0,
|
|
38
|
+
maximum: 150
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Valid data
|
|
44
|
+
const validUsers = [
|
|
45
|
+
{ name: 'John Doe', email: 'john@example.com', age: 30 },
|
|
46
|
+
{ name: 'Jane Smith', email: 'jane@test.org', age: 25 }
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const csv = jsonToCsv(validUsers, { schema: userSchema });
|
|
51
|
+
console.log('Valid data converted successfully:');
|
|
52
|
+
console.log(csv);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.log('Unexpected error:', error.message);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Invalid data
|
|
58
|
+
const invalidUsers = [
|
|
59
|
+
{ name: '', email: 'john@example.com', age: 30 }, // Empty name
|
|
60
|
+
{ name: 'Jane', email: 'invalid-email', age: -5 } // Bad email, negative age
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
jsonToCsv(invalidUsers, { schema: userSchema });
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof ValidationError) {
|
|
67
|
+
console.log('\nValidation failed (expected):');
|
|
68
|
+
console.log('Error:', error.message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// Example 2: Complex Nested Schema
|
|
75
|
+
// =============================================================================
|
|
76
|
+
|
|
77
|
+
function nestedSchemaValidation() {
|
|
78
|
+
console.log('\n=== Nested Schema Validation ===\n');
|
|
79
|
+
|
|
80
|
+
const orderSchema = {
|
|
81
|
+
type: 'object',
|
|
82
|
+
required: ['orderId', 'customer', 'total'],
|
|
83
|
+
properties: {
|
|
84
|
+
orderId: {
|
|
85
|
+
type: 'string',
|
|
86
|
+
pattern: '^ORD-[0-9]{6}$' // Format: ORD-123456
|
|
87
|
+
},
|
|
88
|
+
customer: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
required: ['name', 'email'],
|
|
91
|
+
properties: {
|
|
92
|
+
name: { type: 'string', minLength: 1 },
|
|
93
|
+
email: { type: 'string' }
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
items: {
|
|
97
|
+
type: 'array',
|
|
98
|
+
minItems: 1,
|
|
99
|
+
items: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
required: ['sku', 'quantity'],
|
|
102
|
+
properties: {
|
|
103
|
+
sku: { type: 'string' },
|
|
104
|
+
quantity: { type: 'number', minimum: 1 }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
total: {
|
|
109
|
+
type: 'number',
|
|
110
|
+
minimum: 0
|
|
111
|
+
},
|
|
112
|
+
status: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
enum: ['pending', 'processing', 'shipped', 'delivered']
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const orders = [
|
|
120
|
+
{
|
|
121
|
+
orderId: 'ORD-123456',
|
|
122
|
+
customer: { name: 'John Doe', email: 'john@example.com' },
|
|
123
|
+
items: [
|
|
124
|
+
{ sku: 'PROD-001', quantity: 2 },
|
|
125
|
+
{ sku: 'PROD-002', quantity: 1 }
|
|
126
|
+
],
|
|
127
|
+
total: 149.99,
|
|
128
|
+
status: 'processing'
|
|
129
|
+
}
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const csv = jsonToCsv(orders, {
|
|
134
|
+
schema: orderSchema,
|
|
135
|
+
delimiter: ','
|
|
136
|
+
});
|
|
137
|
+
console.log('Order with nested data converted:');
|
|
138
|
+
console.log(csv);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.log('Error:', error.message);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// =============================================================================
|
|
145
|
+
// Example 3: Schema with Custom Formats
|
|
146
|
+
// =============================================================================
|
|
147
|
+
|
|
148
|
+
function customFormatSchema() {
|
|
149
|
+
console.log('\n=== Custom Format Schema ===\n');
|
|
150
|
+
|
|
151
|
+
const eventSchema = {
|
|
152
|
+
type: 'object',
|
|
153
|
+
required: ['eventId', 'timestamp', 'eventType'],
|
|
154
|
+
properties: {
|
|
155
|
+
eventId: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
pattern: '^EVT-[A-Z0-9]{8}$' // EVT-XXXXXXXX
|
|
158
|
+
},
|
|
159
|
+
timestamp: {
|
|
160
|
+
type: 'string',
|
|
161
|
+
pattern: '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$' // ISO 8601
|
|
162
|
+
},
|
|
163
|
+
eventType: {
|
|
164
|
+
type: 'string',
|
|
165
|
+
enum: ['click', 'view', 'purchase', 'signup', 'login', 'logout']
|
|
166
|
+
},
|
|
167
|
+
userId: {
|
|
168
|
+
type: 'string',
|
|
169
|
+
pattern: '^USR-\\d{6}$' // Optional but must match if present
|
|
170
|
+
},
|
|
171
|
+
metadata: {
|
|
172
|
+
type: 'object' // Allow any object structure
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const events = [
|
|
178
|
+
{
|
|
179
|
+
eventId: 'EVT-A1B2C3D4',
|
|
180
|
+
timestamp: '2024-01-15T10:30:00.123Z',
|
|
181
|
+
eventType: 'purchase',
|
|
182
|
+
userId: 'USR-000123',
|
|
183
|
+
metadata: { productId: 'PRD-001', amount: 99.99 }
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
eventId: 'EVT-E5F6G7H8',
|
|
187
|
+
timestamp: '2024-01-15T10:31:00Z',
|
|
188
|
+
eventType: 'view',
|
|
189
|
+
metadata: { page: '/products', duration: 45 }
|
|
190
|
+
}
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
const csv = jsonToCsv(events, { schema: eventSchema });
|
|
195
|
+
console.log('Events validated and converted:');
|
|
196
|
+
console.log(csv);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.log('Error:', error.message);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// =============================================================================
|
|
203
|
+
// Example 4: Array Validation
|
|
204
|
+
// =============================================================================
|
|
205
|
+
|
|
206
|
+
function arraySchemaValidation() {
|
|
207
|
+
console.log('\n=== Array Schema Validation ===\n');
|
|
208
|
+
|
|
209
|
+
const surveySchema = {
|
|
210
|
+
type: 'object',
|
|
211
|
+
required: ['respondentId', 'answers'],
|
|
212
|
+
properties: {
|
|
213
|
+
respondentId: {
|
|
214
|
+
type: 'number',
|
|
215
|
+
minimum: 1
|
|
216
|
+
},
|
|
217
|
+
answers: {
|
|
218
|
+
type: 'array',
|
|
219
|
+
minItems: 5,
|
|
220
|
+
maxItems: 10,
|
|
221
|
+
items: {
|
|
222
|
+
type: 'number',
|
|
223
|
+
minimum: 1,
|
|
224
|
+
maximum: 5 // Rating 1-5
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
comments: {
|
|
228
|
+
type: 'string',
|
|
229
|
+
maxLength: 500
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const surveyResponses = [
|
|
235
|
+
{
|
|
236
|
+
respondentId: 1,
|
|
237
|
+
answers: [5, 4, 3, 5, 4],
|
|
238
|
+
comments: 'Great experience!'
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
respondentId: 2,
|
|
242
|
+
answers: [3, 3, 4, 4, 5, 4],
|
|
243
|
+
comments: ''
|
|
244
|
+
}
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
const csv = jsonToCsv(surveyResponses, { schema: surveySchema });
|
|
249
|
+
console.log('Survey responses validated:');
|
|
250
|
+
console.log(csv);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.log('Error:', error.message);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Test with invalid data
|
|
256
|
+
console.log('\nTesting invalid survey data:');
|
|
257
|
+
const invalidSurvey = [
|
|
258
|
+
{
|
|
259
|
+
respondentId: 1,
|
|
260
|
+
answers: [5, 4, 6, 5, 4], // 6 is out of range (max 5)
|
|
261
|
+
comments: 'Test'
|
|
262
|
+
}
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
jsonToCsv(invalidSurvey, { schema: surveySchema });
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.log('Validation error (expected):', error.message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// =============================================================================
|
|
273
|
+
// Example 5: Conditional Schema (oneOf/anyOf)
|
|
274
|
+
// =============================================================================
|
|
275
|
+
|
|
276
|
+
function conditionalSchema() {
|
|
277
|
+
console.log('\n=== Conditional Schema ===\n');
|
|
278
|
+
|
|
279
|
+
// Schema where payment method determines required fields
|
|
280
|
+
const paymentSchema = {
|
|
281
|
+
type: 'object',
|
|
282
|
+
required: ['paymentId', 'method', 'amount'],
|
|
283
|
+
properties: {
|
|
284
|
+
paymentId: { type: 'string' },
|
|
285
|
+
method: {
|
|
286
|
+
type: 'string',
|
|
287
|
+
enum: ['credit_card', 'bank_transfer', 'crypto']
|
|
288
|
+
},
|
|
289
|
+
amount: {
|
|
290
|
+
type: 'number',
|
|
291
|
+
minimum: 0.01
|
|
292
|
+
},
|
|
293
|
+
// Credit card fields
|
|
294
|
+
cardLast4: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
pattern: '^\\d{4}$'
|
|
297
|
+
},
|
|
298
|
+
// Bank transfer fields
|
|
299
|
+
bankAccount: {
|
|
300
|
+
type: 'string'
|
|
301
|
+
},
|
|
302
|
+
// Crypto fields
|
|
303
|
+
walletAddress: {
|
|
304
|
+
type: 'string',
|
|
305
|
+
pattern: '^0x[a-fA-F0-9]{40}$'
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const payments = [
|
|
311
|
+
{
|
|
312
|
+
paymentId: 'PAY-001',
|
|
313
|
+
method: 'credit_card',
|
|
314
|
+
amount: 99.99,
|
|
315
|
+
cardLast4: '1234'
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
paymentId: 'PAY-002',
|
|
319
|
+
method: 'bank_transfer',
|
|
320
|
+
amount: 500.00,
|
|
321
|
+
bankAccount: 'GB82WEST12345698765432'
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
paymentId: 'PAY-003',
|
|
325
|
+
method: 'crypto',
|
|
326
|
+
amount: 250.00,
|
|
327
|
+
walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8e21d'
|
|
328
|
+
}
|
|
329
|
+
];
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
const csv = jsonToCsv(payments, { schema: paymentSchema });
|
|
333
|
+
console.log('Payments validated:');
|
|
334
|
+
console.log(csv);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.log('Error:', error.message);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// =============================================================================
|
|
341
|
+
// Example 6: Schema for Type Coercion Hints
|
|
342
|
+
// =============================================================================
|
|
343
|
+
|
|
344
|
+
function typeCoercionSchema() {
|
|
345
|
+
console.log('\n=== Schema for Type Hints ===\n');
|
|
346
|
+
|
|
347
|
+
// Schema that helps with proper type handling
|
|
348
|
+
const productSchema = {
|
|
349
|
+
type: 'object',
|
|
350
|
+
properties: {
|
|
351
|
+
sku: { type: 'string' },
|
|
352
|
+
name: { type: 'string' },
|
|
353
|
+
price: { type: 'number' },
|
|
354
|
+
quantity: { type: 'integer' },
|
|
355
|
+
isAvailable: { type: 'boolean' },
|
|
356
|
+
tags: {
|
|
357
|
+
type: 'array',
|
|
358
|
+
items: { type: 'string' }
|
|
359
|
+
},
|
|
360
|
+
dimensions: {
|
|
361
|
+
type: 'object',
|
|
362
|
+
properties: {
|
|
363
|
+
width: { type: 'number' },
|
|
364
|
+
height: { type: 'number' },
|
|
365
|
+
depth: { type: 'number' }
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const products = [
|
|
372
|
+
{
|
|
373
|
+
sku: 'LAPTOP-001',
|
|
374
|
+
name: 'Pro Laptop 15"',
|
|
375
|
+
price: 1299.99,
|
|
376
|
+
quantity: 50,
|
|
377
|
+
isAvailable: true,
|
|
378
|
+
tags: ['electronics', 'computers', 'portable'],
|
|
379
|
+
dimensions: { width: 35.5, height: 1.8, depth: 24.0 }
|
|
380
|
+
}
|
|
381
|
+
];
|
|
382
|
+
|
|
383
|
+
const csv = jsonToCsv(products, {
|
|
384
|
+
schema: productSchema,
|
|
385
|
+
delimiter: ','
|
|
386
|
+
});
|
|
387
|
+
console.log('Product with type hints:');
|
|
388
|
+
console.log(csv);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// =============================================================================
|
|
392
|
+
// Example 7: Validation Error Details
|
|
393
|
+
// =============================================================================
|
|
394
|
+
|
|
395
|
+
function validationErrorDetails() {
|
|
396
|
+
console.log('\n=== Validation Error Details ===\n');
|
|
397
|
+
|
|
398
|
+
const strictSchema = {
|
|
399
|
+
type: 'object',
|
|
400
|
+
additionalProperties: false, // No extra fields allowed
|
|
401
|
+
required: ['id', 'name', 'email', 'role'],
|
|
402
|
+
properties: {
|
|
403
|
+
id: {
|
|
404
|
+
type: 'integer',
|
|
405
|
+
minimum: 1
|
|
406
|
+
},
|
|
407
|
+
name: {
|
|
408
|
+
type: 'string',
|
|
409
|
+
minLength: 2,
|
|
410
|
+
maxLength: 50
|
|
411
|
+
},
|
|
412
|
+
email: {
|
|
413
|
+
type: 'string',
|
|
414
|
+
pattern: '^[^@]+@[^@]+\\.[^@]+$'
|
|
415
|
+
},
|
|
416
|
+
role: {
|
|
417
|
+
type: 'string',
|
|
418
|
+
enum: ['admin', 'user', 'guest']
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// Data with multiple validation errors
|
|
424
|
+
const invalidData = [
|
|
425
|
+
{
|
|
426
|
+
id: 0, // Error: minimum is 1
|
|
427
|
+
name: 'A', // Error: minLength is 2
|
|
428
|
+
email: 'invalid', // Error: doesn't match pattern
|
|
429
|
+
role: 'superuser', // Error: not in enum
|
|
430
|
+
extra: 'field' // Error: additionalProperties false
|
|
431
|
+
}
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
try {
|
|
435
|
+
jsonToCsv(invalidData, { schema: strictSchema });
|
|
436
|
+
} catch (error) {
|
|
437
|
+
if (error instanceof ValidationError) {
|
|
438
|
+
console.log('Multiple validation errors detected:');
|
|
439
|
+
console.log('Message:', error.message);
|
|
440
|
+
console.log('Code:', error.code);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// =============================================================================
|
|
446
|
+
// Example 8: Schema Validation with CSV Input
|
|
447
|
+
// =============================================================================
|
|
448
|
+
|
|
449
|
+
function schemaValidationOnCsvInput() {
|
|
450
|
+
console.log('\n=== Schema Validation on CSV Input ===\n');
|
|
451
|
+
|
|
452
|
+
const csv = `id,name,score,passed
|
|
453
|
+
1,Alice,95,true
|
|
454
|
+
2,Bob,87,true
|
|
455
|
+
3,Charlie,45,false
|
|
456
|
+
4,Diana,invalid,true`; // 'invalid' should be a number
|
|
457
|
+
|
|
458
|
+
// First parse CSV
|
|
459
|
+
const data = csvToJson(csv, {
|
|
460
|
+
parseNumbers: true,
|
|
461
|
+
parseBooleans: true
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
console.log('Parsed data:');
|
|
465
|
+
data.forEach(row => {
|
|
466
|
+
console.log(` ${row.name}: score=${row.score} (${typeof row.score})`);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Now validate
|
|
470
|
+
const scoreSchema = {
|
|
471
|
+
type: 'object',
|
|
472
|
+
properties: {
|
|
473
|
+
id: { type: 'number' },
|
|
474
|
+
name: { type: 'string' },
|
|
475
|
+
score: { type: 'number', minimum: 0, maximum: 100 },
|
|
476
|
+
passed: { type: 'boolean' }
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
// Validate each row
|
|
481
|
+
console.log('\nValidation results:');
|
|
482
|
+
data.forEach((row, i) => {
|
|
483
|
+
const isValid = typeof row.score === 'number' &&
|
|
484
|
+
row.score >= 0 && row.score <= 100;
|
|
485
|
+
console.log(` Row ${i + 1} (${row.name}): ${isValid ? 'Valid' : 'Invalid'}`);
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// =============================================================================
|
|
490
|
+
// Example 9: Reusable Schema Definitions
|
|
491
|
+
// =============================================================================
|
|
492
|
+
|
|
493
|
+
function reusableSchemaDefinitions() {
|
|
494
|
+
console.log('\n=== Reusable Schema Definitions ===\n');
|
|
495
|
+
|
|
496
|
+
// Common field definitions
|
|
497
|
+
const commonFields = {
|
|
498
|
+
id: { type: 'integer', minimum: 1 },
|
|
499
|
+
createdAt: { type: 'string' },
|
|
500
|
+
updatedAt: { type: 'string' }
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const addressSchema = {
|
|
504
|
+
type: 'object',
|
|
505
|
+
required: ['street', 'city', 'country'],
|
|
506
|
+
properties: {
|
|
507
|
+
street: { type: 'string' },
|
|
508
|
+
city: { type: 'string' },
|
|
509
|
+
postalCode: { type: 'string' },
|
|
510
|
+
country: { type: 'string', minLength: 2, maxLength: 2 } // ISO country code
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// Customer schema using common fields
|
|
515
|
+
const customerSchema = {
|
|
516
|
+
type: 'object',
|
|
517
|
+
required: ['id', 'name', 'email'],
|
|
518
|
+
properties: {
|
|
519
|
+
...commonFields,
|
|
520
|
+
name: { type: 'string', minLength: 1 },
|
|
521
|
+
email: { type: 'string' },
|
|
522
|
+
phone: { type: 'string' },
|
|
523
|
+
billingAddress: addressSchema,
|
|
524
|
+
shippingAddress: addressSchema
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const customers = [
|
|
529
|
+
{
|
|
530
|
+
id: 1,
|
|
531
|
+
name: 'John Doe',
|
|
532
|
+
email: 'john@example.com',
|
|
533
|
+
phone: '+1-555-1234',
|
|
534
|
+
billingAddress: {
|
|
535
|
+
street: '123 Main St',
|
|
536
|
+
city: 'New York',
|
|
537
|
+
postalCode: '10001',
|
|
538
|
+
country: 'US'
|
|
539
|
+
},
|
|
540
|
+
shippingAddress: {
|
|
541
|
+
street: '456 Oak Ave',
|
|
542
|
+
city: 'Brooklyn',
|
|
543
|
+
postalCode: '11201',
|
|
544
|
+
country: 'US'
|
|
545
|
+
},
|
|
546
|
+
createdAt: '2024-01-15T10:00:00Z',
|
|
547
|
+
updatedAt: '2024-01-15T10:00:00Z'
|
|
548
|
+
}
|
|
549
|
+
];
|
|
550
|
+
|
|
551
|
+
try {
|
|
552
|
+
const csv = jsonToCsv(customers, { schema: customerSchema });
|
|
553
|
+
console.log('Customer data validated with reusable schema:');
|
|
554
|
+
console.log(csv);
|
|
555
|
+
} catch (error) {
|
|
556
|
+
console.log('Error:', error.message);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// =============================================================================
|
|
561
|
+
// Example 10: Schema Factory Pattern
|
|
562
|
+
// =============================================================================
|
|
563
|
+
|
|
564
|
+
function schemaFactoryPattern() {
|
|
565
|
+
console.log('\n=== Schema Factory Pattern ===\n');
|
|
566
|
+
|
|
567
|
+
// Schema factory for different entity types
|
|
568
|
+
const createEntitySchema = (entityType, customProperties = {}) => ({
|
|
569
|
+
type: 'object',
|
|
570
|
+
required: ['id', 'type', 'name'],
|
|
571
|
+
properties: {
|
|
572
|
+
id: { type: 'integer', minimum: 1 },
|
|
573
|
+
type: { type: 'string', enum: [entityType] },
|
|
574
|
+
name: { type: 'string', minLength: 1 },
|
|
575
|
+
description: { type: 'string' },
|
|
576
|
+
active: { type: 'boolean' },
|
|
577
|
+
metadata: { type: 'object' },
|
|
578
|
+
...customProperties
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
// Create specific schemas
|
|
583
|
+
const productSchema = createEntitySchema('product', {
|
|
584
|
+
price: { type: 'number', minimum: 0 },
|
|
585
|
+
sku: { type: 'string', pattern: '^[A-Z]{3}-\\d{4}$' },
|
|
586
|
+
category: { type: 'string' }
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const serviceSchema = createEntitySchema('service', {
|
|
590
|
+
hourlyRate: { type: 'number', minimum: 0 },
|
|
591
|
+
duration: { type: 'integer', minimum: 1 },
|
|
592
|
+
availability: { type: 'string', enum: ['available', 'busy', 'unavailable'] }
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
console.log('Product schema created:', Object.keys(productSchema.properties));
|
|
596
|
+
console.log('Service schema created:', Object.keys(serviceSchema.properties));
|
|
597
|
+
|
|
598
|
+
// Validate data
|
|
599
|
+
const product = {
|
|
600
|
+
id: 1,
|
|
601
|
+
type: 'product',
|
|
602
|
+
name: 'Widget Pro',
|
|
603
|
+
price: 29.99,
|
|
604
|
+
sku: 'WGT-0001',
|
|
605
|
+
category: 'widgets',
|
|
606
|
+
active: true
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
try {
|
|
610
|
+
const csv = jsonToCsv([product], { schema: productSchema });
|
|
611
|
+
console.log('\nProduct validated successfully');
|
|
612
|
+
} catch (error) {
|
|
613
|
+
console.log('Error:', error.message);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// =============================================================================
|
|
618
|
+
// Run All Examples
|
|
619
|
+
// =============================================================================
|
|
620
|
+
|
|
621
|
+
async function main() {
|
|
622
|
+
console.log('jtcsv Schema Validation Examples');
|
|
623
|
+
console.log('='.repeat(60));
|
|
624
|
+
|
|
625
|
+
basicSchemaValidation();
|
|
626
|
+
nestedSchemaValidation();
|
|
627
|
+
customFormatSchema();
|
|
628
|
+
arraySchemaValidation();
|
|
629
|
+
conditionalSchema();
|
|
630
|
+
typeCoercionSchema();
|
|
631
|
+
validationErrorDetails();
|
|
632
|
+
schemaValidationOnCsvInput();
|
|
633
|
+
reusableSchemaDefinitions();
|
|
634
|
+
schemaFactoryPattern();
|
|
635
|
+
|
|
636
|
+
console.log('\n' + '='.repeat(60));
|
|
637
|
+
console.log('All schema validation examples completed.');
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
main().catch(console.error);
|
package/examples/simple-usage.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @date 2026-01-22
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
;(async () => {
|
|
11
12
|
console.log('🚀 JTCSV 2.1.0 - Демонстрация новых возможностей\n');
|
|
12
13
|
|
|
13
14
|
// ============================================================================
|
|
@@ -17,7 +18,7 @@ console.log('🚀 JTCSV 2.1.0 - Демонстрация новых возмож
|
|
|
17
18
|
console.log('1. 📦 Базовое использование (обратная совместимость)');
|
|
18
19
|
console.log('='.repeat(60));
|
|
19
20
|
|
|
20
|
-
const { jsonToCsv, csvToJson } = require('jtcsv
|
|
21
|
+
const { jsonToCsv, csvToJson } = require('jtcsv');
|
|
21
22
|
|
|
22
23
|
const sampleData = [
|
|
23
24
|
{ id: 1, name: 'John Doe', age: 30, city: 'New York' },
|
|
@@ -44,7 +45,7 @@ console.log();
|
|
|
44
45
|
console.log('\n2. ⚡ Fast-Path Engine (оптимизированный парсинг)');
|
|
45
46
|
console.log('='.repeat(60));
|
|
46
47
|
|
|
47
|
-
const
|
|
48
|
+
const FastPathEngine = require('../src/engines/fast-path-engine');
|
|
48
49
|
const engine = new FastPathEngine();
|
|
49
50
|
|
|
50
51
|
// Создаем тестовый CSV
|
|
@@ -87,7 +88,7 @@ console.log(` Hit rate: ${(stats.hitRate * 100).toFixed(1)}%`);
|
|
|
87
88
|
console.log('\n3. 📝 NDJSON поддержка (потоковая обработка)');
|
|
88
89
|
console.log('='.repeat(60));
|
|
89
90
|
|
|
90
|
-
const
|
|
91
|
+
const NdjsonParser = require('../src/formats/ndjson-parser');
|
|
91
92
|
|
|
92
93
|
// Конвертация в NDJSON
|
|
93
94
|
const ndjson = NdjsonParser.toNdjson(sampleData, { space: 2 });
|
|
@@ -115,7 +116,7 @@ console.log(` Успешность: ${ndjsonStats.successRate}%`);
|
|
|
115
116
|
console.log('\n4. 🔌 Plugin System (расширяемость)');
|
|
116
117
|
console.log('='.repeat(60));
|
|
117
118
|
|
|
118
|
-
const
|
|
119
|
+
const PluginManager = require('../src/core/plugin-system');
|
|
119
120
|
|
|
120
121
|
// Создаем простой плагин для логирования
|
|
121
122
|
const loggingPlugin = {
|
|
@@ -265,7 +266,7 @@ console.log('3. Попробуйте примеры: npm run example:plugins');
|
|
|
265
266
|
console.log('4. Создайте свой плагин!');
|
|
266
267
|
|
|
267
268
|
console.log('\n💡 Совет: Для production используйте:');
|
|
268
|
-
console.log(' const jtcsv = require("jtcsv.create();');
|
|
269
|
+
console.log(' const jtcsv = require("jtcsv/plugins").create();');
|
|
269
270
|
console.log(' jtcsv.use("your-plugin", yourPluginConfig);');
|
|
270
271
|
|
|
271
272
|
console.log('\n📚 Документация: https://github.com/Linol-Hamelton/jtcsv');
|
|
@@ -275,5 +276,7 @@ console.log('⭐ Star на GitHub если понравилось!');
|
|
|
275
276
|
console.log('\n' + '✨'.repeat(30));
|
|
276
277
|
console.log('✨ JTCSV 2.1.0 - Next Generation JSON/CSV Converter ✨');
|
|
277
278
|
console.log('✨'.repeat(30));
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
})().catch((error) => {
|
|
280
|
+
console.error('Demo failed:', error);
|
|
281
|
+
process.exitCode = 1;
|
|
282
|
+
});
|