nodester 0.0.1 → 0.0.6

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 (58) hide show
  1. package/Readme.md +61 -26
  2. package/lib/application/index.js +86 -35
  3. package/lib/constants/Operations.js +23 -0
  4. package/lib/controllers/methods/index.js +170 -0
  5. package/lib/controllers/mixins/index.js +213 -0
  6. package/lib/enums/Enum.js +16 -0
  7. package/lib/factories/errors/CustomError.js +7 -5
  8. package/lib/factories/responses/html.js +7 -2
  9. package/lib/factories/responses/rest.js +110 -0
  10. package/lib/http/codes/index.js +157 -0
  11. package/lib/{application/http → http}/request.js +6 -30
  12. package/lib/{application/http → http}/response.js +20 -53
  13. package/lib/middlewares/etag/index.js +62 -0
  14. package/lib/middlewares/ql/sequelize/index.js +34 -0
  15. package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
  16. package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
  17. package/lib/models/define.js +6 -13
  18. package/lib/models/mixins.js +28 -15
  19. package/lib/params/Params.js +34 -0
  20. package/lib/queries/NodesterQueryParams.js +139 -0
  21. package/lib/router/handlers.util.js +61 -0
  22. package/lib/router/index.js +386 -0
  23. package/lib/router/route.js +124 -0
  24. package/lib/router/routes.util.js +66 -0
  25. package/lib/stacks/MarkersStack.js +35 -0
  26. package/lib/{application → stacks}/MiddlewareStack.js +47 -13
  27. package/lib/utils/path.util.js +3 -1
  28. package/lib/utils/types.util.js +51 -1
  29. package/lib/validators/dates.js +25 -0
  30. package/lib/validators/numbers.js +14 -0
  31. package/package.json +16 -2
  32. package/tests/index.test.js +7 -2
  33. package/tests/nql.test.js +277 -0
  34. package/docs/App.md +0 -13
  35. package/docs/Queries.md +0 -61
  36. package/docs/Readme.md +0 -2
  37. package/docs/Routing.md +0 -34
  38. package/examples/goal/index.js +0 -23
  39. package/examples/rest/index.js +0 -25
  40. package/examples/rest/node_modules/.package-lock.json +0 -40
  41. package/examples/rest/package-lock.json +0 -72
  42. package/examples/rest/package.json +0 -14
  43. package/lib/constants/ConstantsEnum.js +0 -13
  44. package/lib/factories/responses/api.js +0 -90
  45. package/lib/routers/Default/index.js +0 -143
  46. package/lib/routers/Default/layer.js +0 -50
  47. package/lib/routers/Main/index.js +0 -10
  48. package/lib/routers/Roles/index.js +0 -81
  49. package/lib/utils/params.util.js +0 -19
  50. /package/lib/{controllers/Controller.js → _/n_controllers/Controller.js"} +0 -0
  51. /package/lib/{controllers/JWTController.js → _/n_controllers/JWTController.js"} +0 -0
  52. /package/lib/{controllers/ServiceController.js → _/n_controllers/ServiceController.js"} +0 -0
  53. /package/lib/{controllers/WebController.js → _/n_controllers/WebController.js"} +0 -0
  54. /package/lib/{facades → _facades}/Facade.js +0 -0
  55. /package/lib/{facades → _facades}/FacadeParams.js +0 -0
  56. /package/lib/{facades → _facades}/ServiceFacade.js +0 -0
  57. /package/lib/{facades → _facades}/jwt.facade.js +0 -0
  58. /package/lib/{application/http → http}/utils.js +0 -0
@@ -0,0 +1,456 @@
1
+ const Enum = require('../../../../enums/Enum');
2
+ const { ModelsTree, ModelsTreeNode } = require('./ModelsTree');
3
+ const util = require('util');
4
+ const debug = require('debug')('nodester:interpreter:QueryLexer');
5
+
6
+ const OP_TOKENS = new Enum({
7
+ AND: 'and',
8
+ BETWEEN: 'between',
9
+ NOT_BETWEEN: 'notBetween',
10
+ BETWEEN_MARK: '~',
11
+ OR: 'or',
12
+ OR_MARK: '|',
13
+ XOR: 'xor',
14
+ NOT: 'not',
15
+ NOT_MARK: '!',
16
+ NOT_IN: 'notIn',
17
+ LIKE: 'like',
18
+ GREATER: 'gt',
19
+ GREATER_OR_EQUAL: 'gte',
20
+ LOWER: 'lt',
21
+ LOWER_OR_EQUAL: 'lte'
22
+ });
23
+
24
+
25
+ module.exports = class QueryLexer {
26
+ constructor(queryString='') {
27
+ this.tree = new ModelsTree();
28
+ this.query = !!queryString ?
29
+ this.parse(queryString).toObject()
30
+ :
31
+ {};
32
+ }
33
+
34
+ parse(queryString='', tree=this.tree) {
35
+ if (typeof queryString !== 'string') {
36
+ const err = new TypeError(`Invalid 'queryString'.`);
37
+ throw err;
38
+ }
39
+
40
+ // You never know if it's encoded or not.
41
+ const decoded = decodeURI(queryString);
42
+
43
+ this.parseIsolatedQuery(decoded, 0, this.tree);
44
+
45
+ return this.tree.root;
46
+ }
47
+
48
+ parseIsolatedQuery(queryString='', startAt=0, tree) {
49
+ const isSubQuery = tree.node.model !== 'root';
50
+ debug({ isSubQuery, startAt });
51
+
52
+ // Token is accumulated char-by-char.
53
+ let token = '';
54
+ // Value of param ('id=10' OR 'fields=id,text').
55
+ let value = [];
56
+ // Model, that was active before cursor went up in the tree.
57
+ let previousActive = null;
58
+
59
+ for (let i=startAt; i < queryString.length; i++) {
60
+ const char = queryString[i];
61
+
62
+ // ( can mean params of OP token,
63
+ // or subquery of a model:
64
+ if (char === '(') {
65
+ debug('char', char, { token, node: tree.node });
66
+
67
+ // If OP token:
68
+ if (OP_TOKENS.asArray.indexOf(token) > -1) {
69
+ // Set operation token.
70
+ tree.node.op = this.parseOP(token);
71
+ token = '';
72
+ continue;
73
+ }
74
+ // If model subquery:
75
+ else {
76
+ const model = token;
77
+ tree.use(model) ?? tree.include(model).use(model);
78
+ token = '';
79
+
80
+ // Process subquery:
81
+ i++;
82
+ const [ charsCount ] = this.parseIsolatedQuery(queryString, i, tree);
83
+ i += charsCount;
84
+
85
+ previousActive = model;
86
+ tree.up();
87
+
88
+ continue;
89
+ }
90
+ }
91
+
92
+ // ) can mean end of OP token params,
93
+ // or end of subquery:
94
+ if (char === ')') {
95
+ debug('char', char, { token, node: tree.node });
96
+
97
+ // If end of OP token:
98
+ if (!!tree.node.op) {
99
+
100
+ // If token is empty, error:
101
+ if (token === '') {
102
+ const err = UnexpectedCharError(i, char);
103
+ throw err;
104
+ }
105
+
106
+ // Structure of a value depends on OP:
107
+ let fullOp = {};
108
+ switch (tree.node.op) {
109
+ case 'not':
110
+ case 'like':
111
+ fullOp = { [tree.node.activeParam]: { [tree.node.op]: [token] } };
112
+ break;
113
+ default:
114
+ value.push({ [tree.node.activeParam]: [token] });
115
+ fullOp = { [tree.node.op]: value };
116
+ break;
117
+ }
118
+
119
+ tree.node.addWhere(fullOp);
120
+
121
+ // Reset:
122
+ tree.node.resetOP();
123
+ tree.node.activeParam = 'includes';
124
+ token = '';
125
+ value = [];
126
+ continue;
127
+ }
128
+
129
+ // If end of subquery:
130
+ if (!!tree.node.activeParam && tree.node.activeParam !== 'includes') {
131
+ // Set value.
132
+ this.setNodeParam(tree.node, token, value);
133
+ // Reset:
134
+ tree.node.resetActiveParam();
135
+ tree.node.resetOP();
136
+ }
137
+ const numberOfProcessedChars = i - startAt;
138
+ return [ numberOfProcessedChars ];
139
+ }
140
+
141
+ // , can mean n-th value in value array,
142
+ // or horizontal include:
143
+ if (char === ',') {
144
+ debug('char', char, { token, node: tree.node });
145
+
146
+ // If OP token:
147
+ if (!!tree.node.op) {
148
+ value.push({
149
+ [tree.node.activeParam]: [token]
150
+ });
151
+ token = '';
152
+ continue;
153
+ }
154
+
155
+ // If param value:
156
+ if (tree.node.activeParam !== 'includes') {
157
+ value.push(token);
158
+ token = '';
159
+ continue;
160
+ }
161
+
162
+ // Just quit from subquery:
163
+ if (token.length === 0) {
164
+ continue;
165
+ }
166
+
167
+ // Horizontal include:
168
+ if (tree.node.activeParam === 'includes') {
169
+ const model = token;
170
+ tree.use(model) ?? tree.include(model);
171
+
172
+ token = '';
173
+ continue;
174
+ }
175
+
176
+ const err = UnexpectedCharError(i, char);
177
+ throw err;
178
+ }
179
+
180
+ // . can mean vertical include
181
+ // or it can be a part of param for "where":
182
+ if (char === '.') {
183
+ debug('char', char, { token, node: tree.node });
184
+
185
+ // Vertical include:
186
+ if (!!previousActive) {
187
+ tree.use(previousActive);
188
+ tree.node.activeParam = 'includes';
189
+ token = '';
190
+ continue;
191
+ }
192
+
193
+ // If include of new model:
194
+ if (token.length > 0) {
195
+ const model = token;
196
+ tree.use(model) ?? tree.include(model).use(model);
197
+
198
+ // Prepare for more includes:
199
+ tree.node.activeParam = 'includes';
200
+
201
+ token = '';
202
+ continue;
203
+ }
204
+
205
+ const err = UnexpectedCharError(i, char);
206
+ throw err;
207
+ }
208
+
209
+ // + can only mean horizontal include:
210
+ if (char === '+') {
211
+ debug('char', char, { token, node: tree.node });
212
+
213
+ // If include of new model:
214
+ if (token.length > 0) {
215
+ const model = token;
216
+ // Include, but do not use:
217
+ tree.use(model) ?? tree.include(model).use(model);
218
+ tree.up();
219
+
220
+ // Prepare for more includes:
221
+ tree.node.activeParam = 'includes';
222
+
223
+ token = '';
224
+ continue;
225
+ }
226
+
227
+ if (tree.node.hasParent === false) {
228
+ const err = UnexpectedCharError(i, char);
229
+ throw err;
230
+ }
231
+
232
+ tree.up();
233
+ tree.node.activeParam = 'includes';
234
+
235
+ continue;
236
+ }
237
+
238
+ // & can mean the end of key=value pair,
239
+ // or the end of subincludes:
240
+ if (char === '&') {
241
+ debug('char', char, { token, node: tree.node });
242
+
243
+ // If any OP at all:
244
+ if (!!tree.node.op) {
245
+ const err = MissingCharError(i+1, ')');
246
+ throw err;
247
+ }
248
+
249
+ // If end of key=value pair:
250
+ if (!!tree.node.activeParam && tree.node.activeParam !== 'includes') {
251
+ // Set value.
252
+ this.setNodeParam(tree.node, token, value);
253
+ // Reset:
254
+ tree.node.resetActiveParam();
255
+ token = '';
256
+ value = [];
257
+ continue;
258
+ }
259
+ else if (tree.node.activeParam === 'includes') {
260
+ // If include of new model:
261
+ if (token.length > 0) {
262
+ const model = token;
263
+ // Just include, no use.
264
+ tree.include(model);
265
+ }
266
+
267
+ // Then jump to root.
268
+ tree.upToRoot();
269
+
270
+ // Reset:
271
+ token = '';
272
+ value = [];
273
+ continue;
274
+ }
275
+
276
+ // If end of subquery:
277
+ if (tree.node.hasParent === true) {
278
+ tree.up();
279
+ continue;
280
+ }
281
+ // If root:
282
+ else {
283
+ // Reset:
284
+ tree.node.resetActiveParam();
285
+ token = '';
286
+ value = [];
287
+ continue;
288
+ }
289
+
290
+ // Unknown case:
291
+ const err = UnexpectedCharError(i, char);
292
+ throw err;
293
+ }
294
+
295
+ // [ can only mean start of 'in':
296
+ if (char === '[') {
297
+ tree.node.op = 'in';
298
+ continue;
299
+ }
300
+
301
+ // ] can only mean end if 'in':
302
+ if (char === ']') {
303
+ // User missed first '[' :
304
+ if (tree.node.op !== 'in') {
305
+ const err = UnexpectedCharError(i, char);
306
+ throw err;
307
+ }
308
+
309
+ tree.node.addWhere({
310
+ [tree.node.activeParam]: {
311
+ [tree.node.op]: value
312
+ }
313
+ });
314
+ // Reset:
315
+ tree.node.resetOP();
316
+ value = [];
317
+ token = '';
318
+ continue;
319
+ }
320
+
321
+ // = can only mean the end of param name:
322
+ if (char === '=') {
323
+ const param = this.parseParamFromToken(token);
324
+
325
+ if (isSubQuery === true && param === 'includes') {
326
+ const err = new TypeError(`'include' is forbidden inside subquery (position ${ i }). Use: 'model.model' or 'model.model+model'.`);
327
+ throw err;
328
+ }
329
+
330
+ tree.node.activeParam = param;
331
+ token = '';
332
+ continue;
333
+ }
334
+
335
+ // Continue accumulating token.
336
+ token += char;
337
+
338
+ // If last char:
339
+ if (i === queryString.length-1) {
340
+ debug('last char', { token, node: tree.node });
341
+
342
+ // haven't up from 'in':
343
+ if (tree.node.op === 'in') {
344
+ const err = MissingCharError(i+1, ']');
345
+ throw err;
346
+ }
347
+
348
+ // If any OP at all:
349
+ if (!!tree.node.op) {
350
+ const err = MissingCharError(i+1, ')');
351
+ throw err;
352
+ }
353
+
354
+ this.setNodeParam(tree.node, token, value);
355
+
356
+ // If end of subquery:
357
+ if (isSubQuery === true) {
358
+ const numberOfProcessedChars = i+1 - startAt;
359
+ return [ numberOfProcessedChars ];
360
+ }
361
+ }
362
+ }
363
+
364
+ return [ queryString.length - startAt ];
365
+ }
366
+
367
+ parseParamFromToken(token) {
368
+ switch(token) {
369
+ case 'limit':
370
+ case 'l':
371
+ return 'limit';
372
+ case 'skip':
373
+ case 's':
374
+ case 'offset':
375
+ return 'skip';
376
+ case 'order':
377
+ case 'o':
378
+ return 'order';
379
+ case 'order_by':
380
+ case 'o_by':
381
+ return 'orderBy';
382
+ case 'fields':
383
+ case 'f':
384
+ return 'fields';
385
+ case 'includes':
386
+ case 'in':
387
+ return 'includes';
388
+ default:
389
+ return token;
390
+ }
391
+ }
392
+
393
+ setNodeParam(treeNode, token, value) {
394
+ const param = treeNode.activeParam;
395
+
396
+ debug(`set param ${ param }`, { token, value });
397
+
398
+ switch(param) {
399
+ case 'limit':
400
+ treeNode.limit = parseInt(token);
401
+ break;
402
+ case 'skip':
403
+ case 'offset':
404
+ treeNode.skip = parseInt(token);
405
+ break;
406
+ case 'order':
407
+ treeNode.order = token;
408
+ break;
409
+ case 'orderBy':
410
+ treeNode.orderBy = token;
411
+ break;
412
+ case 'fields':
413
+ if (token)
414
+ value.push(token);
415
+ treeNode.fields = value;
416
+ break;
417
+ case 'includes':
418
+ const node = new ModelsTreeNode(token);
419
+ treeNode.include(node);
420
+ break;
421
+ default:
422
+ if (token)
423
+ value.push(token);
424
+ treeNode.addWhere({ [param]: value });
425
+ break;
426
+ }
427
+ }
428
+
429
+ parseOP(opToken) {
430
+ switch(opToken) {
431
+ case '|':
432
+ case 'or':
433
+ return 'or';
434
+ case 'not':
435
+ case '!':
436
+ return 'not';
437
+ default:
438
+ return opToken;
439
+ }
440
+ }
441
+
442
+ [util.inspect.custom](depth, opts) {
443
+ return this.tree.root;
444
+ }
445
+ }
446
+
447
+
448
+ function UnexpectedCharError(index, char) {
449
+ const err = new TypeError(`Unexpected ${ char } at position ${ index }`);
450
+ return err;
451
+ }
452
+
453
+ function MissingCharError(index, char) {
454
+ const err = new TypeError(`Missing ${ char } at position ${ index }`);
455
+ return err;
456
+ }
@@ -3,25 +3,18 @@ const { implementsCRUD } = require('./mixins');
3
3
  // ORM.
4
4
  const { DataTypes } = require('sequelize');
5
5
 
6
- // Utils.
7
- // const {
8
- // pluralize,
9
- // underscore
10
- // } = require('../utils/strings.util');
11
6
 
12
-
13
- module.exports = _defineModel;
7
+ module.exports = defineModel;
14
8
 
15
9
  /*
16
- * params:
17
- * - databaseConnection (Instance of Sequilize)
18
- * - modelName (String)
19
- * - definition (function)
20
- * - options (Object)
10
+ * @param {SequilizeConnection} databaseConnection
11
+ * @param {String} modelName
12
+ * @param {Function} definition
13
+ * @param {Object} options
21
14
  * - ... Sequilize model options
22
15
  * - noCRUD (Bool)
23
16
  */
24
- function _defineModel(
17
+ function defineModel(
25
18
  databaseConnection,
26
19
  modelName='',
27
20
  definition=()=>{},
@@ -13,28 +13,41 @@ module.exports = {
13
13
  implementsCRUD: _implementsCRUD
14
14
  }
15
15
 
16
- function _implementsCRUD(modelDefinition) {
17
- if (!!modelDefinition) {
18
16
 
19
- // Create.
20
- modelDefinition.createWithIncludes = _createWithIncludes.bind(modelDefinition);
17
+ /**
18
+ * Sets all of CRUD methods to Model.
19
+ *
20
+ * @param {Object} controller
21
+ *
22
+ *
23
+ * @api public
24
+ * @alias implementsCRUD
25
+ */
26
+ function _implementsCRUD(model) {
27
+ if (!model) {
28
+ const err = new TypeError(`'model' argument is not provided.`);
29
+ throw err;
30
+ }
21
31
 
22
- // Read:
23
- modelDefinition.findById = _findById.bind(modelDefinition);
24
- modelDefinition.findOneWithIncludes = _findOneWithIncludes.bind(modelDefinition);
32
+ // Create.
33
+ modelDefinition.createWithIncludes = _createWithIncludes.bind(modelDefinition);
25
34
 
26
- // Update:
27
- modelDefinition.updateOne = _updateOne.bind(modelDefinition);
28
- modelDefinition.updateById = _updateById.bind(modelDefinition);
35
+ // Read:
36
+ modelDefinition.findById = _findById.bind(modelDefinition);
37
+ modelDefinition.findOneWithIncludes = _findOneWithIncludes.bind(modelDefinition);
29
38
 
30
- // Delete.
31
- modelDefinition.deleteById = _deleteById.bind(modelDefinition);
39
+ // Update:
40
+ modelDefinition.updateOne = _updateOne.bind(modelDefinition);
41
+ modelDefinition.updateById = _updateById.bind(modelDefinition);
32
42
 
33
- // Associations:
34
- modelDefinition.getIncludesList = _getIncludesList.bind(modelDefinition);
35
- }
43
+ // Delete.
44
+ modelDefinition.deleteById = _deleteById.bind(modelDefinition);
45
+
46
+ // Associations:
47
+ modelDefinition.getIncludesList = _getIncludesList.bind(modelDefinition);
36
48
  }
37
49
 
50
+
38
51
  /* Main mixinis: */
39
52
  async function _createWithIncludes(
40
53
  data={}
@@ -0,0 +1,34 @@
1
+
2
+ module.exports = Params;
3
+
4
+ /**
5
+ * Extracts only values in second argument
6
+ * from first argument.
7
+ * If such values is missing in first atgument,
8
+ * will fallback to the value in second argument.
9
+ *
10
+ * @param {Object} sourceObj
11
+ * @param {Object} defaultValuesList
12
+ *
13
+ * @return {Function|Object} controller
14
+ *
15
+ * @api public
16
+ * @alias withDefaultCRUD
17
+ */
18
+ function Params(
19
+ sourceObj={},
20
+ defaultValuesList={}
21
+ ) {
22
+ const result = {};
23
+
24
+ const keys = Object.keys(defaultValuesList);
25
+ for (const key of keys) {
26
+ // If value is not set, use default one from 'defaultValuesList'.
27
+ result[key] = !(key in sourceObj[key]) ?
28
+ defaultValuesList[key]
29
+ :
30
+ sourceObj[key];
31
+ }
32
+
33
+ return result;
34
+ }
@@ -0,0 +1,139 @@
1
+ // Dictionary of unsafe characters:
2
+ const NOT_ALLOWED = [
3
+ '{',
4
+ '}',
5
+ // `\`,
6
+ '^',
7
+ '~',
8
+ '[',
9
+ ']',
10
+ '`'
11
+ ];
12
+
13
+ const util = require('util');
14
+
15
+ /*
16
+ * NodesterQueryParams is a ready-to-use replacement for URLSearchParams.
17
+ * The only difference is that NodesterQueryParams
18
+ * respects nested "&" during parsing.
19
+ */
20
+ module.exports = class NodesterQueryParams {
21
+ constructor(queryString='') {
22
+ // Type validateion:
23
+ if (typeof queryString !== 'string') {
24
+ const err = new TypeError(`'query' must be a String.`);
25
+ throw err;
26
+ }
27
+
28
+ // You never know if it's encoded or not.
29
+ const decoded = decodeURI(queryString);
30
+
31
+ // Indicates, how deep the char is inside different ().
32
+ let deep = 0;
33
+
34
+ const paramLevels = {};
35
+
36
+ // Current query parameter.
37
+ let param = '';
38
+
39
+ // Current query token.
40
+ let token = '';
41
+
42
+ this._map = new Map();
43
+
44
+ for (let i=0; i < decoded.length; i++) {
45
+ const char = decoded[i];
46
+
47
+ // Validate char:
48
+ if (NOT_ALLOWED.indexOf(char) > -1) {
49
+ const err = new TypeError(`Invalid query token at ${ i }: '${ char }'`);
50
+ throw err;
51
+ }
52
+
53
+ if (char === '(') {
54
+ // Error If there is nothing behind:
55
+ if (param.length === 0) {
56
+ const err = new TypeError(`Invalid query token at ${ i }: '${ char }'`);
57
+ throw err;
58
+ }
59
+
60
+ // If not special token, go deeper:
61
+ if (['and', 'or', 'xor', 'not', '!', '|', 'like'].indexOf(token) === -1) {
62
+ this.append(param, token);
63
+ deep++;
64
+ }
65
+
66
+ // will set ( in token later.
67
+ }
68
+
69
+ if (char === ')') {
70
+ // If sub-level:
71
+ if (deep > 0) {
72
+ deep--
73
+ }
74
+ }
75
+
76
+ // & can mean the end of key=value pair:
77
+ if (char === '&') {
78
+ // If top-level:
79
+ if (deep === 0) {
80
+ this.append(param, token);
81
+ param = '';
82
+ token = '';
83
+ continue;
84
+ }
85
+
86
+ // If sub-level do nothing.
87
+ }
88
+
89
+ // = can mean the end of param name:
90
+ if (char === '=') {
91
+ // If top-level:
92
+ if (deep === 0) {
93
+ param = token;
94
+ token = '';
95
+ }
96
+ }
97
+
98
+ // Continue building token:
99
+ if (char !== '=' || deep > 0 ) {
100
+ token += char;
101
+ }
102
+
103
+ // If last char:
104
+ if (i === decoded.length-1) {
105
+ // Validate:
106
+ if (deep > 0) {
107
+ const err = new TypeError(`Missing ')' at ${ i }`);
108
+ throw err;
109
+ }
110
+
111
+ this.append(param, token);
112
+ }
113
+ }
114
+ }
115
+
116
+ append(...args) {
117
+ return this._map.set(...args);
118
+ }
119
+
120
+ get(...args) {
121
+ return this._map.get(...args);
122
+ }
123
+
124
+ delete(...args) {
125
+ return this._map.delete(...args);
126
+ }
127
+
128
+ entries(...args) {
129
+ return this._map.entries(...args);
130
+ }
131
+
132
+ toString() {
133
+ return this._map.toString();
134
+ }
135
+
136
+ [util.inspect.custom](depth, opts) {
137
+ return this._map;
138
+ }
139
+ }