@toa.io/norm 1.0.0-alpha.28 → 1.0.0-alpha.283
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/CHANGELOG.md +195 -0
- package/package.json +8 -7
- package/src/.component/.expand/bridge.js +2 -6
- package/src/.component/.expand/entity.js +2 -9
- package/src/.component/.expand/events.js +2 -6
- package/src/.component/.expand/extensions.js +4 -8
- package/src/.component/.expand/index.js +8 -19
- package/src/.component/.expand/operations.js +2 -9
- package/src/.component/.expand/properties.js +2 -6
- package/src/.component/.expand/receivers.js +2 -6
- package/src/.component/.expand/version.js +39 -27
- package/src/.component/.normalize/events.js +12 -5
- package/src/.component/.normalize/index.js +3 -9
- package/src/.component/.normalize/operations.js +2 -6
- package/src/.component/.normalize/receivers.js +1 -5
- package/src/.component/collapse.js +7 -6
- package/src/.component/defaults.js +14 -7
- package/src/.component/dependencies.js +7 -6
- package/src/.component/dereference.js +8 -7
- package/src/.component/expand.js +2 -15
- package/src/.component/extensions.js +13 -7
- package/src/.component/index.js +9 -21
- package/src/.component/merge.js +22 -9
- package/src/.component/normalize.js +3 -7
- package/src/.component/schema.yaml +82 -41
- package/src/.component/validate.js +15 -16
- package/src/.context/.dependencies/connectors.js +2 -6
- package/src/.context/.dependencies/describe.js +1 -5
- package/src/.context/.dependencies/extensions.js +55 -18
- package/src/.context/.dependencies/index.js +3 -9
- package/src/.context/.dependencies/load.js +14 -13
- package/src/.context/.dependencies/resolve.js +23 -6
- package/src/.context/complete.js +1 -5
- package/src/.context/dependencies.js +2 -6
- package/src/.context/dereference.js +9 -6
- package/src/.context/expand.js +8 -6
- package/src/.context/index.js +6 -15
- package/src/.context/normalize.js +2 -6
- package/src/.context/schema.yaml +126 -7
- package/src/.context/validate.js +8 -14
- package/src/component.js +31 -28
- package/src/context.js +28 -20
- package/src/index.js +3 -9
- package/src/shortcuts.js +7 -12
- package/test/component/collapse.fixtures.js +2 -5
- package/test/component/collapse.test.js +17 -10
- package/test/component/dependencies.test.js +12 -10
- package/test/component/dereference.fixtures.js +2 -7
- package/test/component/dereference.test.js +9 -8
- package/test/component/dummies/extension/index.js +1 -5
- package/test/component/expand.fixtures.js +13 -13
- package/test/component/expand.test.js +25 -10
- package/test/component/normalize.fixtures.js +3 -7
- package/test/component/normalize.test.js +27 -17
- package/test/component/validate.fixtures.js +1 -5
- package/test/component/validate.test.js +89 -90
- package/test/context/complete.fixtures.js +2 -8
- package/test/context/complete.test.js +10 -8
- package/test/context/dependencies.load.test.js +13 -12
- package/test/context/dereference.fixtures.js +3 -9
- package/test/context/dereference.test.js +17 -7
- package/test/context/expand.fixtures.js +1 -5
- package/test/context/expand.test.js +34 -8
- package/test/context/normalize.fixtures.js +2 -7
- package/test/context/normalize.test.js +10 -8
- package/test/context/validate.fixtures.js +1 -6
- package/test/context/validate.test.js +54 -30
- package/test/shortcuts.fixtures.js +4 -9
- package/test/shortcuts.test.js +16 -15
- package/types/context/declaration.d.ts +25 -2
- package/types/context.d.ts +5 -4
- package/types/index.d.ts +3 -3
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import clone from 'clone-deep'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { validate } = require('../../src/.component')
|
|
8
|
-
const fixtures = require('./validate.fixtures')
|
|
6
|
+
import { validate } from '../../src/.component/index.js'
|
|
7
|
+
import * as fixtures from './validate.fixtures.js'
|
|
9
8
|
|
|
10
9
|
let manifest
|
|
11
10
|
|
|
@@ -13,249 +12,249 @@ beforeEach(() => {
|
|
|
13
12
|
manifest = clone(fixtures.ok)
|
|
14
13
|
})
|
|
15
14
|
|
|
16
|
-
it('should be ok', () => {
|
|
17
|
-
|
|
15
|
+
it('should be ok', async () => {
|
|
16
|
+
await assert.doesNotReject(validate(manifest))
|
|
18
17
|
})
|
|
19
18
|
|
|
20
|
-
it('should provide error', () => {
|
|
19
|
+
it('should provide error', async () => {
|
|
21
20
|
manifest.foo = 'bar'
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
await assert.rejects(validate(manifest))
|
|
24
23
|
})
|
|
25
24
|
|
|
26
|
-
it('should not have additional properties', () => {
|
|
25
|
+
it('should not have additional properties', async () => {
|
|
27
26
|
manifest.foo = 'bar'
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
await assert.rejects(validate(manifest))
|
|
30
29
|
})
|
|
31
30
|
|
|
32
31
|
describe('namespace', () => {
|
|
33
|
-
it('should match token pattern', () => {
|
|
32
|
+
it('should match token pattern', async () => {
|
|
34
33
|
manifest.namespace = '1'
|
|
35
|
-
|
|
34
|
+
await assert.rejects(validate(manifest), (error) => /must match pattern/.test(error.message))
|
|
36
35
|
|
|
37
36
|
manifest.namespace = 'foo_'
|
|
38
|
-
|
|
37
|
+
await assert.rejects(validate(manifest), (error) => /must match pattern/.test(error.message))
|
|
39
38
|
|
|
40
39
|
manifest.namespace = 'foo_bar'
|
|
41
|
-
|
|
40
|
+
await assert.rejects(validate(manifest), (error) => /must match pattern/.test(error.message))
|
|
42
41
|
|
|
43
42
|
manifest.namespace = 'foo-'
|
|
44
|
-
|
|
43
|
+
await assert.rejects(validate(manifest), (error) => /must match pattern/.test(error.message))
|
|
45
44
|
|
|
46
45
|
manifest.namespace = 'foo-bar'
|
|
47
|
-
|
|
46
|
+
await assert.rejects(validate(manifest), (error) => /must match pattern/.test(error.message))
|
|
48
47
|
|
|
49
48
|
manifest.namespace = 'FooBar12'
|
|
50
|
-
|
|
49
|
+
await assert.doesNotReject(validate(manifest))
|
|
51
50
|
})
|
|
52
51
|
|
|
53
|
-
it('should forbid \'system\' namespace', () => {
|
|
52
|
+
it('should forbid \'system\' namespace', async () => {
|
|
54
53
|
manifest.namespace = 'system'
|
|
55
|
-
|
|
54
|
+
await assert.rejects(validate(manifest), (error) => /must NOT be valid/.test(error.message))
|
|
56
55
|
})
|
|
57
56
|
|
|
58
57
|
it('should set `default` namespace', async () => {
|
|
59
58
|
delete manifest.namespace
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
await assert.doesNotReject(validate(manifest))
|
|
61
|
+
assert.deepStrictEqual(manifest.namespace, 'default')
|
|
63
62
|
})
|
|
64
63
|
})
|
|
65
64
|
|
|
66
65
|
describe('name', () => {
|
|
67
|
-
it('should be optional', () => {
|
|
66
|
+
it('should be optional', async () => {
|
|
68
67
|
delete manifest.name
|
|
69
|
-
|
|
68
|
+
await assert.doesNotReject(validate(manifest))
|
|
70
69
|
})
|
|
71
70
|
})
|
|
72
71
|
|
|
73
72
|
describe('entity', () => {
|
|
74
|
-
it('should be optional', () => {
|
|
73
|
+
it('should be optional', async () => {
|
|
75
74
|
delete manifest.entity
|
|
76
|
-
|
|
75
|
+
await assert.doesNotReject(validate(manifest))
|
|
77
76
|
})
|
|
78
77
|
|
|
79
|
-
it('should be object', () => {
|
|
78
|
+
it('should be object', async () => {
|
|
80
79
|
manifest.entity = 'foo'
|
|
81
|
-
|
|
80
|
+
await assert.rejects(validate(manifest), (error) => /must be object/.test(error.message))
|
|
82
81
|
})
|
|
83
82
|
|
|
84
|
-
it('should not have additional properties', () => {
|
|
83
|
+
it('should not have additional properties', async () => {
|
|
85
84
|
manifest.entity.foo = 'bar'
|
|
86
|
-
|
|
85
|
+
await assert.rejects(validate(manifest))
|
|
87
86
|
})
|
|
88
87
|
|
|
89
88
|
describe('schema', () => {
|
|
90
|
-
it('should be required', () => {
|
|
89
|
+
it('should be required', async () => {
|
|
91
90
|
delete manifest.entity.schema
|
|
92
|
-
|
|
91
|
+
await assert.rejects(validate(manifest))
|
|
93
92
|
})
|
|
94
93
|
|
|
95
|
-
it('should be JSON schema object', () => {
|
|
94
|
+
it('should be JSON schema object', async () => {
|
|
96
95
|
manifest.entity.schema = { properties: { foo: 'bar' } }
|
|
97
|
-
|
|
96
|
+
await assert.rejects(validate(manifest))
|
|
98
97
|
})
|
|
99
98
|
|
|
100
|
-
it('should be JSON schema object of type object', () => {
|
|
99
|
+
it('should be JSON schema object of type object', async () => {
|
|
101
100
|
manifest.entity.schema = { type: 'integer' }
|
|
102
|
-
|
|
101
|
+
await assert.rejects(validate(manifest), (error) => /must be equal to constant/.test(error.message))
|
|
103
102
|
|
|
104
103
|
manifest.entity.schema = {}
|
|
105
104
|
validate(manifest)
|
|
106
|
-
|
|
105
|
+
assert.strictEqual(manifest.entity.schema.type, 'object')
|
|
107
106
|
})
|
|
108
107
|
|
|
109
|
-
it('should have property names matching token pattern', () => {
|
|
108
|
+
it('should have property names matching token pattern', async () => {
|
|
110
109
|
manifest.entity.schema.properties._foo = { type: 'string' }
|
|
111
|
-
|
|
110
|
+
await assert.rejects(validate(manifest), (error) => /pattern/.test(error.message))
|
|
112
111
|
})
|
|
113
112
|
|
|
114
|
-
it('should allow default id', () => {
|
|
113
|
+
it('should allow default id', async () => {
|
|
115
114
|
manifest.entity.schema.properties.id = {
|
|
116
115
|
type: 'string',
|
|
117
116
|
pattern: '^[a-fA-F0-9]+$'
|
|
118
117
|
}
|
|
119
|
-
|
|
118
|
+
await assert.doesNotReject(validate(manifest))
|
|
120
119
|
})
|
|
121
120
|
})
|
|
122
121
|
|
|
123
122
|
describe('associated', () => {
|
|
124
|
-
it('should provide default', () => {
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
it('should provide default', async () => {
|
|
124
|
+
await assert.doesNotReject(validate(manifest))
|
|
125
|
+
assert.strictEqual(manifest.entity.associated, false)
|
|
127
126
|
})
|
|
128
127
|
})
|
|
129
128
|
})
|
|
130
129
|
|
|
131
130
|
describe('bindings', () => {
|
|
132
|
-
it('should be array of unique strings', () => {
|
|
131
|
+
it('should be array of unique strings', async () => {
|
|
133
132
|
manifest.bindings = 'oops'
|
|
134
|
-
|
|
133
|
+
await assert.rejects(validate(manifest), (error) => /must be array/.test(error.message))
|
|
135
134
|
|
|
136
135
|
manifest.bindings = ['oops', 'oops']
|
|
137
|
-
|
|
136
|
+
await assert.rejects(validate(manifest), (error) => /duplicate items/.test(error.message))
|
|
138
137
|
|
|
139
138
|
manifest.bindings = ['oops', {}]
|
|
140
|
-
|
|
139
|
+
await assert.rejects(validate(manifest), (error) => /must be string/.test(error.message))
|
|
141
140
|
})
|
|
142
141
|
|
|
143
|
-
it('should forbid explicit loop', () => {
|
|
142
|
+
it('should forbid explicit loop', async () => {
|
|
144
143
|
manifest.bindings = ['@toa.io/bindings.loop']
|
|
145
|
-
|
|
144
|
+
await assert.rejects(validate(manifest), (error) => /must NOT be valid/.test(error.message))
|
|
146
145
|
})
|
|
147
146
|
})
|
|
148
147
|
|
|
149
148
|
describe('operations', () => {
|
|
150
|
-
it('should be object', () => {
|
|
149
|
+
it('should be object', async () => {
|
|
151
150
|
manifest.operations.get = 'bar'
|
|
152
|
-
|
|
151
|
+
await assert.rejects(validate(manifest), (error) => /must be object/.test(error.message))
|
|
153
152
|
})
|
|
154
153
|
|
|
155
|
-
it('should not have additional properties', () => {
|
|
154
|
+
it('should not have additional properties', async () => {
|
|
156
155
|
manifest.operations.get.foo = 'bar'
|
|
157
|
-
|
|
156
|
+
await assert.rejects(validate(manifest))
|
|
158
157
|
})
|
|
159
158
|
|
|
160
|
-
it('should have type (transition or observation)', () => {
|
|
159
|
+
it('should have type (transition or observation)', async () => {
|
|
161
160
|
delete manifest.operations.get.type
|
|
162
|
-
|
|
161
|
+
await assert.rejects(validate(manifest))
|
|
163
162
|
|
|
164
163
|
manifest.operations.get.type = 'foo'
|
|
165
|
-
|
|
164
|
+
await assert.rejects(validate(manifest), (error) => /one of the allowed values/.test(error.message))
|
|
166
165
|
})
|
|
167
166
|
|
|
168
|
-
it('should forbid explicit loop', () => {
|
|
167
|
+
it('should forbid explicit loop', async () => {
|
|
169
168
|
manifest.operations.get.bindings = ['@toa.io/bindings.loop']
|
|
170
|
-
|
|
169
|
+
await assert.rejects(validate(manifest), (error) => /must NOT be valid/.test(error.message))
|
|
171
170
|
})
|
|
172
171
|
|
|
173
|
-
it('should forbid query: false for observations', () => {
|
|
172
|
+
it('should forbid query: false for observations', async () => {
|
|
174
173
|
manifest.operations.get.query = false
|
|
175
|
-
|
|
174
|
+
await assert.rejects(validate(manifest), (error) => /must NOT be valid/.test(error.message))
|
|
176
175
|
})
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
['computation', 'compute']
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
for (const [_, operation] of [
|
|
178
|
+
['computation', 'compute']
|
|
179
|
+
])
|
|
180
|
+
it(`should set query: false for ${_}`, async () => {
|
|
182
181
|
validate(manifest)
|
|
183
182
|
|
|
184
|
-
|
|
183
|
+
assert.strictEqual(manifest.operations[operation].query, false)
|
|
185
184
|
})
|
|
186
185
|
|
|
187
186
|
describe('scope', () => {
|
|
188
|
-
it('should have scope', () => {
|
|
187
|
+
it('should have scope', async () => {
|
|
189
188
|
delete manifest.operations.get.scope
|
|
190
|
-
|
|
189
|
+
await assert.rejects(validate(manifest), (error) => /required property/.test(error.message))
|
|
191
190
|
})
|
|
192
191
|
|
|
193
|
-
it('should allow only entity or set for observations', () => {
|
|
192
|
+
it('should allow only entity or set for observations', async () => {
|
|
194
193
|
manifest.operations.get.scope = 'changeset'
|
|
195
|
-
|
|
194
|
+
await assert.rejects(validate(manifest), (error) => /allowed values/.test(error.message))
|
|
196
195
|
})
|
|
197
196
|
|
|
198
|
-
it('should allow only entity for transitions', () => {
|
|
197
|
+
it('should allow only entity for transitions', async () => {
|
|
199
198
|
manifest.operations.add.scope = 'changeset'
|
|
200
|
-
|
|
199
|
+
await assert.rejects(validate(manifest), (error) => /allowed values/.test(error.message))
|
|
201
200
|
|
|
202
201
|
manifest.operations.add.scope = 'set'
|
|
203
|
-
|
|
202
|
+
await assert.rejects(validate(manifest), (error) => /allowed values/.test(error.message))
|
|
204
203
|
})
|
|
205
204
|
|
|
206
|
-
it('should allow only changeset for assignments', () => {
|
|
205
|
+
it('should allow only changeset for assignments', async () => {
|
|
207
206
|
manifest.operations.set.scope = 'changeset'
|
|
208
|
-
|
|
207
|
+
await assert.doesNotReject(validate(manifest))
|
|
209
208
|
|
|
210
209
|
manifest.operations.set.scope = 'set'
|
|
211
|
-
|
|
210
|
+
await assert.rejects(validate(manifest), (error) => /allowed values/.test(error.message))
|
|
212
211
|
})
|
|
213
212
|
})
|
|
214
213
|
|
|
215
214
|
describe('concurrency', () => {
|
|
216
|
-
it('should be required for transitions', () => {
|
|
215
|
+
it('should be required for transitions', async () => {
|
|
217
216
|
delete manifest.operations.add.concurrency
|
|
218
|
-
|
|
217
|
+
await assert.rejects(validate(manifest), (error) => /required property/.test(error.message))
|
|
219
218
|
})
|
|
220
219
|
|
|
221
|
-
it('should throw for observations, assignments', () => {
|
|
220
|
+
it('should throw for observations, assignments', async () => {
|
|
222
221
|
manifest.operations.get.concurrency = 'none'
|
|
223
|
-
|
|
222
|
+
await assert.rejects(validate(manifest))
|
|
224
223
|
delete manifest.operations.get.concurrency
|
|
225
224
|
|
|
226
225
|
manifest.operations.set.concurrency = 'none'
|
|
227
|
-
|
|
226
|
+
await assert.rejects(validate(manifest))
|
|
228
227
|
})
|
|
229
228
|
})
|
|
230
229
|
|
|
231
230
|
describe('input, output', () => {
|
|
232
|
-
it('should be schema', () => {
|
|
231
|
+
it('should be schema', async () => {
|
|
233
232
|
manifest.operations.get.input = { properties: { foo: 'bar' } }
|
|
234
|
-
|
|
233
|
+
await assert.rejects(validate(manifest))
|
|
235
234
|
|
|
236
235
|
delete manifest.operations.get.input
|
|
237
236
|
manifest.operations.get.output = { properties: { foo: 'bar' } }
|
|
238
|
-
|
|
237
|
+
await assert.rejects(validate(manifest))
|
|
239
238
|
})
|
|
240
239
|
})
|
|
241
240
|
})
|
|
242
241
|
|
|
243
242
|
describe('receivers', () => {
|
|
244
|
-
it('should throw if transition points to undefined operation', () => {
|
|
243
|
+
it('should throw if transition points to undefined operation', async () => {
|
|
245
244
|
manifest.receivers['foo.bar.happened'].operation = 'notExists'
|
|
246
245
|
|
|
247
|
-
|
|
246
|
+
await assert.rejects(validate(manifest), (error) => /refers to undefined operation/.test(error.message))
|
|
248
247
|
})
|
|
249
248
|
|
|
250
|
-
it('should throw if transition points to observation', () => {
|
|
249
|
+
it('should throw if transition points to observation', async () => {
|
|
251
250
|
manifest.receivers['foo.bar.happened'].operation = 'get'
|
|
252
251
|
|
|
253
|
-
|
|
252
|
+
await assert.rejects(validate(manifest), (error) => /of the allowed types/.test(error.message))
|
|
254
253
|
})
|
|
255
254
|
|
|
256
255
|
it('should throw if source has a name `context`', async () => {
|
|
257
256
|
manifest.receivers['foo.bar.happened'].source = 'context'
|
|
258
257
|
|
|
259
|
-
|
|
258
|
+
await assert.rejects(validate(manifest), (error) => /must NOT be valid/.test(error.message))
|
|
260
259
|
})
|
|
261
260
|
})
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
const component = (id) => {
|
|
4
2
|
const [namespace, name] = id.split('.')
|
|
5
3
|
|
|
@@ -16,12 +14,11 @@ const component = (id) => {
|
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
const context = {
|
|
17
|
+
export const context = {
|
|
20
18
|
runtime: '0.0.0',
|
|
21
19
|
name: 'test',
|
|
22
20
|
description: 'context fixture',
|
|
23
21
|
version: '0.0.0',
|
|
24
|
-
packages: 'namespaces/**/*',
|
|
25
22
|
registry: 'localhost:5000',
|
|
26
23
|
components: [
|
|
27
24
|
component('a.b'),
|
|
@@ -43,7 +40,7 @@ const context = {
|
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
/** @type {Array<toa.norm.context.Composition>} */
|
|
46
|
-
const compositions = [
|
|
43
|
+
export const compositions = [
|
|
47
44
|
...context.compositions,
|
|
48
45
|
{
|
|
49
46
|
name: 'd-a',
|
|
@@ -54,6 +51,3 @@ const compositions = [
|
|
|
54
51
|
components: [component('d.b')]
|
|
55
52
|
}
|
|
56
53
|
]
|
|
57
|
-
|
|
58
|
-
exports.context = context
|
|
59
|
-
exports.compositions = compositions
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
import clone from 'clone-deep'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
import { complete } from '../../src/.context/index.js'
|
|
8
|
+
import * as fixtures from './complete.fixtures.js'
|
|
7
9
|
|
|
8
10
|
/** @type {toa.norm.Context} */
|
|
9
11
|
let context
|
|
@@ -14,8 +16,8 @@ beforeEach(() => {
|
|
|
14
16
|
})
|
|
15
17
|
|
|
16
18
|
it('should complete compositions', () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
assert.deepStrictEqual(context.compositions.length, fixtures.compositions.length)
|
|
20
|
+
assert.ok(fixtures.compositions.every((item) => context.compositions.some((candidate) => isDeepStrictEqual(candidate, item))))
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
it('should create if compositions are not set', () => {
|
|
@@ -26,6 +28,6 @@ it('should create if compositions are not set', () => {
|
|
|
26
28
|
components: [component]
|
|
27
29
|
}))
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
assert.doesNotThrow(() => complete(context))
|
|
32
|
+
assert.deepStrictEqual(context.compositions, compositions)
|
|
31
33
|
})
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { load } from '../../src/.context/.dependencies/load.js'
|
|
5
6
|
|
|
6
7
|
it('should be', async () => {
|
|
7
|
-
|
|
8
|
+
assert.ok(load instanceof Function)
|
|
8
9
|
})
|
|
9
10
|
|
|
10
11
|
it('should load module', async () => {
|
|
11
|
-
const path = join(
|
|
12
|
-
const { metadata, module } = load(path)
|
|
12
|
+
const path = join(import.meta.dirname, '../../')
|
|
13
|
+
const { metadata, module } = await load(path)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
assert.deepStrictEqual(metadata.name, '@toa.io/norm')
|
|
16
|
+
assert.ok(module.context instanceof Function)
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
it('should return null metadata if no package.json', async () => {
|
|
19
|
-
const path = join(
|
|
20
|
-
const { metadata, module } = load(path)
|
|
20
|
+
const path = join(import.meta.dirname, '../../src')
|
|
21
|
+
const { metadata, module } = await load(path)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
assert.strictEqual(metadata, null)
|
|
24
|
+
assert.ok(module.context instanceof Function)
|
|
24
25
|
})
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const clone = require('clone-deep')
|
|
1
|
+
import clone from 'clone-deep'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @param id {string}
|
|
@@ -22,12 +20,11 @@ const component = (id) => {
|
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
const context = {
|
|
23
|
+
export const context = {
|
|
26
24
|
name: 'test',
|
|
27
25
|
description: 'context fixture',
|
|
28
26
|
version: '0.0.0',
|
|
29
27
|
runtime: '0.0.0',
|
|
30
|
-
packages: 'namespaces/**/*',
|
|
31
28
|
registry: 'localhost:5000',
|
|
32
29
|
components: [component('a.b'), component('b.a'), component('d.c')],
|
|
33
30
|
compositions: [
|
|
@@ -42,7 +39,7 @@ const context = {
|
|
|
42
39
|
]
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
const expected = clone(context)
|
|
42
|
+
export const expected = clone(context)
|
|
46
43
|
|
|
47
44
|
expected.compositions = [
|
|
48
45
|
{
|
|
@@ -54,6 +51,3 @@ expected.compositions = [
|
|
|
54
51
|
components: [component('d.c'), component('a.b')]
|
|
55
52
|
}
|
|
56
53
|
]
|
|
57
|
-
|
|
58
|
-
exports.context = context
|
|
59
|
-
exports.expected = expected
|
|
@@ -1,24 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import { it, before } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import clone from 'clone-deep'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
import { dereference } from '../../src/.context/index.js'
|
|
7
|
+
import * as fixtures from './dereference.fixtures.js'
|
|
7
8
|
|
|
8
9
|
/** @type {toa.norm.Context} */
|
|
9
10
|
let context
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
before(() => {
|
|
12
13
|
context = clone(fixtures.context)
|
|
13
14
|
dereference(context)
|
|
14
15
|
})
|
|
15
16
|
|
|
16
17
|
it('should dereference', () => {
|
|
17
|
-
|
|
18
|
+
assert.partialDeepStrictEqual(context, fixtures.expected)
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
it('should not throw on empty compositions', () => {
|
|
21
22
|
context.compositions = undefined
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
assert.doesNotThrow(() => dereference(context))
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should throw on an unknown component', () => {
|
|
28
|
+
const broken = clone(fixtures.context)
|
|
29
|
+
|
|
30
|
+
broken.compositions[1].components.push('nope.here')
|
|
31
|
+
|
|
32
|
+
assert.throws(() => dereference(broken),
|
|
33
|
+
{ message: "Composition 'bar' lists an unknown component 'nope.here'." })
|
|
24
34
|
})
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import clone from 'clone-deep'
|
|
5
|
+
import { generate } from 'randomstring'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
import { expand } from '../../src/.context/index.js'
|
|
8
|
+
import * as fixtures from './expand.fixtures.js'
|
|
8
9
|
|
|
9
10
|
/** @type {toa.norm.context.Declaration | object} */
|
|
10
11
|
let context
|
|
@@ -17,7 +18,7 @@ describe('annotations', () => {
|
|
|
17
18
|
it('should not throw without annotations', () => {
|
|
18
19
|
delete context.annotations
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
assert.doesNotThrow(() => expand(context))
|
|
21
22
|
})
|
|
22
23
|
|
|
23
24
|
it('should expand known annotations', () => {
|
|
@@ -28,7 +29,7 @@ describe('annotations', () => {
|
|
|
28
29
|
|
|
29
30
|
expand(context)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
assert.deepStrictEqual(context.annotations, fixtures.context.annotations)
|
|
32
33
|
})
|
|
33
34
|
|
|
34
35
|
it('should recognize annotations', () => {
|
|
@@ -36,6 +37,31 @@ describe('annotations', () => {
|
|
|
36
37
|
|
|
37
38
|
expand(context)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
assert.notStrictEqual(context.annotations['@toa.io/storages.mongodb'], undefined)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe('composition services', () => {
|
|
45
|
+
it('should resolve shortcuts', () => {
|
|
46
|
+
context.compositions[0].services = ['exposition', 'configuration']
|
|
47
|
+
|
|
48
|
+
expand(context)
|
|
49
|
+
|
|
50
|
+
assert.deepStrictEqual(context.compositions[0].services,
|
|
51
|
+
['@toa.io/extensions.exposition', '@toa.io/extensions.configuration'])
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should leave a package reference alone', () => {
|
|
55
|
+
context.compositions[0].services = ['@acme/extension']
|
|
56
|
+
|
|
57
|
+
expand(context)
|
|
58
|
+
|
|
59
|
+
assert.deepStrictEqual(context.compositions[0].services, ['@acme/extension'])
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should not throw without compositions', () => {
|
|
63
|
+
delete context.compositions
|
|
64
|
+
|
|
65
|
+
assert.doesNotThrow(() => expand(context))
|
|
40
66
|
})
|
|
41
67
|
})
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { generate } from 'randomstring'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const context = {
|
|
3
|
+
export const context = {
|
|
6
4
|
runtime: {
|
|
7
5
|
version: '0.0.0'
|
|
8
6
|
},
|
|
9
7
|
name: 'test',
|
|
10
8
|
description: 'context fixture',
|
|
11
9
|
version: '0.0.0',
|
|
12
|
-
packages: 'namespaces/**/*',
|
|
13
10
|
registry: 'localhost:5000',
|
|
14
11
|
compositions: [
|
|
15
12
|
{
|
|
@@ -28,5 +25,3 @@ const context = {
|
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
|
-
|
|
32
|
-
exports.context = context
|