json-rest-api 1.0.0 → 1.0.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.
Files changed (67) hide show
  1. package/.claude/settings.local.json +16 -0
  2. package/LICENSE +674 -0
  3. package/README.md +655 -309
  4. package/RELATIONSHIPS.md +1013 -0
  5. package/TODO_rest-api-plugin-extras.js +142 -0
  6. package/connectors_ideas/express-plugin.js +120 -0
  7. package/connectors_ideas/fastify.js +219 -0
  8. package/connectors_ideas/http-plugin.js +138 -0
  9. package/connectors_ideas/koa-plugin.js +113 -0
  10. package/docs/fileUploads.md +722 -0
  11. package/docs/mini-guides/file-uploads-complete.md +159 -0
  12. package/examples/.gitkeep +0 -0
  13. package/examples/express-example.js +262 -0
  14. package/examples/express-plugin.js +366 -0
  15. package/examples/file-upload-example.js +205 -0
  16. package/examples/filename-strategies.js +140 -0
  17. package/examples/knex-basic.js +66 -0
  18. package/index.js +31 -56
  19. package/lib/payload-validators.js +685 -0
  20. package/lib/rest-api-errors.js +58 -0
  21. package/package.json +41 -14
  22. package/payloadValdators.js +686 -0
  23. package/plugins/core/connectors/express-plugin.js +449 -0
  24. package/plugins/core/connectors/http-plugin.js +450 -0
  25. package/plugins/core/file-handling-plugin.js +338 -0
  26. package/plugins/core/lib/busboy-detector.js +167 -0
  27. package/plugins/core/lib/formidable-detector.js +130 -0
  28. package/plugins/core/rest-api-knex-plugin.js +200 -0
  29. package/plugins/core/rest-api-plugin.js +1419 -0
  30. package/plugins/storage/local-storage.js +218 -0
  31. package/plugins/storage/s3-storage.js +125 -0
  32. package/test-examples/package-lock.json +906 -0
  33. package/test-examples/package.json +15 -0
  34. package/test-examples/test-basic-api.js +11 -0
  35. package/test-examples/test-books-resource.js +116 -0
  36. package/test-examples/test-complete-file-upload.js +140 -0
  37. package/test-examples/test-debug.js +28 -0
  38. package/test-examples/test-express-plugin.js +177 -0
  39. package/test-examples/test-express-simple.js +28 -0
  40. package/test-examples/test-express-with-import.js +71 -0
  41. package/test-examples/test-file-upload.js +132 -0
  42. package/test-examples/test-http-plugin.js +159 -0
  43. package/test-examples/test-programmatic-api.js +188 -0
  44. package/test-examples/test-rest-api-plugin.js +13 -0
  45. package/TODO.todo +0 -113
  46. package/api.js +0 -628
  47. package/docs/API.md +0 -1306
  48. package/docs/FIXES_APPLIED.md +0 -59
  49. package/docs/GUIDES.md +0 -1792
  50. package/docs/RESOURCES_IN_EXPRESS.md +0 -456
  51. package/docs/example-versioning.js +0 -168
  52. package/docs/example.js +0 -195
  53. package/plugins/API guide.md +0 -364
  54. package/plugins/api-registry.js +0 -142
  55. package/plugins/api-versioning.md +0 -135
  56. package/plugins/http.js +0 -273
  57. package/plugins/logging.js +0 -255
  58. package/plugins/memory.js +0 -182
  59. package/plugins/mysql.js +0 -753
  60. package/plugins/openapi.js +0 -401
  61. package/plugins/positioning.js +0 -220
  62. package/plugins/security.js +0 -261
  63. package/plugins/validation.js +0 -173
  64. package/plugins/versioning.js +0 -288
  65. package/resource-helper.js +0 -79
  66. package/schema.js +0 -481
  67. package/test-basic.js +0 -107
package/docs/API.md DELETED
@@ -1,1306 +0,0 @@
1
- # JSON REST API - Complete API Reference
2
-
3
- This document provides a complete reference for every class, method, and option in the JSON REST API library.
4
-
5
- ## Key Concepts: API Instance Management
6
-
7
- ### When to Create New vs Share Instances
8
-
9
- **Create NEW instance (with `createApi()` or `new Api()`):**
10
- - Simple APIs where everything is in one file
11
- - Standalone services that don't interact
12
- - Different API versions (each version gets its own instance)
13
-
14
- **Share EXISTING instance (with `Api.get()` or `defineResource()`):**
15
- - Resources split across multiple files
16
- - Resources that need to interact (e.g., users querying products)
17
- - Resources sharing the same database connection
18
- - Resources in the same API version
19
-
20
- ### Example Patterns
21
-
22
- ```javascript
23
- // Simple API (one file) - CREATE new instance
24
- const api = createApi({ storage: 'memory' });
25
- api.addResource('users', userSchema);
26
- api.addResource('products', productSchema);
27
-
28
- // Modular API (multiple files) - SHARE instance
29
- // api/1.0.0/users.js
30
- const api = Api.get('myapp', '1.0.0') || new Api({ name: 'myapp', version: '1.0.0' });
31
- api.addResource('users', userSchema);
32
- export default api;
33
-
34
- // api/1.0.0/products.js
35
- const api = Api.get('myapp', '1.0.0'); // Gets SAME instance!
36
- api.addResource('products', productSchema);
37
- export default api;
38
- ```
39
-
40
- ## Table of Contents
41
-
42
- 1. [Core Classes](#core-classes)
43
- - [Api Class](#api-class)
44
- - [Schema Class](#schema-class)
45
- 2. [Plugin Reference](#plugin-reference)
46
- - [ValidationPlugin](#validationplugin)
47
- - [MemoryPlugin](#memoryplugin)
48
- - [MySQLPlugin](#mysqlplugin)
49
- - [HTTPPlugin](#httpplugin)
50
- - [PositioningPlugin](#positioningplugin)
51
- - [VersioningPlugin](#versioningplugin)
52
- - [SecurityPlugin](#securityplugin)
53
- - [LoggingPlugin](#loggingplugin)
54
- - [OpenAPIPlugin](#openapiplugin)
55
- 3. [Helper Functions](#helper-functions)
56
- 4. [Type Definitions](#type-definitions)
57
-
58
- ---
59
-
60
- # Core Classes
61
-
62
- ## Api Class
63
-
64
- The main class for creating and managing JSON REST APIs.
65
-
66
- ### Constructor
67
-
68
- ```javascript
69
- new Api(options)
70
- ```
71
-
72
- **Options:**
73
- | Option | Type | Default | Description |
74
- |--------|------|---------|-------------|
75
- | `idProperty` | string | `'id'` | The field name used as the primary identifier |
76
- | `name` | string | `null` | API name for versioning registry |
77
- | `version` | string | `null` | API version (e.g., '1.0.0') |
78
-
79
- **Example:**
80
- ```javascript
81
- const api = new Api({
82
- idProperty: 'id',
83
- name: 'myapp',
84
- version: '1.0.0'
85
- });
86
- ```
87
-
88
- ### Methods
89
-
90
- #### `use(plugin, options)`
91
- Add a plugin to the API.
92
-
93
- **Parameters:**
94
- - `plugin` (Object): Plugin object with `install` method
95
- - `options` (Object): Plugin-specific options
96
-
97
- **Returns:** `this` (for chaining)
98
-
99
- **Example:**
100
- ```javascript
101
- api.use(MySQLPlugin, { connection: dbConfig })
102
- .use(HTTPPlugin, { basePath: '/api' });
103
- ```
104
-
105
- #### `hook(name, handler, priority)`
106
- Register a hook handler.
107
-
108
- **Parameters:**
109
- - `name` (string): Hook name
110
- - `handler` (async function): Hook handler function
111
- - `priority` (number): Execution priority (lower = earlier, default: 50)
112
-
113
- **Available Hooks:**
114
- - `beforeValidate`: Before data validation
115
- - `afterValidate`: After validation, before operation
116
- - `beforeGet`: Before fetching single resource
117
- - `afterGet`: After fetching single resource
118
- - `beforeQuery`: Before querying resources
119
- - `afterQuery`: After querying resources
120
- - `beforeInsert`: Before inserting resource
121
- - `afterInsert`: After inserting resource
122
- - `beforeUpdate`: Before updating resource
123
- - `afterUpdate`: After updating resource
124
- - `beforeDelete`: Before deleting resource
125
- - `afterDelete`: After deleting resource
126
- - `beforeSend`: Before sending response (HTTP)
127
- - `transformResult`: Transform results before returning
128
-
129
- **Hook Context Object:**
130
- ```javascript
131
- {
132
- method: 'insert', // Current operation
133
- id: '123', // Resource ID (for get/update/delete)
134
- data: {...}, // Request data
135
- params: {...}, // Query parameters
136
- options: {...}, // Operation options
137
- result: {...}, // Operation result
138
- results: [...], // Query results
139
- errors: [...], // Validation errors
140
- meta: {...} // Metadata
141
- }
142
- ```
143
-
144
- **Example:**
145
- ```javascript
146
- api.hook('beforeInsert', async (context) => {
147
- context.data.createdAt = Date.now();
148
- });
149
- ```
150
-
151
- #### `get(id, options)`
152
- Fetch a single resource by ID.
153
-
154
- **Parameters:**
155
- - `id` (string|number): Resource identifier
156
- - `options` (Object): Operation options
157
-
158
- **Options:**
159
- | Option | Type | Description |
160
- |--------|------|-------------|
161
- | `type` | string | Resource type (required) |
162
- | `table` | string | Database table (MySQL) |
163
- | `connection` | string | Database connection name |
164
- | `fields` | string[] | Fields to return |
165
- | `userId` | any | User ID for audit |
166
- | `request` | Object | HTTP request object |
167
-
168
- **Returns:** Promise<{ data: Resource }>
169
-
170
- **Example:**
171
- ```javascript
172
- const result = await api.get('123', { type: 'users' });
173
- // { data: { id: '123', type: 'users', attributes: {...} } }
174
- ```
175
-
176
- #### `query(params, options)`
177
- Query multiple resources.
178
-
179
- **Parameters:**
180
- - `params` (Object): Query parameters
181
- - `options` (Object): Operation options
182
-
183
- **Query Parameters:**
184
- | Parameter | Type | Description |
185
- |-----------|------|-------------|
186
- | `filter` | Object | Field filters |
187
- | `sort` | string | Sort order (e.g., '-createdAt,name') |
188
- | `page.size` | number | Page size |
189
- | `page.number` | number | Page number |
190
- | `search` | string | Search term |
191
- | `include` | string | Related resources to include |
192
-
193
- **Returns:** Promise<{ data: Resource[], meta: Object, links: Object }>
194
-
195
- **Example:**
196
- ```javascript
197
- const result = await api.query({
198
- filter: { active: true },
199
- sort: '-createdAt',
200
- page: { size: 10, number: 1 }
201
- }, { type: 'users' });
202
- ```
203
-
204
- #### `insert(data, options)`
205
- Create a new resource.
206
-
207
- **Parameters:**
208
- - `data` (Object): Resource data
209
- - `options` (Object): Operation options
210
-
211
- **Additional Options:**
212
- | Option | Type | Description |
213
- |--------|------|-------------|
214
- | `positioning` | Object | Positioning options |
215
- | `skipValidation` | boolean | Skip validation |
216
- | `fullRecord` | boolean | Validate all fields |
217
-
218
- **Returns:** Promise<{ data: Resource }>
219
-
220
- **Example:**
221
- ```javascript
222
- const result = await api.insert({
223
- name: 'John Doe',
224
- email: 'john@example.com'
225
- }, { type: 'users' });
226
- ```
227
-
228
- #### `update(id, data, options)`
229
- Update an existing resource.
230
-
231
- **Parameters:**
232
- - `id` (string|number): Resource identifier
233
- - `data` (Object): Update data
234
- - `options` (Object): Operation options
235
-
236
- **Returns:** Promise<{ data: Resource }>
237
-
238
- **Example:**
239
- ```javascript
240
- const result = await api.update('123', {
241
- name: 'Jane Doe'
242
- }, { type: 'users' });
243
- ```
244
-
245
- #### `delete(id, options)`
246
- Delete a resource.
247
-
248
- **Parameters:**
249
- - `id` (string|number): Resource identifier
250
- - `options` (Object): Operation options
251
-
252
- **Returns:** Promise<{ data: null }>
253
-
254
- **Example:**
255
- ```javascript
256
- await api.delete('123', { type: 'users' });
257
- ```
258
-
259
- #### `addResource(type, schema, hooks?)`
260
- Register a resource type with its schema and optional hooks.
261
-
262
- **Parameters:**
263
- - `type` (string): Resource type name
264
- - `schema` (Schema): Schema instance
265
- - `hooks` (object, optional): Hook functions for this resource
266
-
267
- **Example:**
268
- ```javascript
269
- const userHooks = {
270
- async afterValidate(context) {
271
- // Custom validation
272
- },
273
- async transformResult(context) {
274
- // Transform output
275
- }
276
- };
277
-
278
- api.addResource('users', userSchema, userHooks);
279
- ```
280
-
281
- **Available hooks:**
282
- - `beforeValidate` - Before schema validation
283
- - `afterValidate` - After schema validation
284
- - `beforeGet` - Before fetching single record
285
- - `afterGet` - After fetching single record
286
- - `beforeQuery` - Before querying records
287
- - `afterQuery` - After querying records
288
- - `beforeInsert` - Before inserting
289
- - `afterInsert` - After inserting
290
- - `beforeUpdate` - Before updating
291
- - `afterUpdate` - After updating
292
- - `beforeDelete` - Before deleting
293
- - `afterDelete` - After deleting
294
- - `transformResult` - Transform results before sending
295
-
296
- #### `resource(type)`
297
- Alternative method to access a resource.
298
-
299
- **Parameters:**
300
- - `type` (string): Resource type name
301
-
302
- **Returns:** Resource proxy object
303
-
304
- **Example:**
305
- ```javascript
306
- // Useful when resource name is dynamic
307
- const resourceName = getUserResourceName();
308
- const data = await api.resource(resourceName).get(123);
309
- ```
310
-
311
- ### Resource Proxy Methods
312
-
313
- Each resource accessible via `api.resources.{name}` has the following methods:
314
-
315
- #### Resource CRUD Methods
316
-
317
- ##### `get(id, options)`
318
- Fetch a single resource.
319
-
320
- ```javascript
321
- const user = await api.resources.users.get(123);
322
- ```
323
-
324
- ##### `query(params, options)`
325
- Query multiple resources.
326
-
327
- ```javascript
328
- const users = await api.resources.users.query({
329
- filter: { active: true },
330
- sort: '-createdAt'
331
- });
332
- ```
333
-
334
- ##### `create(data, options)` / `post(data, options)`
335
- Create a new resource.
336
-
337
- ```javascript
338
- const user = await api.resources.users.create({
339
- name: 'John Doe',
340
- email: 'john@example.com'
341
- });
342
- ```
343
-
344
- ##### `update(id, data, options)` / `put(id, data, options)`
345
- Update an existing resource.
346
-
347
- ```javascript
348
- const updated = await api.resources.users.update(123, {
349
- email: 'newemail@example.com'
350
- });
351
- ```
352
-
353
- ##### `delete(id, options)` / `remove(id, options)`
354
- Delete a resource.
355
-
356
- ```javascript
357
- await api.resources.users.delete(123);
358
- ```
359
-
360
- #### Resource Versioning
361
-
362
- ##### `version(versionSpec)`
363
- Access a specific version of the resource.
364
-
365
- ```javascript
366
- // Access version 1.0.0 of users
367
- const userV1 = await api.resources.users.version('1.0.0').get(123);
368
-
369
- // Access latest 2.x version
370
- const userV2 = await api.resources.users.version('^2.0.0').get(123);
371
- ```
372
-
373
- #### Batch Operations
374
-
375
- ##### `batch.create(items, options)`
376
- Create multiple resources.
377
-
378
- ```javascript
379
- const users = await api.resources.users.batch.create([
380
- { name: 'User 1' },
381
- { name: 'User 2' }
382
- ]);
383
- ```
384
-
385
- ##### `batch.update(updates, options)`
386
- Update multiple resources.
387
-
388
- ```javascript
389
- await api.resources.users.batch.update([
390
- { id: 1, data: { active: false } },
391
- { id: 2, data: { active: false } }
392
- ]);
393
- ```
394
-
395
- ##### `batch.delete(ids, options)`
396
- Delete multiple resources.
397
-
398
- ```javascript
399
- await api.resources.users.batch.delete([1, 2, 3]);
400
- ```
401
-
402
- #### Resource Properties
403
-
404
- ##### `schema`
405
- Access the resource's schema.
406
-
407
- ```javascript
408
- const userSchema = api.resources.users.schema;
409
- ```
410
-
411
- ##### `hooks`
412
- Access the resource's hooks.
413
-
414
- ```javascript
415
- const userHooks = api.resources.users.hooks;
416
- ```
417
-
418
- #### `getSchema(type)`
419
- Get the schema for a resource type.
420
-
421
- **Parameters:**
422
- - `type` (string): Resource type name
423
-
424
- **Returns:** Schema instance or undefined
425
-
426
- #### `mount(app, basePath)`
427
- Mount HTTP routes on Express app (requires HTTPPlugin).
428
-
429
- **Parameters:**
430
- - `app` (Express app): Express application
431
- - `basePath` (string): Base path for routes (default: '/api')
432
-
433
- **Example:**
434
- ```javascript
435
- api.mount(app, '/api/v1');
436
- ```
437
-
438
- ### Static Methods
439
-
440
- #### `Api.get(name, version)`
441
- Get a registered API by name and version.
442
-
443
- **Parameters:**
444
- - `name` (string): API name
445
- - `version` (string): Version specifier ('latest', '1.0.0', '>=1.0.0', etc.)
446
-
447
- **Returns:** Api instance or null
448
-
449
- **Example:**
450
- ```javascript
451
- const api = Api.get('myapp', 'latest');
452
- const apiV1 = Api.get('myapp', '1.0.0');
453
- const apiV2Plus = Api.get('myapp', '>=2.0.0');
454
- ```
455
-
456
- #### `Api.getRegistry()`
457
- Get all registered APIs.
458
-
459
- **Returns:** Object with API names and versions
460
-
461
- **Example:**
462
- ```javascript
463
- const registry = Api.getRegistry();
464
- // { myapp: ['2.1.0', '2.0.0', '1.0.0'], otherapp: ['1.0.0'] }
465
- ```
466
-
467
- ### Properties
468
-
469
- #### `apis`
470
- Proxy object for accessing other registered APIs.
471
-
472
- **Example:**
473
- ```javascript
474
- const usersApi = api.apis.users; // Gets compatible users API
475
- ```
476
-
477
- ---
478
-
479
- ## Schema Class
480
-
481
- Defines data structure and validation rules.
482
-
483
- ### Constructor
484
-
485
- ```javascript
486
- new Schema(structure, options)
487
- ```
488
-
489
- **Parameters:**
490
- - `structure` (Object): Field definitions
491
- - `options` (Object): Schema options
492
-
493
- **Options:**
494
- | Option | Type | Default | Description |
495
- |--------|------|---------|-------------|
496
- | `emptyAsNull` | boolean | false | Convert empty strings to null |
497
- | `canBeNull` | boolean | false | Allow null values by default |
498
-
499
- ### Field Definition
500
-
501
- ```javascript
502
- {
503
- type: 'string', // Required: field type
504
- required: false, // Field is required
505
- default: null, // Default value or function
506
- canBeNull: false, // Can be null
507
- emptyAsNull: false, // Empty string becomes null
508
-
509
- // Type-specific options
510
- min: 0, // Minimum value/length
511
- max: 100, // Maximum value/length
512
- pattern: /regex/, // Regex pattern (strings)
513
- enum: ['a', 'b'], // Allowed values
514
-
515
- // String options
516
- lowercase: false, // Convert to lowercase
517
- uppercase: false, // Convert to uppercase
518
- trim: 50, // Trim to length
519
- noTrim: false, // Don't trim whitespace
520
-
521
- // Validation
522
- validator: fn, // Custom validator function
523
- notEmpty: false, // Can't be empty string
524
-
525
- // Documentation
526
- description: '', // Field description
527
- example: '', // Example value
528
-
529
- // Special
530
- silent: false, // Hide from responses
531
- searchable: false, // Include in search
532
- unique: false // Must be unique (custom)
533
- }
534
- ```
535
-
536
- ### Methods
537
-
538
- #### `use(plugin, options)`
539
- Add a plugin to the schema.
540
-
541
- **Parameters:**
542
- - `plugin` (Object): Plugin with `install` method
543
- - `options` (Object): Plugin options
544
-
545
- **Returns:** `this`
546
-
547
- #### `registerType(name, handler)`
548
- Register a custom type handler.
549
-
550
- **Parameters:**
551
- - `name` (string): Type name
552
- - `handler` (Function): Type handler function
553
-
554
- **Handler Parameters:**
555
- ```javascript
556
- {
557
- definition: {}, // Field definition
558
- value: any, // Current value
559
- fieldName: string, // Field name
560
- object: {}, // Full object
561
- options: {}, // Validation options
562
- computedOptions: {} // Computed options
563
- }
564
- ```
565
-
566
- **Example:**
567
- ```javascript
568
- schema.registerType('phone', ({ value }) => {
569
- const cleaned = value.replace(/\D/g, '');
570
- if (cleaned.length !== 10) throw new Error('Invalid phone');
571
- return cleaned;
572
- });
573
- ```
574
-
575
- #### `registerParam(name, handler)`
576
- Register a custom parameter handler.
577
-
578
- **Parameters:**
579
- - `name` (string): Parameter name
580
- - `handler` (Function): Parameter handler function
581
-
582
- **Example:**
583
- ```javascript
584
- schema.registerParam('unique', async ({ value, fieldName }) => {
585
- const exists = await checkUnique(fieldName, value);
586
- if (exists) throw new Error(`${fieldName} must be unique`);
587
- });
588
- ```
589
-
590
- #### `validate(object, options)`
591
- Validate an object against the schema.
592
-
593
- **Parameters:**
594
- - `object` (Object): Object to validate
595
- - `options` (Object): Validation options
596
-
597
- **Validation Options:**
598
- | Option | Type | Description |
599
- |--------|------|-------------|
600
- | `onlyObjectValues` | boolean | Only validate provided fields |
601
- | `skipFields` | string[] | Fields to skip |
602
- | `skipParams` | Object | Parameters to skip by field |
603
- | `emptyAsNull` | boolean | Convert empty to null |
604
- | `canBeNull` | boolean | Allow null values |
605
-
606
- **Returns:** Promise<{ validatedObject: Object, errors: Array }>
607
-
608
- **Example:**
609
- ```javascript
610
- const { validatedObject, errors } = await schema.validate({
611
- name: 'John',
612
- email: 'john@example.com'
613
- });
614
- ```
615
-
616
- #### `cleanup(object, parameterName)`
617
- Get object with only fields having specific parameter.
618
-
619
- **Parameters:**
620
- - `object` (Object): Source object
621
- - `parameterName` (string): Parameter to filter by
622
-
623
- **Returns:** Filtered object
624
-
625
- ### Built-in Types
626
-
627
- | Type | Description | Casts From | Default |
628
- |------|-------------|------------|---------|
629
- | `none` | No casting | - | - |
630
- | `string` | String value | Any with toString() | `''` |
631
- | `number` | Numeric value | Numeric strings | `0` |
632
- | `boolean` | Boolean value | Strings, numbers | `false` |
633
- | `id` | Integer ID | Numeric strings | - |
634
- | `timestamp` | Unix timestamp | Date strings, numbers | - |
635
- | `date` | Date (YYYY-MM-DD) | Date objects, strings | - |
636
- | `dateTime` | DateTime | Date objects, strings | - |
637
- | `array` | Array | Single values | `[]` |
638
- | `object` | Object | Objects | `{}` |
639
- | `serialize` | Circular JSON | Any | - |
640
- | `blob` | Binary data | - | - |
641
-
642
- ---
643
-
644
- # Plugin Reference
645
-
646
- ## ValidationPlugin
647
-
648
- Automatically included. Provides schema validation for all operations.
649
-
650
- ### Installation
651
- ```javascript
652
- api.use(ValidationPlugin); // Usually automatic
653
- ```
654
-
655
- ### Features
656
- - Validates data against registered schemas
657
- - Supports custom validation hooks
658
- - Provides detailed error messages
659
- - Handles cross-field validation
660
-
661
- ### Hooks Added
662
- - `beforeValidate`: Prepare data for validation
663
- - `afterValidate`: Additional validation logic
664
-
665
- ### Methods Added
666
- - `api.addResource(type, schema, hooks?)`: Register resource with schema and hooks
667
- - `api.getSchema(type)`: Get schema
668
- - `api.createSearchSchema(schema, fields)`: Create search schema
669
-
670
- ---
671
-
672
- ## MemoryPlugin
673
-
674
- In-memory storage backend.
675
-
676
- ### Installation
677
- ```javascript
678
- api.use(MemoryPlugin, {
679
- initialData: [], // Initial data array
680
- initialIdCounter: 1 // Starting ID value
681
- });
682
- ```
683
-
684
- ### Features
685
- - Fast in-memory storage
686
- - Full CRUD operations
687
- - Filtering and sorting
688
- - Pagination support
689
- - Search functionality
690
-
691
- ### Storage Access
692
- ```javascript
693
- api.memoryData // Direct access to data array
694
- api.memoryIdCounter // Current ID counter
695
- ```
696
-
697
- ---
698
-
699
- ## MySQLPlugin
700
-
701
- MySQL database storage backend.
702
-
703
- ### Installation
704
- ```javascript
705
- api.use(MySQLPlugin, {
706
- connection: {
707
- host: 'localhost',
708
- user: 'root',
709
- password: 'password',
710
- database: 'myapp',
711
- waitForConnections: true,
712
- connectionLimit: 10,
713
- queueLimit: 0
714
- }
715
- });
716
-
717
- // Or multiple connections
718
- api.use(MySQLPlugin, {
719
- connections: [
720
- {
721
- name: 'primary',
722
- config: { host: 'primary.db', ... }
723
- },
724
- {
725
- name: 'replica',
726
- config: { host: 'replica.db', ... }
727
- }
728
- ]
729
- });
730
- ```
731
-
732
- ### Methods Added
733
-
734
- #### `api.syncSchema(schema, table, options)`
735
- Synchronize database table with schema.
736
-
737
- **Parameters:**
738
- - `schema` (Schema): Schema to sync
739
- - `table` (string): Table name
740
- - `options` (Object): Sync options
741
-
742
- **Options:**
743
- | Option | Type | Description |
744
- |--------|------|-------------|
745
- | `connection` | string | Connection name |
746
- | `idProperty` | string | ID field name |
747
-
748
- **Example:**
749
- ```javascript
750
- await api.syncSchema(userSchema, 'users');
751
- ```
752
-
753
- #### `api.getConnection(name)`
754
- Get connection pool by name.
755
-
756
- **Parameters:**
757
- - `name` (string): Connection name (default: 'default')
758
-
759
- **Returns:** { pool: MySQLPool, options: Object }
760
-
761
- ### Schema Sync Features
762
- - Creates tables if not exists
763
- - Adds new columns
764
- - Updates column types
765
- - Creates indexes for searchable fields
766
- - Handles foreign key constraints
767
-
768
- ### Field Type Mapping
769
-
770
- | Schema Type | MySQL Type | Notes |
771
- |-------------|------------|-------|
772
- | `id` | `INT AUTO_INCREMENT` | Primary key |
773
- | `number` | `INT` | Or FLOAT, DECIMAL |
774
- | `string` | `VARCHAR(n)` | Or TEXT |
775
- | `boolean` | `BOOLEAN` | |
776
- | `timestamp` | `BIGINT` | Unix timestamp |
777
- | `date` | `DATE` | |
778
- | `dateTime` | `DATETIME` | |
779
- | `array` | `JSON` | |
780
- | `object` | `JSON` | |
781
- | `serialize` | `JSON` | |
782
- | `blob` | `BLOB` | |
783
-
784
- ---
785
-
786
- ## HTTPPlugin
787
-
788
- Provides RESTful HTTP endpoints.
789
-
790
- ### Installation
791
- ```javascript
792
- api.use(HTTPPlugin, {
793
- basePath: '/api', // Base URL path
794
- app: expressApp, // Express app (optional)
795
- typeOptions: { // Per-type options
796
- users: {
797
- searchFields: ['name', 'email']
798
- }
799
- }
800
- });
801
- ```
802
-
803
- ### Routes Created
804
-
805
- | Method | Path | Description |
806
- |--------|------|-------------|
807
- | GET | `/{type}` | List resources |
808
- | GET | `/{type}/{id}` | Get single resource |
809
- | POST | `/{type}` | Create resource |
810
- | PATCH | `/{type}/{id}` | Update resource |
811
- | DELETE | `/{type}/{id}` | Delete resource |
812
- | OPTIONS | `*` | CORS preflight |
813
-
814
- ### Query Parameters
815
-
816
- | Parameter | Example | Description |
817
- |-----------|---------|-------------|
818
- | `filter[field]` | `filter[active]=true` | Filter by field |
819
- | `sort` | `sort=-createdAt,name` | Sort order |
820
- | `page[size]` | `page[size]=20` | Page size |
821
- | `page[number]` | `page[number]=2` | Page number |
822
- | `fields[type]` | `fields[users]=id,name` | Sparse fields |
823
- | `include` | `include=posts,comments` | Include relations |
824
-
825
- ### Request/Response Format
826
-
827
- **Request Body (POST/PATCH):**
828
- ```json
829
- {
830
- "data": {
831
- "type": "users",
832
- "attributes": {
833
- "name": "John Doe",
834
- "email": "john@example.com"
835
- }
836
- }
837
- }
838
- ```
839
-
840
- **Response Format:**
841
- ```json
842
- {
843
- "data": {
844
- "id": "123",
845
- "type": "users",
846
- "attributes": {
847
- "name": "John Doe",
848
- "email": "john@example.com"
849
- }
850
- },
851
- "meta": {
852
- "total": 100
853
- },
854
- "links": {
855
- "self": "/api/users/123"
856
- }
857
- }
858
- ```
859
-
860
- ### Methods Added
861
-
862
- #### `api.mount(app, basePath)`
863
- Mount routes on Express app.
864
-
865
- #### `api.useMiddleware(middleware)`
866
- Add middleware to all routes.
867
-
868
- #### `api.useRouteMiddleware(method, path, middleware)`
869
- Add middleware to specific route.
870
-
871
- ---
872
-
873
- ## PositioningPlugin
874
-
875
- Manage record ordering for drag-and-drop interfaces.
876
-
877
- ### Installation
878
- ```javascript
879
- api.use(PositioningPlugin, {
880
- positionField: 'position', // Position field name
881
- beforeIdField: 'beforeId', // Virtual field for positioning
882
- positionFilters: ['projectId'] // Group by these fields
883
- });
884
- ```
885
-
886
- ### Features
887
- - Automatic position management
888
- - Drag-and-drop support
889
- - Position groups/scopes
890
- - Gap-free positioning
891
-
892
- ### Usage
893
-
894
- **Insert with position:**
895
- ```javascript
896
- await api.insert({
897
- title: 'Task',
898
- beforeId: '123' // Insert before this ID
899
- }, {
900
- type: 'tasks',
901
- positioning: { enabled: true }
902
- });
903
-
904
- // beforeId values:
905
- // - null: Insert at end
906
- // - undefined: Keep current position (update) or end (insert)
907
- // - ID: Insert before specified record
908
- ```
909
-
910
- ### Methods Added
911
-
912
- #### `api.reposition(type, recordId, beforeId, options)`
913
- Reposition existing record.
914
-
915
- **Parameters:**
916
- - `type` (string): Resource type
917
- - `recordId` (string): Record to move
918
- - `beforeId` (string|null): Position before this ID
919
- - `options` (Object): Positioning options
920
-
921
- #### `api.getNextPosition(type, filters, options)`
922
- Get next available position.
923
-
924
- **Returns:** Promise<number>
925
-
926
- #### `api.normalizePositions(type, filters, options)`
927
- Remove gaps in position numbers.
928
-
929
- ---
930
-
931
- ## VersioningPlugin
932
-
933
- API versioning and resource version tracking.
934
-
935
- ### Installation
936
- ```javascript
937
- api.use(VersioningPlugin, {
938
- // API versioning
939
- apiVersion: '2.0.0',
940
- versionHeader: 'api-version',
941
- versionParam: 'v',
942
-
943
- // Resource versioning
944
- versionField: 'version',
945
- lastModifiedField: 'lastModified',
946
- modifiedByField: 'modifiedBy',
947
- trackHistory: true,
948
- historyTable: 'posts_history',
949
- optimisticLocking: true
950
- });
951
- ```
952
-
953
- ### Features
954
- - Automatic API version negotiation
955
- - Resource version tracking
956
- - Version history
957
- - Optimistic locking
958
- - Version comparison
959
-
960
- ### Methods Added
961
-
962
- #### `api.getVersionHistory(type, id, options)`
963
- Get version history for a resource.
964
-
965
- **Returns:** Promise<{ data: VersionHistory[] }>
966
-
967
- #### `api.restoreVersion(type, id, version, options)`
968
- Restore a specific version.
969
-
970
- **Returns:** Promise<{ data: Resource }>
971
-
972
- #### `api.diffVersions(type, id, version1, version2, options)`
973
- Compare two versions.
974
-
975
- **Returns:** Promise<VersionDiff>
976
-
977
- ```javascript
978
- {
979
- version1: 1,
980
- version2: 2,
981
- changes: [
982
- { field: 'title', oldValue: 'Old', newValue: 'New' }
983
- ]
984
- }
985
- ```
986
-
987
- ### Version Headers
988
- - Request: `API-Version: 2.0.0`
989
- - Response: `API-Version: 2.0.0`
990
-
991
- ---
992
-
993
- ## SecurityPlugin
994
-
995
- Comprehensive security features.
996
-
997
- ### Installation
998
- ```javascript
999
- api.use(SecurityPlugin, {
1000
- // Rate limiting
1001
- rateLimit: {
1002
- windowMs: 15 * 60 * 1000, // 15 minutes
1003
- max: 100, // Max requests
1004
- message: 'Too many requests'
1005
- },
1006
-
1007
- // CORS
1008
- cors: {
1009
- origin: '*',
1010
- credentials: true,
1011
- methods: ['GET', 'POST', 'PATCH', 'DELETE'],
1012
- allowedHeaders: ['Content-Type', 'Authorization'],
1013
- exposedHeaders: ['X-Total-Count']
1014
- },
1015
-
1016
- // Authentication
1017
- authentication: {
1018
- type: 'bearer', // 'bearer', 'basic', 'apikey'
1019
- header: 'Authorization',
1020
- queryParam: 'api_key',
1021
- required: true
1022
- },
1023
-
1024
- // Token verification
1025
- verifyToken: async (token, context) => {
1026
- // Return user object or throw
1027
- return { id: '123', roles: ['admin'] };
1028
- },
1029
-
1030
- // Options
1031
- publicRead: false, // Allow GET without auth
1032
- allowUnknownFilters: false
1033
- });
1034
- ```
1035
-
1036
- ### Security Headers Added
1037
- - `X-Content-Type-Options: nosniff`
1038
- - `X-Frame-Options: DENY`
1039
- - `X-XSS-Protection: 1; mode=block`
1040
- - `Strict-Transport-Security`
1041
- - `Content-Security-Policy`
1042
- - `X-Request-ID`
1043
-
1044
- ### Rate Limit Headers
1045
- - `X-RateLimit-Limit`
1046
- - `X-RateLimit-Remaining`
1047
- - `X-RateLimit-Reset`
1048
-
1049
- ### Methods Added
1050
-
1051
- #### `api.generateToken(payload, expiresIn)`
1052
- Generate authentication token.
1053
-
1054
- #### `api.verifyToken(token)`
1055
- Verify authentication token.
1056
-
1057
- ---
1058
-
1059
- ## LoggingPlugin
1060
-
1061
- Structured logging with sensitive data protection.
1062
-
1063
- ### Installation
1064
- ```javascript
1065
- api.use(LoggingPlugin, {
1066
- level: 'info', // error, warn, info, debug
1067
- format: 'json', // json or pretty
1068
- includeRequest: true,
1069
- includeResponse: true,
1070
- includeTiming: true,
1071
- sensitiveFields: ['password', 'token'],
1072
- logger: console, // Or Winston, Bunyan, etc.
1073
- auditLog: false // Enable audit logging
1074
- });
1075
- ```
1076
-
1077
- ### Log Levels
1078
- - `error`: Errors only
1079
- - `warn`: Warnings and above
1080
- - `info`: Info and above
1081
- - `debug`: Everything
1082
-
1083
- ### Methods Added
1084
-
1085
- #### `api.log`
1086
- Structured logger with methods:
1087
- - `api.log.error(message, meta)`
1088
- - `api.log.warn(message, meta)`
1089
- - `api.log.info(message, meta)`
1090
- - `api.log.debug(message, meta)`
1091
-
1092
- **Example:**
1093
- ```javascript
1094
- api.log.info('User created', {
1095
- userId: '123',
1096
- email: 'user@example.com',
1097
- ip: req.ip
1098
- });
1099
- ```
1100
-
1101
- ### Automatic Logging
1102
- - All API operations
1103
- - HTTP requests/responses
1104
- - SQL queries (with MySQL)
1105
- - Validation errors
1106
- - Performance metrics
1107
-
1108
- ---
1109
-
1110
- ## OpenAPIPlugin
1111
-
1112
- Auto-generate OpenAPI documentation.
1113
-
1114
- ### Installation
1115
- ```javascript
1116
- api.use(OpenAPIPlugin, {
1117
- title: 'My API',
1118
- version: '1.0.0',
1119
- description: 'API description',
1120
- servers: [
1121
- { url: 'https://api.example.com', description: 'Production' },
1122
- { url: 'http://localhost:3000', description: 'Development' }
1123
- ],
1124
- contact: {
1125
- name: 'API Support',
1126
- email: 'support@example.com',
1127
- url: 'https://example.com/support'
1128
- },
1129
- license: {
1130
- name: 'MIT',
1131
- url: 'https://opensource.org/licenses/MIT'
1132
- }
1133
- });
1134
- ```
1135
-
1136
- ### Endpoints Added
1137
- - `GET /openapi.json` - OpenAPI specification
1138
- - `GET /docs` - Swagger UI
1139
-
1140
- ### Methods Added
1141
-
1142
- #### `api.generateOpenAPISpec()`
1143
- Generate OpenAPI 3.0 specification.
1144
-
1145
- **Returns:** OpenAPI specification object
1146
-
1147
- ### Schema Documentation
1148
- ```javascript
1149
- const schema = new Schema({
1150
- email: {
1151
- type: 'string',
1152
- required: true,
1153
- description: 'User email address',
1154
- example: 'user@example.com',
1155
- pattern: '^[^@]+@[^@]+$'
1156
- }
1157
- });
1158
- ```
1159
-
1160
- ---
1161
-
1162
- # Helper Functions
1163
-
1164
- ## `createApi(options)`
1165
-
1166
- Convenience function to create a fully configured API.
1167
-
1168
- **Parameters:**
1169
- - `options` (Object): Combined options for Api and plugins
1170
-
1171
- **Options:**
1172
- ```javascript
1173
- {
1174
- // Api options
1175
- name: 'myapp',
1176
- version: '1.0.0',
1177
- idProperty: 'id',
1178
-
1179
- // Storage
1180
- storage: 'memory' | 'mysql',
1181
-
1182
- // Plugin options
1183
- memory: { /* MemoryPlugin options */ },
1184
- mysql: { /* MySQLPlugin options */ },
1185
- http: { /* HTTPPlugin options */ },
1186
- validation: { /* ValidationPlugin options */ },
1187
- positioning: { /* PositioningPlugin options */ },
1188
- versioning: { /* VersioningPlugin options */ },
1189
- security: { /* SecurityPlugin options */ },
1190
- logging: { /* LoggingPlugin options */ }
1191
- }
1192
- ```
1193
-
1194
- **Example:**
1195
- ```javascript
1196
- const api = createApi({
1197
- name: 'myapp',
1198
- version: '1.0.0',
1199
- storage: 'mysql',
1200
- mysql: {
1201
- connection: dbConfig
1202
- },
1203
- http: {
1204
- basePath: '/api'
1205
- },
1206
- security: {
1207
- authentication: { type: 'bearer' }
1208
- }
1209
- });
1210
- ```
1211
-
1212
- ---
1213
-
1214
- # Type Definitions
1215
-
1216
- ## Resource Format
1217
-
1218
- JSON:API resource format:
1219
-
1220
- ```typescript
1221
- interface Resource {
1222
- id: string;
1223
- type: string;
1224
- attributes: {
1225
- [key: string]: any;
1226
- };
1227
- relationships?: {
1228
- [key: string]: {
1229
- data: ResourceIdentifier | ResourceIdentifier[];
1230
- };
1231
- };
1232
- }
1233
-
1234
- interface ResourceIdentifier {
1235
- id: string;
1236
- type: string;
1237
- }
1238
- ```
1239
-
1240
- ## Error Format
1241
-
1242
- JSON:API error format:
1243
-
1244
- ```typescript
1245
- interface Error {
1246
- status: string; // HTTP status code
1247
- code?: string; // Application error code
1248
- title: string; // Error title
1249
- detail?: string; // Error details
1250
- source?: {
1251
- pointer?: string; // JSON pointer to error field
1252
- parameter?: string; // Query parameter that caused error
1253
- };
1254
- meta?: any; // Additional metadata
1255
- }
1256
- ```
1257
-
1258
- ## Query Response Format
1259
-
1260
- ```typescript
1261
- interface QueryResponse {
1262
- data: Resource[];
1263
- meta?: {
1264
- total: number;
1265
- pageSize: number;
1266
- pageNumber: number;
1267
- totalPages: number;
1268
- [key: string]: any;
1269
- };
1270
- links?: {
1271
- self: string;
1272
- first?: string;
1273
- last?: string;
1274
- prev?: string;
1275
- next?: string;
1276
- };
1277
- included?: Resource[];
1278
- }
1279
- ```
1280
-
1281
- ---
1282
-
1283
- # Constants
1284
-
1285
- ## VERSION
1286
- Current library version.
1287
- ```javascript
1288
- import { VERSION } from 'jsonrestapi';
1289
- console.log(VERSION); // '1.0.0'
1290
- ```
1291
-
1292
- ## Default Values
1293
-
1294
- | Constant | Default | Description |
1295
- |----------|---------|-------------|
1296
- | ID Property | `'id'` | Default ID field name |
1297
- | Page Size | `10` | Default query page size |
1298
- | Max Page Size | `1000` | Maximum allowed page size |
1299
- | Position Field | `'position'` | Default position field |
1300
- | Version Field | `'version'` | Default version field |
1301
- | Rate Limit Window | `900000` | 15 minutes in ms |
1302
- | Rate Limit Max | `100` | Max requests per window |
1303
-
1304
- ---
1305
-
1306
- This completes the comprehensive API reference for the JSON REST API library. Every public method, option, and feature is documented with examples and type information.