codehooks-js 1.2.2 → 1.2.4
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/crudlify/index.mjs +53 -36
- package/package.json +1 -1
- package/types/index.d.ts +73 -5
package/crudlify/index.mjs
CHANGED
|
@@ -20,7 +20,7 @@ let _eventHooks = null;
|
|
|
20
20
|
* @see {@link https://codehooks.io/docs/database-rest-api}
|
|
21
21
|
* @param {object} app - Codehooks app ( npm package codehooks-js)
|
|
22
22
|
* @param {object} schema - Yup schema object
|
|
23
|
-
* @param {object} options -
|
|
23
|
+
* @param {object} options - {prefix: "/crud", schema: "yup"}
|
|
24
24
|
* @returns {Promise} EventHooks for REST operations
|
|
25
25
|
*/
|
|
26
26
|
export default async function crudlify(app, schema = {}, options = { schema: "yup", query: "q2m", prefix: "" }) {
|
|
@@ -52,35 +52,44 @@ export default async function crudlify(app, schema = {}, options = { schema: "yu
|
|
|
52
52
|
|
|
53
53
|
console.debug('Query lang', _query)
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
try {
|
|
56
|
+
// load schema validators
|
|
57
|
+
console.debug('load validators')
|
|
58
|
+
_validate = _validateYup;
|
|
59
|
+
_cast = _castYup;
|
|
60
|
+
_prepare = _prepareYup;
|
|
61
|
+
|
|
62
|
+
// schema provider other than Yup?
|
|
63
|
+
for (const property in schema) {
|
|
64
|
+
//console.log(`${property}: ${schema[property].toString()}`);
|
|
65
|
+
if (schema[property] !== undefined) {
|
|
66
|
+
if (schema[property].parse) {
|
|
67
|
+
_opt.schema = 'zod';
|
|
68
|
+
} else if (schema[property].properties) {
|
|
69
|
+
_opt.schema = 'json-schema';
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
console.error(`${property} is undefined`)
|
|
73
|
+
//schema[property] = null;
|
|
74
|
+
}
|
|
68
75
|
}
|
|
76
|
+
|
|
77
|
+
if (new String(_opt.schema).toLowerCase() === 'json-schema') {
|
|
78
|
+
_validate = _validateJSON;
|
|
79
|
+
_cast = _castJSON;
|
|
80
|
+
_prepare = _prepareJSON;
|
|
81
|
+
}
|
|
82
|
+
if (new String(_opt.schema).toLowerCase() === 'zod') {
|
|
83
|
+
_validate = _validateZod;
|
|
84
|
+
_cast = _castZod;
|
|
85
|
+
_prepare = _prepareZod;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// prep schemas
|
|
89
|
+
_schema = _prepare(_schema, _opt);
|
|
90
|
+
} catch (ex) {
|
|
91
|
+
throw new Error(ex)
|
|
69
92
|
}
|
|
70
|
-
|
|
71
|
-
if (new String(_opt.schema).toLowerCase() === 'json-schema') {
|
|
72
|
-
_validate = _validateJSON;
|
|
73
|
-
_cast = _castJSON;
|
|
74
|
-
_prepare = _prepareJSON;
|
|
75
|
-
}
|
|
76
|
-
if (new String(_opt.schema).toLowerCase() === 'zod') {
|
|
77
|
-
_validate = _validateZod;
|
|
78
|
-
_cast = _castZod;
|
|
79
|
-
_prepare = _prepareZod;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// prep schemas
|
|
83
|
-
_schema = _prepare(_schema, _opt);
|
|
84
93
|
|
|
85
94
|
console.debug('Apply routes to app');
|
|
86
95
|
// App API routes
|
|
@@ -150,7 +159,8 @@ async function createFunc(req, res) {
|
|
|
150
159
|
res.status(400).send(ex);
|
|
151
160
|
}
|
|
152
161
|
} else {
|
|
153
|
-
|
|
162
|
+
console.error('schema for' ,collection, 'is not valid:', _schema[collection])
|
|
163
|
+
return res.status(400).json({ "error": `Collection schema not found: ${collection}` });
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
}
|
|
@@ -161,7 +171,8 @@ async function readManyFunc(req, res) {
|
|
|
161
171
|
try {
|
|
162
172
|
const { collection } = req.params;
|
|
163
173
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
164
|
-
|
|
174
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
175
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
165
176
|
}
|
|
166
177
|
|
|
167
178
|
const mongoQuery = _query(req.query, req.headers);
|
|
@@ -181,7 +192,8 @@ async function readOneFunc(req, res) {
|
|
|
181
192
|
const conn = await Datastore.open();
|
|
182
193
|
try {
|
|
183
194
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
184
|
-
|
|
195
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
196
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
185
197
|
}
|
|
186
198
|
console.log(req.headers['x-real-ip'], req.method, req.originalUrl);
|
|
187
199
|
const result = await conn.getOne(collection, ID);
|
|
@@ -198,7 +210,8 @@ async function updateFunc(req, res) {
|
|
|
198
210
|
|
|
199
211
|
try {
|
|
200
212
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
201
|
-
|
|
213
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
214
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
202
215
|
}
|
|
203
216
|
const document = req.body;
|
|
204
217
|
delete document._id; // avoid schema validation error
|
|
@@ -237,7 +250,8 @@ async function patchFunc(req, res) {
|
|
|
237
250
|
const { collection, ID } = req.params;
|
|
238
251
|
try {
|
|
239
252
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
240
|
-
|
|
253
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
254
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
241
255
|
}
|
|
242
256
|
const document = req.body;
|
|
243
257
|
console.log(req.headers['x-real-ip'], req.method, req.originalUrl);
|
|
@@ -257,7 +271,8 @@ async function patchFunc(req, res) {
|
|
|
257
271
|
async function patchManyFunc(req, res) {
|
|
258
272
|
const { collection } = req.params;
|
|
259
273
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
260
|
-
|
|
274
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
275
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
261
276
|
}
|
|
262
277
|
|
|
263
278
|
try {
|
|
@@ -280,7 +295,8 @@ async function patchManyFunc(req, res) {
|
|
|
280
295
|
async function deleteFunc(req, res) {
|
|
281
296
|
const { collection, ID } = req.params;
|
|
282
297
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
283
|
-
|
|
298
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
299
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
284
300
|
}
|
|
285
301
|
try {
|
|
286
302
|
console.log(req.headers['x-real-ip'], req.method, req.originalUrl);
|
|
@@ -300,7 +316,8 @@ async function deleteFunc(req, res) {
|
|
|
300
316
|
async function deleteManyFunc(req, res) {
|
|
301
317
|
const { collection } = req.params;
|
|
302
318
|
if (Object.keys(_schema).length > 0 && _schema[collection] === undefined) {
|
|
303
|
-
|
|
319
|
+
console.error('Invalid schema for', collection, _schema[collection])
|
|
320
|
+
return res.status(404).json({error: `Schema error for collection ${collection}`})
|
|
304
321
|
}
|
|
305
322
|
|
|
306
323
|
try {
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
/**
|
|
2
3
|
* Built-in persistent datastore.
|
|
3
4
|
* - Datastore is capable of serving NoSQL object data and Key-Value data.
|
|
@@ -36,14 +37,74 @@ export namespace schedule {
|
|
|
36
37
|
export namespace filestore {
|
|
37
38
|
/**
|
|
38
39
|
* Raad file content as stream
|
|
39
|
-
* @
|
|
40
|
+
* @see {@link https://codehooks.io/docs/fileapi#filestoregetreadstreampath API docs}
|
|
41
|
+
* @param path Absolute path to file
|
|
40
42
|
* @param options Not in use
|
|
43
|
+
* @returns Promise EventEmitter with chunks on data
|
|
44
|
+
* @example
|
|
45
|
+
* app.get('/image', async (req: httpRequest, res: httpResponse) => {
|
|
46
|
+
* const bufStream = await filestore.getReadStream('/img/logo.png');
|
|
47
|
+
* res.set('content-type', 'image/png')
|
|
48
|
+
* bufStream.on('data', (buf) => {
|
|
49
|
+
* res.write(buf, 'buffer')
|
|
50
|
+
* })
|
|
51
|
+
* .on('end', () => {
|
|
52
|
+
* res.end()
|
|
53
|
+
* })
|
|
54
|
+
* })
|
|
55
|
+
*/
|
|
56
|
+
function getReadStream(path: string, options?: any): Promise<any>;
|
|
57
|
+
/**
|
|
58
|
+
* Read file content as string
|
|
59
|
+
* @see {@link https://codehooks.io/docs/fileapi#filestorereadfilepath API docs}
|
|
60
|
+
* @param path Absolute path to file
|
|
61
|
+
* @param options
|
|
62
|
+
* @returns Promise File content as string
|
|
41
63
|
*/
|
|
42
|
-
function getReadStream(path: string, options?: any): Promise<ReadableStream>;
|
|
43
64
|
function readFile(path: string, options?: any): Promise<String>;
|
|
65
|
+
/**
|
|
66
|
+
* Save file binary buffer
|
|
67
|
+
* @see {@link https://codehooks.io/docs/fileapi#filestoresavefilepath-filestream API docs}
|
|
68
|
+
* @param path Abolute path to file, e.g. /static/home.html
|
|
69
|
+
* @param buffer Stream data
|
|
70
|
+
* @param options Not in use
|
|
71
|
+
* @returns Promise with save result
|
|
72
|
+
* @example
|
|
73
|
+
* import {PassThrough} from 'stream';
|
|
74
|
+
* app.post('/file', async (req, res) => {
|
|
75
|
+
* try {
|
|
76
|
+
* const stream = new PassThrough();
|
|
77
|
+
* req.pipe(stream);
|
|
78
|
+
* const result = await filestore.saveFile('/static.html', stream);
|
|
79
|
+
* res.end(result)
|
|
80
|
+
* } catch (error) {
|
|
81
|
+
* console.error(error)
|
|
82
|
+
* res.status(404).end('Bad upload')
|
|
83
|
+
* }
|
|
84
|
+
* })
|
|
85
|
+
*/
|
|
44
86
|
function saveFile(path: string, buffer: any, options?: any): Promise<any>;
|
|
87
|
+
/**
|
|
88
|
+
* Delete file
|
|
89
|
+
* @see {@link https://codehooks.io/docs/fileapi#filestoredeletefilepath API docs}
|
|
90
|
+
* @param path
|
|
91
|
+
* @param options
|
|
92
|
+
*/
|
|
45
93
|
function deleteFile(path: string, options?: any): Promise<any>;
|
|
94
|
+
/**
|
|
95
|
+
* List file directories and files
|
|
96
|
+
* @see {@link https://codehooks.io/docs/fileapi#filestorelistpath API docs}
|
|
97
|
+
* @param path
|
|
98
|
+
* @param options
|
|
99
|
+
*/
|
|
46
100
|
function list(path: string, options?: any): Promise<Array<Object>>;
|
|
101
|
+
/**
|
|
102
|
+
* Read binary buffer from file
|
|
103
|
+
* @param path Path to file
|
|
104
|
+
* @returns Promise with Buffer
|
|
105
|
+
* @example
|
|
106
|
+
* const myBuf = await filestore.getFileAsBuffer('/images/logo.png');
|
|
107
|
+
*/
|
|
47
108
|
function readFileAsBuffer(path: any): Promise<any>;
|
|
48
109
|
}
|
|
49
110
|
export default _coho;
|
|
@@ -283,6 +344,12 @@ export type httpRequest = {
|
|
|
283
344
|
* - Get the project URL domain name
|
|
284
345
|
*/
|
|
285
346
|
hostname: string;
|
|
347
|
+
/**
|
|
348
|
+
* Pipe data to stream
|
|
349
|
+
* @param data
|
|
350
|
+
* @returns
|
|
351
|
+
*/
|
|
352
|
+
pipe: (data: any) => void;
|
|
286
353
|
};
|
|
287
354
|
export type httpResponse = {
|
|
288
355
|
/**
|
|
@@ -300,8 +367,9 @@ export type httpResponse = {
|
|
|
300
367
|
/**
|
|
301
368
|
* - Write stream data to the client response.
|
|
302
369
|
* - Content-type must be set before any write operations
|
|
370
|
+
* - set optional type to 'buffer' for binary write operations
|
|
303
371
|
*/
|
|
304
|
-
write: (data: string) => any;
|
|
372
|
+
write: (data: any, type?: string) => any;
|
|
305
373
|
/**
|
|
306
374
|
* - Set a response header value,
|
|
307
375
|
* - e.g. res.set('Content-Type', 'text/html; charset=UTF-8');
|
|
@@ -327,7 +395,7 @@ export type Filesystem = {
|
|
|
327
395
|
/**
|
|
328
396
|
* - Get binary file input stream. Takes a path (string) to file (e.g. /static/logo.png) and an options object (Object) for future use. Returns a Promise resolving to a binary data stream emitter.
|
|
329
397
|
*/
|
|
330
|
-
getReadStream: (filePath: string, options?: any) => Promise<
|
|
398
|
+
getReadStream: (filePath: string, options?: any) => Promise<any>;
|
|
331
399
|
/**
|
|
332
400
|
* - Get file as text. Takes an absolute path (string) to file (e.g. /static/home.html) and an options object (Object) for future use. Returns a Promise resolving to the file content (string).
|
|
333
401
|
*/
|
|
@@ -454,7 +522,7 @@ import * as crud from './crudlify/index.mjs';
|
|
|
454
522
|
/**
|
|
455
523
|
* @typedef {Object} Filesystem
|
|
456
524
|
*
|
|
457
|
-
* @property {function(string, Object): Promise<ReadableStream>}
|
|
525
|
+
* @property {function(string, Object): Promise<ReadableStream>} any
|
|
458
526
|
* - Get binary file input stream. Takes a path (string) to file (e.g. /static/logo.png) and an options object (Object) for future use. Returns a Promise resolving to a binary data stream emitter.
|
|
459
527
|
*
|
|
460
528
|
* @property {function(string, Object): Promise<string>} readFile
|