@voxgig/sdkgen 0.36.0 → 0.37.0

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 (135) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/Main.js +0 -12
  3. package/dist/cmp/Main.js.map +1 -1
  4. package/package.json +1 -1
  5. package/project/.sdk/src/cmp/go/Config_go.ts +6 -2
  6. package/project/.sdk/src/cmp/js/EntityBase_js.ts +34 -0
  7. package/project/.sdk/src/cmp/js/Main_js.ts +10 -0
  8. package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +33 -0
  9. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +123 -0
  10. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +152 -0
  11. package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +25 -0
  12. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +65 -0
  13. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +36 -0
  14. package/project/.sdk/src/cmp/js/TestDirect_js.ts +53 -5
  15. package/project/.sdk/src/cmp/js/TestEntity_js.ts +114 -20
  16. package/project/.sdk/src/cmp/js/fragment/Entity.fragment.js +7 -139
  17. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +149 -0
  18. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +6 -10
  19. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +6 -10
  20. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -11
  21. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -11
  22. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -11
  23. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +2 -0
  24. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +0 -2
  25. package/project/.sdk/src/cmp/lua/Config_lua.ts +6 -2
  26. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +3 -1
  27. package/project/.sdk/src/cmp/php/Config_php.ts +6 -2
  28. package/project/.sdk/src/cmp/php/TestDirect_php.ts +2 -2
  29. package/project/.sdk/src/cmp/php/TestEntity_php.ts +10 -15
  30. package/project/.sdk/src/cmp/py/Config_py.ts +6 -2
  31. package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -1
  32. package/project/.sdk/src/cmp/rb/Config_rb.ts +6 -2
  33. package/project/.sdk/src/cmp/ts/Main_ts.ts +7 -0
  34. package/project/.sdk/tm/go/feature/log_feature.go +1 -1
  35. package/project/.sdk/tm/go/test/runner_test.go +16 -2
  36. package/project/.sdk/tm/js/src/Context.js +142 -0
  37. package/project/.sdk/tm/js/src/Control.js +16 -0
  38. package/project/.sdk/tm/js/src/Operation.js +19 -0
  39. package/project/.sdk/tm/js/src/Point.js +24 -0
  40. package/project/.sdk/tm/js/src/README.md +1 -0
  41. package/project/.sdk/tm/js/src/Response.js +19 -0
  42. package/project/.sdk/tm/js/src/Result.js +21 -0
  43. package/project/.sdk/tm/js/src/Spec.js +26 -0
  44. package/project/.sdk/tm/js/src/feature/README.md +1 -0
  45. package/project/.sdk/tm/js/src/feature/base/BaseFeature.js +45 -0
  46. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +46 -47
  47. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +207 -0
  48. package/project/.sdk/tm/js/src/types.js +22 -0
  49. package/project/.sdk/tm/js/src/utility/CleanUtility.js +31 -0
  50. package/project/.sdk/tm/js/src/utility/DoneUtility.js +11 -4
  51. package/project/.sdk/tm/js/src/utility/FeatureAddUtility.js +42 -0
  52. package/project/.sdk/tm/js/src/utility/FeatureHookUtility.js +25 -0
  53. package/project/.sdk/tm/js/src/utility/FeatureInitUtility.js +11 -0
  54. package/project/.sdk/tm/js/src/utility/FetcherUtility.js +28 -0
  55. package/project/.sdk/tm/js/src/utility/MakeContextUtility.js +11 -0
  56. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +55 -0
  57. package/project/.sdk/tm/js/src/utility/MakeFetchDefUtility.js +44 -0
  58. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +93 -0
  59. package/project/.sdk/tm/js/src/utility/MakePointUtility.js +77 -0
  60. package/project/.sdk/tm/js/src/utility/MakeRequestUtility.js +63 -0
  61. package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +55 -0
  62. package/project/.sdk/tm/js/src/utility/MakeResultUtility.js +54 -0
  63. package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +58 -0
  64. package/project/.sdk/tm/js/src/utility/MakeUrlUtility.js +40 -0
  65. package/project/.sdk/tm/js/src/utility/ParamUtility.js +61 -0
  66. package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +41 -0
  67. package/project/.sdk/tm/js/src/utility/PrepareBodyUtility.js +25 -0
  68. package/project/.sdk/tm/js/src/utility/PrepareHeadersUtility.js +18 -0
  69. package/project/.sdk/tm/js/src/utility/{MethodUtility.js → PrepareMethodUtility.js} +7 -7
  70. package/project/.sdk/tm/js/src/utility/PrepareParamsUtility.js +25 -0
  71. package/project/.sdk/tm/js/src/utility/PreparePathUtility.js +13 -0
  72. package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +26 -0
  73. package/project/.sdk/tm/js/src/utility/README.md +1 -0
  74. package/project/.sdk/tm/js/src/utility/ResultBasicUtility.js +34 -0
  75. package/project/.sdk/tm/js/src/utility/ResultBodyUtility.js +18 -0
  76. package/project/.sdk/tm/js/src/utility/ResultHeadersUtility.js +22 -0
  77. package/project/.sdk/tm/js/src/utility/StructUtility.js +2219 -1078
  78. package/project/.sdk/tm/js/src/utility/TransformRequestUtility.js +28 -0
  79. package/project/.sdk/tm/js/src/utility/TransformResponseUtility.js +31 -0
  80. package/project/.sdk/tm/js/src/utility/Utility.js +61 -61
  81. package/project/.sdk/tm/js/test/README.md +1 -0
  82. package/project/.sdk/tm/js/test/exists.test.js +16 -0
  83. package/project/.sdk/tm/js/test/runner.js +323 -107
  84. package/project/.sdk/tm/js/test/utility/Custom.test.js +41 -63
  85. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +390 -116
  86. package/project/.sdk/tm/js/test/utility/StructUtility.test.js +728 -175
  87. package/project/.sdk/tm/js/test/utility/index.js +9 -0
  88. package/project/.sdk/tm/js/test/utility.js +72 -0
  89. package/project/.sdk/tm/lua/test/primary_utility_test.lua +1213 -0
  90. package/project/.sdk/tm/lua/test/runner.lua +2 -2
  91. package/project/.sdk/tm/lua/test/struct_runner.lua +602 -0
  92. package/project/.sdk/tm/lua/test/struct_utility_test.lua +959 -0
  93. package/project/.sdk/tm/lua/utility/struct/struct.lua +10 -0
  94. package/project/.sdk/tm/php/feature/TestFeature.php +59 -96
  95. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +1309 -0
  96. package/project/.sdk/tm/php/test/Runner.php +24 -1
  97. package/project/.sdk/tm/php/test/StructRunner.php +275 -0
  98. package/project/.sdk/tm/php/test/StructUtilityTest.php +1336 -0
  99. package/project/.sdk/tm/php/utility/Fetcher.php +6 -2
  100. package/project/.sdk/tm/php/utility/MakeOptions.php +5 -1
  101. package/project/.sdk/tm/php/utility/MakeResult.php +3 -0
  102. package/project/.sdk/tm/php/utility/Param.php +9 -7
  103. package/project/.sdk/tm/php/utility/struct/Struct.php +312 -208
  104. package/project/.sdk/tm/py/test/runner.py +13 -0
  105. package/project/.sdk/tm/py/test/struct_runner.py +411 -0
  106. package/project/.sdk/tm/py/test/test_primary_utility.py +1101 -0
  107. package/project/.sdk/tm/py/test/test_struct_utility.py +751 -0
  108. package/project/.sdk/tm/rb/test/primary_utility_test.rb +1083 -0
  109. package/project/.sdk/tm/rb/test/runner.rb +5 -0
  110. package/project/.sdk/tm/rb/test/struct_runner.rb +309 -0
  111. package/project/.sdk/tm/rb/test/struct_utility_test.rb +670 -0
  112. package/src/cmp/Main.ts +1 -16
  113. package/project/.sdk/src/cmp/js/Quick_js.ts +0 -78
  114. package/project/.sdk/src/cmp/js/TestAcceptEntity_js.ts +0 -13
  115. package/project/.sdk/src/cmp/js/TestAccept_js.ts +0 -18
  116. package/project/.sdk/tm/js/src/utility/AuthUtility.js +0 -21
  117. package/project/.sdk/tm/js/src/utility/BodyUtility.js +0 -29
  118. package/project/.sdk/tm/js/src/utility/ErrorUtility.js +0 -33
  119. package/project/.sdk/tm/js/src/utility/FindparamUtility.js +0 -31
  120. package/project/.sdk/tm/js/src/utility/FullurlUtility.js +0 -39
  121. package/project/.sdk/tm/js/src/utility/HeadersUtility.js +0 -13
  122. package/project/.sdk/tm/js/src/utility/JoinurlUtility.js +0 -14
  123. package/project/.sdk/tm/js/src/utility/OperatorUtility.js +0 -44
  124. package/project/.sdk/tm/js/src/utility/OptionsUtility.js +0 -54
  125. package/project/.sdk/tm/js/src/utility/ParamsUtility.js +0 -21
  126. package/project/.sdk/tm/js/src/utility/QueryUtility.js +0 -21
  127. package/project/.sdk/tm/js/src/utility/ReqformUtility.js +0 -32
  128. package/project/.sdk/tm/js/src/utility/RequestUtility.js +0 -48
  129. package/project/.sdk/tm/js/src/utility/ResbasicUtility.js +0 -27
  130. package/project/.sdk/tm/js/src/utility/ResbodyUtility.js +0 -15
  131. package/project/.sdk/tm/js/src/utility/ResformUtility.js +0 -34
  132. package/project/.sdk/tm/js/src/utility/ResheadersUtility.js +0 -19
  133. package/project/.sdk/tm/js/src/utility/ResponseUtility.js +0 -37
  134. package/project/.sdk/tm/js/src/utility/ResultUtility.js +0 -28
  135. package/project/.sdk/tm/js/src/utility/SpecUtility.js +0 -35
@@ -1,305 +1,716 @@
1
+ // VERSION: @voxgig/struct 0.0.10
2
+ // RUN: npm test
3
+ // RUN-SOME: npm run test-some --pattern=getpath
1
4
 
2
- const { readFileSync } = require('node:fs')
3
- const { join } = require('node:path')
4
- const { test, describe } = require('node:test')
5
- const { equal, deepEqual, fail } = require('node:assert')
5
+ const { test, describe, before } = require('node:test')
6
+ const assert = require('node:assert')
7
+
8
+ const {
9
+ makeRunner,
10
+ nullModifier,
11
+ NULLMARK,
12
+ } = require('../runner')
6
13
 
7
14
 
8
15
  const {
9
- clone,
10
- escre,
11
- escurl,
12
- getpath,
13
- getprop,
14
- inject,
15
- isempty,
16
- iskey,
17
- islist,
18
- ismap,
19
- isnode,
20
- items,
21
- haskey,
22
- keysof,
23
- merge,
24
- setprop,
25
- stringify,
26
- transform,
27
- walk,
28
- validate,
29
- joinurl,
30
- } = require('../../src/utility/StructUtility')
31
-
32
-
33
- const { runner } = require('../runner')
34
-
35
-
36
- function walkpath(_key, val, _parent, path) {
37
- return 'string' === typeof val ? val + '~' + path.join('.') : val
38
- }
39
-
40
-
41
- function nullModifier(
42
- key,
43
- val,
44
- parent
45
- ) {
46
- if ("__NULL__" === val) {
47
- setprop(parent, key, null)
48
- }
49
- else if ('string' === typeof val) {
50
- setprop(parent, key, val.replaceAll('__NULL__', 'null'))
51
- }
52
- }
16
+ SDK,
17
+ TEST_JSON_FILE
18
+ } = require('./index')
53
19
 
54
20
 
21
+ const { equal, deepEqual } = assert
22
+
23
+
24
+ // NOTE: tests are (mostly) in order of increasing dependence.
55
25
  describe('struct', async () => {
56
26
 
57
- const { spec, runset, subject } = await runner('struct')
27
+ let spec
28
+ let runset
29
+ let runsetflags
30
+ let client
31
+ let struct
58
32
 
59
-
60
- // minor tests
61
- // ===========
33
+ before(async () => {
34
+ const runner = await makeRunner(TEST_JSON_FILE, await SDK.test())
35
+ const runner_struct = await runner('struct')
62
36
 
63
- test('minor-exists', () => {
64
- equal('function', typeof clone)
65
- equal('function', typeof escre)
66
- equal('function', typeof escurl)
67
- equal('function', typeof getprop)
68
- equal('function', typeof isempty)
69
- equal('function', typeof iskey)
70
- equal('function', typeof islist)
71
- equal('function', typeof ismap)
72
- equal('function', typeof isnode)
73
- equal('function', typeof items)
74
- equal('function', typeof setprop)
75
- equal('function', typeof stringify)
76
- equal('function', typeof haskey)
77
- equal('function', typeof keysof)
78
- equal('function', typeof joinurl)
37
+ spec = runner_struct.spec
38
+
39
+ runset = runner_struct.runset
40
+ runsetflags = runner_struct.runsetflags
41
+ client = runner_struct.client
42
+
43
+ struct = client.utility().struct
79
44
  })
80
45
 
81
- test('minor-clone', async () => {
82
- await runset(spec.minor.clone, clone)
46
+
47
+
48
+ test('exists', () => {
49
+ const s = struct
50
+
51
+ equal('function', typeof s.clone)
52
+ equal('function', typeof s.delprop)
53
+ equal('function', typeof s.escre)
54
+ equal('function', typeof s.escurl)
55
+ equal('function', typeof s.filter)
56
+
57
+ equal('function', typeof s.flatten)
58
+ equal('function', typeof s.getelem)
59
+ equal('function', typeof s.getprop)
60
+
61
+ equal('function', typeof s.getpath)
62
+ equal('function', typeof s.haskey)
63
+ equal('function', typeof s.inject)
64
+ equal('function', typeof s.isempty)
65
+ equal('function', typeof s.isfunc)
66
+
67
+ equal('function', typeof s.iskey)
68
+ equal('function', typeof s.islist)
69
+ equal('function', typeof s.ismap)
70
+ equal('function', typeof s.isnode)
71
+ equal('function', typeof s.items)
72
+
73
+ equal('function', typeof s.join)
74
+ equal('function', typeof s.jsonify)
75
+ equal('function', typeof s.keysof)
76
+ equal('function', typeof s.merge)
77
+ equal('function', typeof s.pad)
78
+ equal('function', typeof s.pathify)
79
+
80
+ equal('function', typeof s.select)
81
+ equal('function', typeof s.setpath)
82
+ equal('function', typeof s.size)
83
+ equal('function', typeof s.slice)
84
+ equal('function', typeof s.setprop)
85
+
86
+ equal('function', typeof s.strkey)
87
+ equal('function', typeof s.stringify)
88
+ equal('function', typeof s.transform)
89
+ equal('function', typeof s.typify)
90
+ equal('function', typeof s.typename)
91
+
92
+ equal('function', typeof s.validate)
93
+ equal('function', typeof s.walk)
83
94
  })
84
95
 
96
+
97
+ // minor tests
98
+ // ===========
99
+
85
100
  test('minor-isnode', async () => {
86
- await runset(spec.minor.isnode, isnode)
101
+ await runset(spec.minor.isnode, struct.isnode)
87
102
  })
88
103
 
104
+
89
105
  test('minor-ismap', async () => {
90
- await runset(spec.minor.ismap, ismap)
106
+ await runset(spec.minor.ismap, struct.ismap)
91
107
  })
92
108
 
109
+
93
110
  test('minor-islist', async () => {
94
- await runset(spec.minor.islist, islist)
111
+ await runset(spec.minor.islist, struct.islist)
95
112
  })
96
113
 
114
+
97
115
  test('minor-iskey', async () => {
98
- await runset(spec.minor.iskey, iskey)
116
+ await runsetflags(spec.minor.iskey, { null: false }, struct.iskey)
99
117
  })
100
118
 
119
+
120
+ test('minor-strkey', async () => {
121
+ await runsetflags(spec.minor.strkey, { null: false }, struct.strkey)
122
+ })
123
+
124
+
101
125
  test('minor-isempty', async () => {
102
- await runset(spec.minor.isempty, isempty)
126
+ await runsetflags(spec.minor.isempty, { null: false }, struct.isempty)
103
127
  })
104
128
 
129
+
130
+ test('minor-isfunc', async () => {
131
+ const { isfunc } = struct
132
+ await runset(spec.minor.isfunc, isfunc)
133
+ function f0() { return null }
134
+ equal(isfunc(f0), true)
135
+ equal(isfunc(() => null), true)
136
+ })
137
+
138
+
139
+ test('minor-clone', async () => {
140
+ await runsetflags(spec.minor.clone, { null: false }, struct.clone)
141
+ })
142
+
143
+
144
+ test('minor-edge-clone', async () => {
145
+ const { clone } = struct
146
+
147
+ const f0 = () => null
148
+ deepEqual({ a: f0 }, clone({ a: f0 }))
149
+
150
+ const x = { y: 1 }
151
+ let xc = clone(x)
152
+ deepEqual(x, xc)
153
+ assert(x !== xc)
154
+
155
+ class A { x = 1 }
156
+ const a = new A()
157
+ let ac = clone(a)
158
+ deepEqual(a, ac)
159
+ assert(a === ac)
160
+ equal(a.constructor.name, ac.constructor.name)
161
+ })
162
+
163
+
164
+ test('minor-filter', async () => {
165
+ const checkmap = {
166
+ gt3: (n) => n[1] > 3,
167
+ lt3: (n) => n[1] < 3,
168
+ }
169
+ await runset(spec.minor.filter, (vin) => struct.filter(vin.val, checkmap[vin.check]))
170
+ })
171
+
172
+
173
+ test('minor-flatten', async () => {
174
+ await runset(spec.minor.flatten, (vin) => struct.flatten(vin.val, vin.depth))
175
+ })
176
+
177
+
105
178
  test('minor-escre', async () => {
106
- await runset(spec.minor.escre, escre)
179
+ await runset(spec.minor.escre, struct.escre)
107
180
  })
108
181
 
182
+
109
183
  test('minor-escurl', async () => {
110
- await runset(spec.minor.escurl, escurl)
184
+ await runset(spec.minor.escurl, struct.escurl)
111
185
  })
112
186
 
187
+
113
188
  test('minor-stringify', async () => {
114
189
  await runset(spec.minor.stringify, (vin) =>
115
- null == vin.max ? stringify(vin.val) : stringify(vin.val, vin.max))
190
+ struct.stringify((NULLMARK === vin.val ? "null" : vin.val), vin.max))
191
+ })
192
+
193
+
194
+ test('minor-edge-stringify', async () => {
195
+ const { stringify } = struct
196
+ const a = {}
197
+ a.a = a
198
+ equal(stringify(a), '__STRINGIFY_FAILED__')
199
+
200
+ equal(stringify({ a: [9] }, -1, true),
201
+ '\x1B[38;5;81m\x1B[38;5;118m{\x1B[38;5;118ma\x1B[38;5;118m:' +
202
+ '\x1B[38;5;213m[\x1B[38;5;213m9\x1B[38;5;213m]\x1B[38;5;118m}\x1B[0m')
203
+ })
204
+
205
+
206
+ test('minor-jsonify', async () => {
207
+ await runsetflags(spec.minor.jsonify, { null: false },
208
+ (vin) => struct.jsonify(vin.val, vin.flags))
209
+ })
210
+
211
+
212
+ test('minor-edge-jsonify', async () => {
213
+ const { jsonify } = struct
214
+ equal(jsonify(() => 1), 'null')
215
+ })
216
+
217
+
218
+ test('minor-pathify', async () => {
219
+ await runsetflags(
220
+ spec.minor.pathify, { null: true },
221
+ (vin) => {
222
+ let path = NULLMARK == vin.path ? undefined : vin.path
223
+ let pathstr = struct.pathify(path, vin.from).replace('__NULL__.', '')
224
+ pathstr = NULLMARK === vin.path ? pathstr.replace('>', ':null>') : pathstr
225
+ return pathstr
226
+ })
116
227
  })
117
228
 
229
+
118
230
  test('minor-items', async () => {
119
- await runset(spec.minor.items, items)
231
+ await runset(spec.minor.items, struct.items)
232
+ })
233
+
234
+
235
+ test('minor-edge-items', async () => {
236
+ const { items } = struct
237
+ const a0 = [11, 22, 33]
238
+ a0.x = 1
239
+ deepEqual(items(a0), [['0', 11], ['1', 22], ['2', 33]])
120
240
  })
121
241
 
242
+
243
+ test('minor-getelem', async () => {
244
+ const { getelem } = struct
245
+ await runsetflags(spec.minor.getelem, { null: false }, (vin) =>
246
+ null == vin.alt ? getelem(vin.val, vin.key) : getelem(vin.val, vin.key, vin.alt))
247
+ })
248
+
249
+
250
+ test('minor-edge-getelem', async () => {
251
+ const { getelem } = struct
252
+ equal(getelem([], 1, () => 2), 2)
253
+ })
254
+
255
+
122
256
  test('minor-getprop', async () => {
123
- await runset(spec.minor.getprop, (vin) =>
124
- null == vin.alt ? getprop(vin.val, vin.key) : getprop(vin.val, vin.key, vin.alt))
257
+ const { getprop } = struct
258
+ await runsetflags(spec.minor.getprop, { null: false }, (vin) =>
259
+ undefined === vin.alt ? getprop(vin.val, vin.key) : getprop(vin.val, vin.key, vin.alt))
260
+ })
261
+
262
+
263
+ test('minor-edge-getprop', async () => {
264
+ const { getprop } = struct
265
+
266
+ let strarr = ['a', 'b', 'c', 'd', 'e']
267
+ deepEqual(getprop(strarr, 2), 'c')
268
+ deepEqual(getprop(strarr, '2'), 'c')
269
+
270
+ let intarr = [2, 3, 5, 7, 11]
271
+ deepEqual(getprop(intarr, 2), 5)
272
+ deepEqual(getprop(intarr, '2'), 5)
125
273
  })
126
274
 
275
+
127
276
  test('minor-setprop', async () => {
128
277
  await runset(spec.minor.setprop, (vin) =>
129
- setprop(vin.parent, vin.key, vin.val))
278
+ struct.setprop(vin.parent, vin.key, vin.val))
279
+ })
280
+
281
+
282
+ test('minor-edge-setprop', async () => {
283
+ const { setprop } = struct
284
+
285
+ let strarr0 = ['a', 'b', 'c', 'd', 'e']
286
+ let strarr1 = ['a', 'b', 'c', 'd', 'e']
287
+ deepEqual(setprop(strarr0, 2, 'C'), ['a', 'b', 'C', 'd', 'e'])
288
+ deepEqual(setprop(strarr1, '2', 'CC'), ['a', 'b', 'CC', 'd', 'e'])
289
+
290
+ let intarr0 = [2, 3, 5, 7, 11]
291
+ let intarr1 = [2, 3, 5, 7, 11]
292
+ deepEqual(setprop(intarr0, 2, 55), [2, 3, 55, 7, 11])
293
+ deepEqual(setprop(intarr1, '2', 555), [2, 3, 555, 7, 11])
294
+ })
295
+
296
+
297
+ test('minor-delprop', async () => {
298
+ await runset(spec.minor.delprop, (vin) =>
299
+ struct.delprop(vin.parent, vin.key))
300
+ })
301
+
302
+
303
+ test('minor-edge-delprop', async () => {
304
+ const { delprop } = struct
305
+
306
+ let strarr0 = ['a', 'b', 'c', 'd', 'e']
307
+ let strarr1 = ['a', 'b', 'c', 'd', 'e']
308
+ deepEqual(delprop(strarr0, 2), ['a', 'b', 'd', 'e'])
309
+ deepEqual(delprop(strarr1, '2'), ['a', 'b', 'd', 'e'])
310
+
311
+ let intarr0 = [2, 3, 5, 7, 11]
312
+ let intarr1 = [2, 3, 5, 7, 11]
313
+ deepEqual(delprop(intarr0, 2), [2, 3, 7, 11])
314
+ deepEqual(delprop(intarr1, '2'), [2, 3, 7, 11])
130
315
  })
131
316
 
317
+
132
318
  test('minor-haskey', async () => {
133
- await runset(spec.minor.haskey, haskey)
319
+ await runsetflags(spec.minor.haskey, { null: false }, (vin) =>
320
+ struct.haskey(vin.src, vin.key))
134
321
  })
135
322
 
323
+
136
324
  test('minor-keysof', async () => {
137
- await runset(spec.minor.keysof, keysof)
325
+ await runset(spec.minor.keysof, struct.keysof)
326
+ })
327
+
328
+ test('minor-edge-keysof', async () => {
329
+ const { keysof } = struct
330
+ const a0 = [11, 22, 33]
331
+ a0.x = 1
332
+ deepEqual(keysof(a0), [0, 1, 2])
333
+ })
334
+
335
+
336
+
337
+ test('minor-join', async () => {
338
+ await runsetflags(spec.minor.join, { null: false },
339
+ (vin) => struct.join(vin.val, vin.sep, vin.url))
340
+ })
341
+
342
+
343
+ test('minor-typename', async () => {
344
+ await runset(spec.minor.typename, struct.typename)
345
+ })
346
+
347
+
348
+ test('minor-typify', async () => {
349
+ await runsetflags(spec.minor.typify, { null: false }, struct.typify)
138
350
  })
139
351
 
140
- test('minor-joinurl', async () => {
141
- await runset(spec.minor.joinurl, joinurl)
352
+
353
+ test('minor-edge-typify', async () => {
354
+ const {
355
+ typify, T_noval, T_scalar, T_function, T_symbol, T_any, T_node, T_instance, T_null
356
+ } = struct
357
+ class X { }
358
+ const x = new X()
359
+ equal(typify(), T_noval)
360
+ equal(typify(undefined), T_noval)
361
+ equal(typify(NaN), T_noval)
362
+ equal(typify(null), T_scalar | T_null)
363
+ equal(typify(() => null), T_scalar | T_function)
364
+ equal(typify(Symbol('S')), T_scalar | T_symbol)
365
+ equal(typify(BigInt(1)), T_any)
366
+ equal(typify(x), T_node | T_instance)
367
+ })
368
+
369
+
370
+ test('minor-size', async () => {
371
+ await runsetflags(spec.minor.size, { null: false }, struct.size)
372
+ })
373
+
374
+
375
+ test('minor-slice', async () => {
376
+ await runsetflags(spec.minor.slice, { null: false },
377
+ (vin) => struct.slice(vin.val, vin.start, vin.end))
378
+ })
379
+
380
+
381
+ test('minor-pad', async () => {
382
+ await runsetflags(spec.minor.pad, { null: false },
383
+ (vin) => struct.pad(vin.val, vin.pad, vin.char))
384
+ })
385
+
386
+
387
+ test('minor-setpath', async () => {
388
+ await runsetflags(spec.minor.setpath, { null: false },
389
+ (vin) => struct.setpath(vin.store, vin.path, vin.val))
390
+ })
391
+
392
+
393
+ test('minor-edge-setpath', async () => {
394
+ const { setpath, DELETE } = struct
395
+ const x = { y: { z: 1, q: 2 } }
396
+ deepEqual(setpath(x, 'y.q', DELETE), { z: 1 })
397
+ deepEqual(x, { y: { z: 1 } })
142
398
  })
143
399
 
144
400
 
401
+
145
402
  // walk tests
146
403
  // ==========
147
404
 
148
- test('walk-exists', async () => {
149
- equal('function', typeof merge)
405
+ test('walk-log', async () => {
406
+ const { clone, stringify, pathify, walk } = struct
407
+
408
+ const test = clone(spec.walk.log)
409
+
410
+ let log = []
411
+
412
+ function walklog(key, val, parent, path) {
413
+ log.push('k=' + stringify(key) +
414
+ ', v=' + stringify(val) +
415
+ ', p=' + stringify(parent) +
416
+ ', t=' + pathify(path))
417
+ return val
418
+ }
419
+
420
+ walk(test.in, undefined, walklog)
421
+ deepEqual(log, test.out.after)
422
+
423
+ log = []
424
+ walk(test.in, walklog)
425
+ deepEqual(log, test.out.before)
426
+
427
+ log = []
428
+ walk(test.in, walklog, walklog)
429
+ deepEqual(log, test.out.both)
150
430
  })
151
431
 
432
+
152
433
  test('walk-basic', async () => {
153
- await runset(spec.walk.basic, (vin) => walk(vin, walkpath))
434
+ function walkpath(_key, val, _parent, path) {
435
+ return 'string' === typeof val ? val + '~' + path.join('.') : val
436
+ }
437
+
438
+ await runset(spec.walk.basic, (vin) => struct.walk(vin, walkpath))
154
439
  })
155
440
 
156
441
 
157
- // merge tests
158
- // ===========
442
+ test('walk-depth', async () => {
443
+
444
+ await runsetflags(spec.walk.depth, { null: false },
445
+ (vin) => {
446
+ let top = undefined
447
+ let cur = undefined
448
+ function copy(key, val, _parent, _path) {
449
+ if (undefined === key || struct.isnode(val)) {
450
+ let child = struct.islist(val) ? [] : {}
451
+ if (undefined === key) {
452
+ top = cur = child
453
+ }
454
+ else {
455
+ cur = cur[key] = child
456
+ }
457
+ }
458
+ else {
459
+ cur[key] = val
460
+ }
461
+ return val
462
+ }
463
+ struct.walk(vin.src, copy, undefined, vin.maxdepth)
464
+ return top
465
+ })
466
+ })
467
+
468
+
469
+ test('walk-copy', async () => {
470
+ const { walk, isnode, ismap, islist, size, setprop } = struct
471
+
472
+ let cur
473
+ function walkcopy(key, val, _parent, path) {
474
+ if (undefined === key) {
475
+ cur = []
476
+ cur[0] = ismap(val) ? {} : islist(val) ? [] : val
477
+ return val
478
+ }
479
+
480
+ let v = val
481
+ let i = size(path)
482
+
483
+ if (isnode(v)) {
484
+ v = cur[i] = ismap(v) ? {} : []
485
+ }
486
+
487
+ setprop(cur[i - 1], key, v)
488
+
489
+ return val
490
+ }
159
491
 
160
- test('merge-exists', async () => {
161
- equal('function', typeof merge)
492
+ await runset(spec.walk.copy, (vin) => (walk(vin, walkcopy), cur[0]))
162
493
  })
163
494
 
495
+
496
+
497
+ // merge tests
498
+ // ===========
499
+
164
500
  test('merge-basic', async () => {
501
+ const { clone, merge } = struct
165
502
  const test = clone(spec.merge.basic)
166
503
  deepEqual(merge(test.in), test.out)
167
504
  })
168
505
 
506
+
169
507
  test('merge-cases', async () => {
170
- await runset(spec.merge.cases, merge)
508
+ await runset(spec.merge.cases, struct.merge)
171
509
  })
172
510
 
511
+
173
512
  test('merge-array', async () => {
174
- await runset(spec.merge.array, merge)
513
+ await runset(spec.merge.array, struct.merge)
514
+ })
515
+
516
+
517
+ test('merge-integrity', async () => {
518
+ await runset(spec.merge.integrity, struct.merge)
519
+ })
520
+
521
+
522
+ test('merge-depth', async () => {
523
+ await runset(spec.merge.depth, (vin) => struct.merge(vin.val, vin.depth))
175
524
  })
176
525
 
526
+
177
527
  test('merge-special', async () => {
178
- const f0 = ()=>null
528
+ const { merge } = struct
529
+ const f0 = () => null
179
530
  deepEqual(merge([f0]), f0)
180
- deepEqual(merge([null,f0]), f0)
181
- deepEqual(merge([{a:f0}]), {a:f0})
182
- deepEqual(merge([{a:{b:f0}}]), {a:{b:f0}})
531
+ deepEqual(merge([null, f0]), f0)
532
+ deepEqual(merge([{ a: f0 }]), { a: f0 })
533
+ deepEqual(merge([[f0]]), [f0])
534
+ deepEqual(merge([{ a: { b: f0 } }]), { a: { b: f0 } })
535
+
536
+ // JavaScript only
537
+ deepEqual(merge([{ a: global.fetch }]), { a: global.fetch })
538
+ deepEqual(merge([[global.fetch]]), [global.fetch])
539
+ deepEqual(merge([{ a: { b: global.fetch } }]), { a: { b: global.fetch } })
540
+
541
+ class Bar { x = 1 }
542
+ const b0 = new Bar()
543
+ let out
544
+
545
+ equal(merge([{ x: 10 }, b0]), b0)
546
+ equal(b0.x, 1)
547
+ equal(b0 instanceof Bar, true)
548
+
549
+ deepEqual(merge([{ a: b0 }, { a: { x: 11 } }]), { a: { x: 11 } })
550
+ equal(b0.x, 1)
551
+ equal(b0 instanceof Bar, true)
552
+
553
+ deepEqual(merge([b0, { x: 20 }]), { x: 20 })
554
+ equal(b0.x, 1)
555
+ equal(b0 instanceof Bar, true)
556
+
557
+ out = merge([{ a: { x: 21 } }, { a: b0 }])
558
+ deepEqual(out, { a: b0 })
559
+ equal(b0, out.a)
560
+ equal(b0.x, 1)
561
+ equal(b0 instanceof Bar, true)
183
562
 
184
- deepEqual(merge([{a:global.fetch}]), {a:global.fetch})
185
- deepEqual(merge([{a:{b:global.fetch}}]), {a:{b:global.fetch}})
563
+ out = merge([{}, { b: b0 }])
564
+ deepEqual(out, { b: b0 })
565
+ equal(b0, out.b)
566
+ equal(b0.x, 1)
567
+ equal(b0 instanceof Bar, true)
186
568
  })
187
-
569
+
188
570
 
189
571
  // getpath tests
190
572
  // =============
191
573
 
192
- test('getpath-exists', async () => {
193
- equal('function', typeof getpath)
574
+ test('getpath-basic', async () => {
575
+ await runset(spec.getpath.basic, (vin) => struct.getpath(vin.store, vin.path))
194
576
  })
195
577
 
196
- test('getpath-basic', async () => {
197
- await runset(spec.getpath.basic, (vin) => getpath(vin.path, vin.store))
578
+
579
+ test('getpath-relative', async () => {
580
+ await runset(spec.getpath.relative, (vin) =>
581
+ struct.getpath(vin.store, vin.path,
582
+ { dparent: vin.dparent, dpath: vin.dpath?.split('.') }))
198
583
  })
199
584
 
200
- test('getpath-current', async () => {
201
- await runset(spec.getpath.current, (vin) =>
202
- getpath(vin.path, vin.store, vin.current))
585
+
586
+ test('getpath-special', async () => {
587
+ await runset(spec.getpath.special, (vin) =>
588
+ struct.getpath(vin.store, vin.path, vin.inj))
203
589
  })
204
590
 
205
- test('getpath-state', async () => {
206
- const state = {
207
- handler: (state, val, _current, _store) => {
208
- let out = state.step + ':' + val
209
- state.step++
210
- return out
211
- },
212
- step: 0,
213
- mode: 'val',
214
- full: false,
215
- keyI: 0,
216
- keys: ['$TOP'],
217
- key: '$TOP',
218
- val: '',
219
- parent: {},
220
- path: ['$TOP'],
221
- nodes: [{}],
222
- base: '$TOP'
223
- }
224
- await runset(spec.getpath.state, (vin) =>
225
- getpath(vin.path, vin.store, vin.current, state))
591
+
592
+ test('getpath-handler', async () => {
593
+ await runset(spec.getpath.handler, (vin) =>
594
+ struct.getpath(
595
+ {
596
+ $TOP: vin.store,
597
+ $FOO: () => 'foo',
598
+ },
599
+ vin.path,
600
+ {
601
+ handler: (_inj, val, _cur, _ref) => {
602
+ return val()
603
+ }
604
+ }
605
+ ))
226
606
  })
227
607
 
228
608
 
229
609
  // inject tests
230
610
  // ============
231
611
 
232
- test('inject-exists', async () => {
233
- equal('function', typeof inject)
234
- })
235
-
236
612
  test('inject-basic', async () => {
613
+ const { clone, inject } = struct
237
614
  const test = clone(spec.inject.basic)
238
615
  deepEqual(inject(test.in.val, test.in.store), test.out)
239
616
  })
240
617
 
618
+
241
619
  test('inject-string', async () => {
242
620
  await runset(spec.inject.string, (vin) =>
243
- inject(vin.val, vin.store, nullModifier, vin.current))
621
+ struct.inject(vin.val, vin.store, { modify: nullModifier }))
244
622
  })
245
623
 
624
+
246
625
  test('inject-deep', async () => {
247
- await runset(spec.inject.deep, (vin) => inject(vin.val, vin.store))
626
+ await runset(spec.inject.deep, (vin) => struct.inject(vin.val, vin.store))
248
627
  })
249
628
 
250
629
 
251
630
  // transform tests
252
631
  // ===============
253
632
 
254
- test('transform-exists', async () => {
255
- equal('function', typeof transform)
256
- })
257
-
258
633
  test('transform-basic', async () => {
634
+ const { clone, transform } = struct
259
635
  const test = clone(spec.transform.basic)
260
- deepEqual(transform(test.in.data, test.in.spec, test.in.store), test.out)
636
+ deepEqual(transform(test.in.data, test.in.spec), test.out)
261
637
  })
262
638
 
639
+
263
640
  test('transform-paths', async () => {
264
641
  await runset(spec.transform.paths, (vin) =>
265
- transform(vin.data, vin.spec, vin.store))
642
+ struct.transform(vin.data, vin.spec))
266
643
  })
267
644
 
645
+
268
646
  test('transform-cmds', async () => {
269
647
  await runset(spec.transform.cmds, (vin) =>
270
- transform(vin.data, vin.spec, vin.store))
648
+ struct.transform(vin.data, vin.spec))
271
649
  })
272
650
 
651
+
273
652
  test('transform-each', async () => {
274
653
  await runset(spec.transform.each, (vin) =>
275
- transform(vin.data, vin.spec, vin.store))
654
+ struct.transform(vin.data, vin.spec))
276
655
  })
277
656
 
657
+
278
658
  test('transform-pack', async () => {
279
659
  await runset(spec.transform.pack, (vin) =>
280
- transform(vin.data, vin.spec, vin.store))
660
+ struct.transform(vin.data, vin.spec))
661
+ })
662
+
663
+
664
+ test('transform-ref', async () => {
665
+ await runset(spec.transform.ref, (vin) =>
666
+ struct.transform(vin.data, vin.spec))
667
+ })
668
+
669
+
670
+ test('transform-format', async () => {
671
+ await runsetflags(spec.transform.format, { null: false }, (vin) =>
672
+ struct.transform(vin.data, vin.spec))
673
+ })
674
+
675
+
676
+ test('transform-apply', async () => {
677
+ await runset(spec.transform.apply, (vin) =>
678
+ struct.transform(vin.data, vin.spec))
679
+ })
680
+
681
+ test('transform-edge-apply', async () => {
682
+ const { transform } = struct
683
+ equal(2, transform({}, ['`$APPLY`', (v) => 1 + v, 1]))
281
684
  })
282
685
 
283
686
 
687
+
284
688
  test('transform-modify', async () => {
285
689
  await runset(spec.transform.modify, (vin) =>
286
- transform(vin.data, vin.spec, vin.store,
287
- (key, val, parent) => {
288
- if (null != key && null != parent && 'string' === typeof val) {
289
- val = parent[key] = '@' + val
690
+ struct.transform(
691
+ vin.data,
692
+ vin.spec,
693
+ {
694
+ modify: (val, key, parent) => {
695
+ if (null != key && null != parent && 'string' === typeof val) {
696
+ val = parent[key] = '@' + val
697
+ }
290
698
  }
291
699
  }
292
700
  ))
293
701
  })
294
702
 
703
+
295
704
  test('transform-extra', async () => {
296
- deepEqual(transform(
705
+ deepEqual(struct.transform(
297
706
  { a: 1 },
298
707
  { x: '`a`', b: '`$COPY`', c: '`$UPPER`' },
299
708
  {
300
- b: 2, $UPPER: (state) => {
301
- const { path } = state
302
- return ('' + getprop(path, path.length - 1)).toUpperCase()
709
+ extra: {
710
+ b: 2, $UPPER: (state) => {
711
+ const { path } = state
712
+ return ('' + struct.getprop(path, path.length - 1)).toUpperCase()
713
+ }
303
714
  }
304
715
  }
305
716
  ), {
@@ -311,42 +722,84 @@ describe('struct', async () => {
311
722
 
312
723
 
313
724
  test('transform-funcval', async () => {
314
- const f0 = ()=>99
315
- deepEqual(transform({},{x:1}), {x:1})
316
- deepEqual(transform({},{x:f0}), {x:f0})
317
- deepEqual(transform({a:1},{x:'`a`'}), {x:1})
318
- deepEqual(transform({f0},{x:'`f0`'}), {x:f0})
725
+ const { transform } = struct
726
+ // f0 should never be called (no $ prefix).
727
+ const f0 = () => 99
728
+ deepEqual(transform({}, { x: 1 }), { x: 1 })
729
+ deepEqual(transform({}, { x: f0 }), { x: f0 })
730
+ deepEqual(transform({ a: 1 }, { x: '`a`' }), { x: 1 })
731
+ deepEqual(transform({ f0 }, { x: '`f0`' }), { x: f0 })
319
732
  })
320
733
 
321
-
734
+
322
735
  // validate tests
323
736
  // ===============
324
737
 
325
- test('validate-exists', async () => {
326
- equal('function', typeof validate)
738
+ test('validate-basic', async () => {
739
+ await runsetflags(spec.validate.basic, { null: false },
740
+ (vin) => struct.validate(vin.data, vin.spec))
327
741
  })
328
742
 
329
-
330
- test('validate-basic', async () => {
331
- await runset(spec.validate.basic, (vin)=>validate(vin.data,vin.spec))
743
+
744
+ test('validate-child', async () => {
745
+ await runset(spec.validate.child, (vin) => struct.validate(vin.data, vin.spec))
332
746
  })
333
747
 
334
748
 
335
- test('validate-node', async () => {
336
- await runset(spec.validate.node, (vin)=>validate(vin.data,vin.spec))
749
+ test('validate-one', async () => {
750
+ await runset(spec.validate.one, (vin) => struct.validate(vin.data, vin.spec))
751
+ })
752
+
753
+
754
+ test('validate-exact', async () => {
755
+ await runset(spec.validate.exact, (vin) => struct.validate(vin.data, vin.spec))
756
+ })
757
+
758
+
759
+ test('validate-invalid', async () => {
760
+ await runsetflags(spec.validate.invalid, { null: false },
761
+ (vin) => struct.validate(vin.data, vin.spec))
762
+ })
763
+
764
+
765
+ test('validate-special', async () => {
766
+ await runset(spec.validate.special, (vin) =>
767
+ struct.validate(vin.data, vin.spec, vin.inj))
768
+ })
769
+
770
+
771
+ test('validate-edge', async () => {
772
+ const { validate } = struct
773
+ let errs = []
774
+ validate({ x: 1 }, { x: '`$INSTANCE`' }, { errs })
775
+ equal(errs[0], 'Expected field x to be instance, but found integer: 1.')
776
+
777
+ errs = []
778
+ validate({ x: {} }, { x: '`$INSTANCE`' }, { errs })
779
+ equal(errs[0], 'Expected field x to be instance, but found map: {}.')
780
+
781
+ errs = []
782
+ validate({ x: [] }, { x: '`$INSTANCE`' }, { errs })
783
+ equal(errs[0], 'Expected field x to be instance, but found list: [].')
784
+
785
+ class C { }
786
+ const c = new C()
787
+ errs = []
788
+ validate({ x: c }, { x: '`$INSTANCE`' }, { errs })
789
+ equal(errs.length, 0)
337
790
  })
338
791
 
339
792
 
340
793
  test('validate-custom', async () => {
341
794
  const errs = []
342
795
  const extra = {
343
- $INTEGER: (state, val, current)=>{
344
- const { mode, key, parent } = state
345
- let out = getprop(current, key)
796
+ $INTEGER: (inj) => {
797
+ const { key } = inj
798
+ let out = struct.getprop(inj.dparent, key)
346
799
 
347
800
  let t = typeof out
348
- if('number' !== t && !Number.isInteger(out)) {
349
- state.errs.push('Not an integer at '+state.path.slice(1).join('.')+': '+out)
801
+ if ('number' !== t && !Number.isInteger(out)) {
802
+ inj.errs.push('Not an integer at ' + inj.path.slice(1).join('.') + ': ' + out)
350
803
  return
351
804
  }
352
805
 
@@ -354,14 +807,114 @@ describe('struct', async () => {
354
807
  },
355
808
  }
356
809
 
357
- validate({a:1},{a:'`$INTEGER`'},extra,errs)
810
+ const shape = { a: '`$INTEGER`' }
811
+
812
+ let out = struct.validate({ a: 1 }, shape, { extra, errs })
813
+ deepEqual(out, { a: 1 })
358
814
  equal(errs.length, 0)
359
815
 
360
- validate({a:'A'},{a:'`$INTEGER`'},extra,errs)
361
- deepEqual(errs, [ 'Not an integer at a: A' ])
816
+ out = struct.validate({ a: 'A' }, shape, { extra, errs })
817
+ deepEqual(out, { a: 'A' })
818
+ deepEqual(errs, ['Not an integer at a: A'])
362
819
  })
363
820
 
364
821
 
365
- })
822
+ // select tests
823
+ // ============
824
+
825
+ test('select-basic', async () => {
826
+ await runset(spec.select.basic, (vin) => struct.select(vin.obj, vin.query))
827
+ })
828
+
829
+
830
+ test('select-operators', async () => {
831
+ await runset(spec.select.operators, (vin) => struct.select(vin.obj, vin.query))
832
+ })
366
833
 
367
834
 
835
+ test('select-edge', async () => {
836
+ await runset(spec.select.edge, (vin) => struct.select(vin.obj, vin.query))
837
+ })
838
+
839
+
840
+ test('select-alts', async () => {
841
+ await runset(spec.select.alts, (vin) => struct.select(vin.obj, vin.query))
842
+ })
843
+
844
+
845
+ // JSON Builder
846
+ // ============
847
+
848
+ test('json-builder', async () => {
849
+ const { jsonify, jm, jt } = struct
850
+ equal(jsonify(jm(
851
+ 'a', 1
852
+ )), `{
853
+ "a": 1
854
+ }`)
855
+
856
+ equal(jsonify(jt(
857
+ 'b', 2
858
+ )), `[
859
+ "b",
860
+ 2
861
+ ]`)
862
+
863
+ equal(jsonify(jm(
864
+ 'c', 'C',
865
+ 'd', jm('x', true),
866
+ 'e', jt(null, false)
867
+ )), `{
868
+ "c": "C",
869
+ "d": {
870
+ "x": true
871
+ },
872
+ "e": [
873
+ null,
874
+ false
875
+ ]
876
+ }`)
877
+
878
+ equal(jsonify(jt(
879
+ 3.3, jm(
880
+ 'f', true,
881
+ 'g', false,
882
+ 'h', null,
883
+ 'i', jt('y', 0),
884
+ 'j', jm('z', -1),
885
+ 'k')
886
+ )), `[
887
+ 3.3,
888
+ {
889
+ "f": true,
890
+ "g": false,
891
+ "h": null,
892
+ "i": [
893
+ "y",
894
+ 0
895
+ ],
896
+ "j": {
897
+ "z": -1
898
+ },
899
+ "k": null
900
+ }
901
+ ]`)
902
+
903
+ equal(jsonify(jm(
904
+ true, 1,
905
+ false, 2,
906
+ null, 3,
907
+ ['a'], 4,
908
+ { 'b': 0 }, 5
909
+ )), `{
910
+ "true": 1,
911
+ "false": 2,
912
+ "null": 3,
913
+ "[a]": 4,
914
+ "{b:0}": 5
915
+ }`)
916
+
917
+ })
918
+
919
+
920
+ })