@toa.io/norm 1.0.0-alpha.29 → 1.0.0-alpha.291

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 (85) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/package.json +8 -7
  3. package/src/.component/.expand/bridge.js +2 -6
  4. package/src/.component/.expand/entity.js +2 -9
  5. package/src/.component/.expand/events.js +2 -6
  6. package/src/.component/.expand/extensions.js +5 -8
  7. package/src/.component/.expand/index.js +8 -19
  8. package/src/.component/.expand/operations.js +2 -9
  9. package/src/.component/.expand/properties.js +2 -6
  10. package/src/.component/.expand/receivers.js +4 -7
  11. package/src/.component/.expand/version.js +38 -28
  12. package/src/.component/.normalize/entity.js +7 -0
  13. package/src/.component/.normalize/events.js +15 -5
  14. package/src/.component/.normalize/index.js +4 -9
  15. package/src/.component/.normalize/operations.js +10 -6
  16. package/src/.component/.normalize/receivers.js +4 -5
  17. package/src/.component/collapse.js +60 -9
  18. package/src/.component/defaults.js +16 -10
  19. package/src/.component/dependencies.js +14 -10
  20. package/src/.component/dereference.js +20 -18
  21. package/src/.component/expand.js +3 -7
  22. package/src/.component/extensions.js +15 -8
  23. package/src/.component/index.js +10 -21
  24. package/src/.component/merge.js +24 -13
  25. package/src/.component/migrations.js +57 -0
  26. package/src/.component/normalize.js +10 -6
  27. package/src/.component/schema.yaml +108 -71
  28. package/src/.component/validate.js +36 -17
  29. package/src/.context/.dependencies/connectors.js +5 -9
  30. package/src/.context/.dependencies/describe.js +4 -5
  31. package/src/.context/.dependencies/extensions.js +62 -20
  32. package/src/.context/.dependencies/index.js +3 -9
  33. package/src/.context/.dependencies/load.js +17 -14
  34. package/src/.context/.dependencies/resolve.js +23 -6
  35. package/src/.context/complete.js +1 -5
  36. package/src/.context/dependencies.js +2 -6
  37. package/src/.context/dereference.js +11 -6
  38. package/src/.context/expand.js +8 -6
  39. package/src/.context/index.js +6 -15
  40. package/src/.context/normalize.js +7 -5
  41. package/src/.context/schema.yaml +132 -11
  42. package/src/.context/validate.js +8 -14
  43. package/src/component.js +36 -17
  44. package/src/context.js +26 -14
  45. package/src/entity.js +15 -0
  46. package/src/index.js +4 -9
  47. package/src/shortcuts.js +8 -13
  48. package/test/component/collapse.fixtures.js +30 -39
  49. package/test/component/collapse.test.js +90 -10
  50. package/test/component/dependencies.test.js +16 -14
  51. package/test/component/dereference.fixtures.js +15 -24
  52. package/test/component/dereference.test.js +18 -8
  53. package/test/component/dummies/extension/index.js +1 -5
  54. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yaml +2 -0
  55. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yml +2 -0
  56. package/test/component/dummies/migrations/malformed/migrations/0001-one.yaml +1 -0
  57. package/test/component/dummies/migrations/ordered/migrations/0001-first.yml +4 -0
  58. package/test/component/dummies/migrations/ordered/migrations/0002-second.yaml +4 -0
  59. package/test/component/dummies/migrations/ordered/migrations/0010-third.json +1 -0
  60. package/test/component/dummies/migrations/stateless/migrations/0001-one.yaml +2 -0
  61. package/test/component/expand.fixtures.js +13 -13
  62. package/test/component/expand.test.js +25 -10
  63. package/test/component/migrations.test.js +62 -0
  64. package/test/component/normalize.fixtures.js +3 -7
  65. package/test/component/normalize.test.js +86 -28
  66. package/test/component/validate.fixtures.js +15 -13
  67. package/test/component/validate.test.js +162 -109
  68. package/test/context/complete.fixtures.js +2 -8
  69. package/test/context/complete.test.js +14 -8
  70. package/test/context/dependencies.load.test.js +13 -12
  71. package/test/context/dereference.fixtures.js +3 -9
  72. package/test/context/dereference.test.js +18 -7
  73. package/test/context/expand.fixtures.js +1 -5
  74. package/test/context/expand.test.js +36 -8
  75. package/test/context/normalize.fixtures.js +2 -7
  76. package/test/context/normalize.test.js +33 -9
  77. package/test/context/validate.fixtures.js +1 -6
  78. package/test/context/validate.test.js +81 -37
  79. package/test/shortcuts.fixtures.js +4 -9
  80. package/test/shortcuts.test.js +17 -15
  81. package/types/component.d.ts +17 -3
  82. package/types/context/declaration.d.ts +26 -3
  83. package/types/context.d.ts +15 -13
  84. package/types/entity.d.ts +7 -0
  85. package/types/index.d.ts +4 -3
@@ -1,19 +1,13 @@
1
- 'use strict'
1
+ import { resolve } from 'node:path'
2
2
 
3
- const { resolve } = require('node:path')
3
+ import { readFileSync } from 'node:fs'
4
+ import { yaml } from '@toa.io/generic'
5
+ import * as schemas from '@toa.io/schemas'
4
6
 
5
- const { load } = require('@toa.io/yaml')
6
- const { Schema } = require('@toa.io/schema')
7
+ const path = resolve(import.meta.dirname, 'schema.yaml')
8
+ const object = yaml.load(readFileSync(path, 'utf8'))
9
+ const schema = schemas.schema(object)
7
10
 
8
- const path = resolve(__dirname, 'schema.yaml')
9
- const object = load.sync(path)
10
- const schema = new Schema(object)
11
-
12
- /**
13
- * @param {toa.norm.context.Declaration} context
14
- */
15
- const validate = (context) => {
11
+ export const validate = (context) => {
16
12
  schema.validate(context)
17
13
  }
18
-
19
- exports.validate = validate
package/src/component.js CHANGED
@@ -1,49 +1,57 @@
1
- 'use strict'
1
+ import { join } from 'node:path'
2
2
 
3
- const { join } = require('node:path')
3
+ import { readFile } from 'node:fs/promises'
4
+ import { yaml as jsyaml } from '@toa.io/generic'
5
+ import { find } from '@toa.io/generic'
6
+ import { Locator } from '@toa.io/core'
4
7
 
5
- const { load: yaml } = require('@toa.io/yaml')
6
- const { directory: { find } } = require('@toa.io/filesystem')
7
- const { Locator } = require('@toa.io/core')
8
-
9
- const {
8
+ import {
10
9
  expand,
11
10
  merge,
11
+ migrations,
12
12
  validate,
13
13
  collapse,
14
14
  dereference,
15
15
  defaults,
16
16
  normalize,
17
17
  extensions
18
- } = require('./.component')
18
+ } from './.component/index.js'
19
19
 
20
- const component = async (path) => {
20
+ export const component = async (path) => {
21
21
  const manifest = await load(path)
22
22
 
23
- normalize(manifest)
24
- validate(manifest)
25
- extensions(manifest)
23
+ await normalize(manifest, path)
24
+ await validate(manifest)
25
+ await extensions(manifest)
26
26
 
27
27
  manifest.locator = new Locator(manifest.name, manifest.namespace)
28
28
 
29
29
  return manifest
30
30
  }
31
31
 
32
- const load = async (path, base) => {
32
+ const load = async (path, base, proto = false) => {
33
33
  if (base !== undefined) path = find(path, base, MANIFEST)
34
34
 
35
35
  const file = join(path, MANIFEST)
36
- const manifest = /** @type {toa.norm.Component} */ await yaml(file) ?? {}
36
+ const manifest = (await read(file)) ?? {}
37
37
 
38
38
  manifest.path = path
39
39
 
40
- defaults(manifest)
40
+ const anonymous = manifest.name === undefined
41
+
42
+ defaults(manifest, proto)
41
43
  await expand(manifest)
42
44
 
43
45
  await merge(path, manifest)
46
+ await migrations(path, manifest)
47
+
48
+ // an inherited migration is recorded under the prototype's name, and a generated one is not
49
+ // the same on the next machine
50
+ if (proto && anonymous && manifest.entity?.migrations !== undefined)
51
+ throw new Error(`Prototype at '${path}' declares migrations, so it has to be named`)
44
52
 
45
53
  if (manifest.prototype !== null) {
46
- const prototype = await load(manifest.prototype, path)
54
+ const prototype = await load(manifest.prototype, path, true)
47
55
 
48
56
  collapse(manifest, prototype)
49
57
  }
@@ -56,4 +64,15 @@ const load = async (path, base) => {
56
64
 
57
65
  const MANIFEST = 'manifest.toa.yaml'
58
66
 
59
- exports.component = component
67
+ /**
68
+ * Reads a YAML file, resolving anchors into distinct objects so that
69
+ * mutating one node cannot reach another.
70
+ *
71
+ * @param {string} path
72
+ * @return {Promise<object>}
73
+ */
74
+ async function read(path) {
75
+ const object = jsyaml.load(await readFile(path, 'utf8'))
76
+
77
+ return jsyaml.load(jsyaml.dump(object, { noRefs: true, lineWidth: -1 }))
78
+ }
package/src/context.js CHANGED
@@ -1,25 +1,23 @@
1
- 'use strict'
1
+ import { resolve } from 'node:path'
2
+ import { convolve, environment as variables } from '@toa.io/generic'
3
+ import glob from 'fast-glob'
4
+ import { readFile } from 'node:fs/promises'
5
+ import { yaml as jsyaml } from '@toa.io/generic'
2
6
 
3
- const { resolve } = require('node:path')
4
- const { convolve } = require('@toa.io/generic')
5
- const { directory: { glob } } = require('@toa.io/filesystem')
6
- const { load } = require('@toa.io/yaml')
7
+ import { component } from './component.js'
7
8
 
8
- const { component } = require('./component')
9
-
10
- const {
9
+ import {
11
10
  dependencies,
12
11
  normalize,
13
12
  complete,
14
13
  dereference,
15
14
  expand,
16
15
  validate
17
- } = require('./.context')
16
+ } from './.context/index.js'
18
17
 
19
- const context = async (root, environment = process.env.TOA_ENV) => {
18
+ export const context = async (root, environment = variables.get('TOA_ENV')) => {
20
19
  const path = resolve(root, CONTEXT)
21
- const context = /** @type {toa.norm.Context} */ await load(path)
22
- const pattern = resolve(root, context.packages)
20
+ const context = /** @type {toa.norm.Context} */ await read(path)
23
21
 
24
22
  context.environment = environment
25
23
 
@@ -29,7 +27,7 @@ const context = async (root, environment = process.env.TOA_ENV) => {
29
27
 
30
28
  validate(context)
31
29
 
32
- const paths = await glob(pattern)
30
+ const paths = await glob(resolve(root, COMPONENTS), GLOB)
33
31
 
34
32
  context.components = await Promise.all(paths.map(component))
35
33
  context.dependencies = await dependencies(context)
@@ -41,5 +39,19 @@ const context = async (root, environment = process.env.TOA_ENV) => {
41
39
  }
42
40
 
43
41
  const CONTEXT = 'context.toa.yaml'
42
+ const COMPONENTS = 'components/*'
43
+
44
+ const GLOB = { onlyDirectories: true, absolute: true }
44
45
 
45
- exports.context = context
46
+ /**
47
+ * Reads a YAML file, resolving anchors into distinct objects so that
48
+ * mutating one node cannot reach another.
49
+ *
50
+ * @param {string} path
51
+ * @return {Promise<object>}
52
+ */
53
+ async function read(path) {
54
+ const object = jsyaml.load(await readFile(path, 'utf8'))
55
+
56
+ return jsyaml.load(jsyaml.dump(object, { noRefs: true, lineWidth: -1 }))
57
+ }
package/src/entity.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * What a component declares about its records is a property map and a list of the properties a
3
+ * whole one has. A validator wants a schema, so it is assembled here rather than declared: one
4
+ * that a stored record must fit, and one for a changeset, which is whatever subset of the same
5
+ * properties an assignment writes.
6
+ */
7
+ export const schema = (entity) =>
8
+ entity.required === undefined
9
+ ? changeset(entity)
10
+ : { type: 'object', properties: entity.properties, required: entity.required }
11
+
12
+ export const changeset = (entity) => ({
13
+ type: 'object',
14
+ properties: entity.properties
15
+ })
package/src/index.js CHANGED
@@ -1,9 +1,4 @@
1
- 'use strict'
2
-
3
- const { context } = require('./context')
4
- const { component } = require('./component')
5
-
6
- exports.shortcuts = require('./shortcuts')
7
-
8
- exports.context = context
9
- exports.component = component
1
+ export { context } from './context.js'
2
+ export { component } from './component.js'
3
+ export * as shortcuts from './shortcuts.js'
4
+ export * as entity from './entity.js'
package/src/shortcuts.js CHANGED
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- const { empty, merge } = require('@toa.io/generic')
1
+ import { empty, merge } from '@toa.io/generic'
4
2
 
5
3
  /**
6
4
  * Resolves shortcuts
@@ -8,7 +6,7 @@ const { empty, merge } = require('@toa.io/generic')
8
6
  * @param {string} token
9
7
  * @returns {string}
10
8
  */
11
- const resolve = (token) => {
9
+ export const resolve = (token) => {
12
10
  if (token in SHORTCUTS) return SHORTCUTS[token]
13
11
  else return token
14
12
  }
@@ -20,7 +18,7 @@ const resolve = (token) => {
20
18
  * @param {Object} object
21
19
  * @param {string} [group]
22
20
  */
23
- const recognize = (shortcuts, object, group) => {
21
+ export const recognize = (shortcuts, object, group) => {
24
22
  if (object === undefined) return
25
23
 
26
24
  const target = group === undefined ? object : {}
@@ -38,21 +36,18 @@ const recognize = (shortcuts, object, group) => {
38
36
  if (group !== undefined && !empty(target)) object[group] = merge(object[group], target)
39
37
  }
40
38
 
41
- const SHORTCUTS = {
39
+ export const SHORTCUTS = {
42
40
  amqp: '@toa.io/bindings.amqp',
43
41
  node: '@toa.io/bridges.node',
44
42
  bash: '@toa.io/bridges.bash',
45
43
  mongodb: '@toa.io/storages.mongodb',
46
- sql: '@toa.io/storages.sql',
47
44
  queues: '@toa.io/storages.queues',
48
45
  exposition: '@toa.io/extensions.exposition',
49
46
  realtime: '@toa.io/extensions.realtime',
50
47
  configuration: '@toa.io/extensions.configuration',
51
- origins: '@toa.io/extensions.origins',
52
48
  stash: '@toa.io/extensions.stash',
53
- storages: '@toa.io/extensions.storages'
49
+ storages: '@toa.io/extensions.storages',
50
+ telemetry: '@toa.io/extensions.telemetry',
51
+ cadence: '@toa.io/extensions.cadence',
52
+ introspection: '@toa.io/extensions.introspection'
54
53
  }
55
-
56
- exports.recognize = recognize
57
- exports.resolve = resolve
58
- exports.SHORTCUTS = SHORTCUTS
@@ -1,55 +1,47 @@
1
- 'use strict'
2
-
3
- const { generate } = require('randomstring')
1
+ import { generate } from 'randomstring'
4
2
 
5
3
  const entity = {
6
4
  manifest: {
7
5
  entity: {
8
- schema: {
9
- properties: {
10
- foo: {
11
- type: 'string'
12
- },
13
- bar: {
14
- type: 'integer'
15
- }
6
+ properties: {
7
+ foo: {
8
+ type: 'string'
16
9
  },
17
- required: ['foo']
18
- }
10
+ bar: {
11
+ type: 'integer'
12
+ }
13
+ },
14
+ required: ['foo']
19
15
  }
20
16
  },
21
17
  prototype: {
22
18
  entity: {
23
- schema: {
24
- properties: {
25
- foo: {
26
- default: 'ok'
27
- },
28
- baz: {
29
- type: 'boolean'
30
- }
19
+ properties: {
20
+ foo: {
21
+ minLength: 1
31
22
  },
32
- required: ['baz']
33
- }
23
+ baz: {
24
+ type: 'boolean'
25
+ }
26
+ },
27
+ required: ['baz']
34
28
  }
35
29
  },
36
30
  result: {
37
31
  entity: {
38
- schema: {
39
- properties: {
40
- foo: {
41
- type: 'string',
42
- default: 'ok'
43
- },
44
- bar: {
45
- type: 'integer'
46
- },
47
- baz: {
48
- type: 'boolean'
49
- }
32
+ properties: {
33
+ foo: {
34
+ type: 'string',
35
+ minLength: 1
50
36
  },
51
- required: ['foo', 'baz']
52
- }
37
+ bar: {
38
+ type: 'integer'
39
+ },
40
+ baz: {
41
+ type: 'boolean'
42
+ }
43
+ },
44
+ required: ['foo', 'baz']
53
45
  }
54
46
  }
55
47
  }
@@ -88,7 +80,6 @@ const operations = {
88
80
  result: {
89
81
  prototype: {
90
82
  prototype: null,
91
- path: expect.any(String),
92
83
  operations: {
93
84
  add: {
94
85
  bridge: 'a'
@@ -131,4 +122,4 @@ const remotes = {
131
122
  }
132
123
  }
133
124
 
134
- exports.samples = { entity, operations, remotes }
125
+ export const samples = { entity, operations, remotes }
@@ -1,9 +1,10 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const clone = require('clone-deep')
4
+ import clone from 'clone-deep'
4
5
 
5
- const fixtures = require('./collapse.fixtures')
6
- const { collapse } = require('../../src/.component')
6
+ import * as fixtures from './collapse.fixtures.js'
7
+ import { collapse } from '../../src/.component/index.js'
7
8
 
8
9
  let samples
9
10
 
@@ -18,7 +19,7 @@ it('should ignore locator', () => {
18
19
 
19
20
  collapse(manifest, prototype)
20
21
 
21
- expect(manifest).toStrictEqual(source)
22
+ assert.deepStrictEqual(manifest, source)
22
23
  })
23
24
 
24
25
  it('should remove prototype property', () => {
@@ -26,7 +27,7 @@ it('should remove prototype property', () => {
26
27
 
27
28
  collapse(manifest, {})
28
29
 
29
- expect(manifest).toStrictEqual({})
30
+ assert.deepStrictEqual(manifest, {})
30
31
  })
31
32
 
32
33
  describe('entity', () => {
@@ -34,7 +35,80 @@ describe('entity', () => {
34
35
  const manifest = clone(samples.entity.manifest)
35
36
 
36
37
  collapse(manifest, samples.entity.prototype)
37
- expect(manifest).toStrictEqual(samples.entity.result)
38
+ assert.deepStrictEqual(manifest, samples.entity.result)
39
+ })
40
+
41
+ it('should let a component state its own id', () => {
42
+ const prototype = { entity: { properties: { id: { type: 'string' }, VERSION: {} } } }
43
+ const manifest = { name: 'pot', entity: { properties: { id: { type: 'number' } } } }
44
+
45
+ collapse(manifest, prototype)
46
+
47
+ assert.strictEqual(manifest.entity.custom, true)
48
+ assert.deepStrictEqual(manifest.entity.properties.id, { type: 'number' })
49
+ })
50
+
51
+ it('should refuse a component that states a property the runtime writes', () => {
52
+ const prototype = { entity: { properties: { DELETED: { type: 'integer' } } } }
53
+ const manifest = {
54
+ name: 'pot',
55
+ entity: { properties: { DELETED: { type: 'integer' } } }
56
+ }
57
+
58
+ assert.throws(
59
+ () => collapse(manifest, prototype),
60
+ /System property 'DELETED' cannot be overridden/
61
+ )
62
+ })
63
+
64
+ it('should inherit migrations ahead of its own, under the prototype name', () => {
65
+ const manifest = { entity: { migrations: [{ id: '0002', steps: [] }] } }
66
+ const prototype = {
67
+ name: 'base',
68
+ entity: { migrations: [{ id: '0001', steps: [] }] }
69
+ }
70
+
71
+ collapse(manifest, prototype)
72
+
73
+ assert.deepStrictEqual(manifest.entity.migrations, [
74
+ { id: 'base:0001', steps: [], prototype: 'base' },
75
+ { id: '0002', steps: [] }
76
+ ])
77
+ })
78
+
79
+ it('should pass on what the prototype inherited as it is', () => {
80
+ const manifest = { entity: { migrations: [{ id: '0002', steps: [] }] } }
81
+ const prototype = {
82
+ name: 'base',
83
+ entity: {
84
+ migrations: [
85
+ { id: 'system:0001', steps: [], prototype: 'system' },
86
+ { id: '0001', steps: [] }
87
+ ]
88
+ }
89
+ }
90
+
91
+ collapse(manifest, prototype)
92
+
93
+ assert.deepStrictEqual(
94
+ manifest.entity.migrations.map(({ id }) => id),
95
+ ['system:0001', 'base:0001', '0002']
96
+ )
97
+ })
98
+
99
+ it('should inherit migrations into a component that declares none', () => {
100
+ const manifest = {}
101
+ const prototype = {
102
+ name: 'base',
103
+ entity: { migrations: [{ id: '0001', steps: [] }] }
104
+ }
105
+
106
+ collapse(manifest, prototype)
107
+
108
+ assert.deepStrictEqual(
109
+ manifest.entity.migrations.map(({ id }) => id),
110
+ ['base:0001']
111
+ )
38
112
  })
39
113
  })
40
114
 
@@ -44,12 +118,12 @@ it('should ignore bindings', () => {
44
118
  const manifest = clone(source)
45
119
 
46
120
  collapse(manifest, prototype)
47
- expect(manifest).toStrictEqual(source)
121
+ assert.deepStrictEqual(manifest, source)
48
122
 
49
123
  delete manifest.bindings
50
124
 
51
125
  collapse(manifest, prototype)
52
- expect(manifest).toStrictEqual({})
126
+ assert.deepStrictEqual(manifest, {})
53
127
  })
54
128
 
55
129
  it('should merge operations', () => {
@@ -57,5 +131,11 @@ it('should merge operations', () => {
57
131
  const prototype = clone(samples.operations.prototype)
58
132
 
59
133
  collapse(manifest, prototype, '/somewhere')
60
- expect(manifest).toStrictEqual(samples.operations.result)
134
+
135
+ // the prototype's path is generated, so it is checked apart from the shape
136
+ assert.strictEqual(typeof manifest.prototype.path, 'string')
137
+
138
+ const { path, ...rest } = manifest.prototype
139
+
140
+ assert.deepStrictEqual({ ...manifest, prototype: rest }, samples.operations.result)
61
141
  })
@@ -1,38 +1,40 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { resolve } = require('node:path')
4
- const { dependencies } = require('../../src/.component')
4
+ import { resolve } from 'node:path'
5
+ import { dependencies } from '../../src/.component/index.js'
5
6
 
6
- const NORM = resolve(__dirname, '../../')
7
+ const NORM = resolve(import.meta.dirname, '../../')
7
8
 
8
9
  it('should be', async () => {
9
- expect(dependencies).toBeInstanceOf(Function)
10
+ assert.ok(dependencies instanceof Function)
10
11
  })
11
12
 
12
13
  /** @type {toa.norm.Component} */
13
14
  let component
14
15
 
15
16
  beforeEach(() => {
16
- component = /** @type {toa.norm.Component} */ { path: __dirname }
17
+ component = /** @type {toa.norm.Component} */ { path: import.meta.dirname }
17
18
  })
18
19
 
19
- describe.each(/** @type {[string, string][]} */ [
20
+ for (const [_, reference] of [
20
21
  ['package id', '@toa.io/norm'],
21
22
  ['relative path', '../../']
22
- ])('%s', (_, reference) => {
23
- it('should resolve storage', async () => {
24
- component.entity = { storage: reference, schema: {} }
23
+ ])
24
+ describe(`${_}`, () => {
25
+ it('should resolve storage', async () => {
26
+ component.entity = { storage: reference, schema: {} }
25
27
 
26
- dependencies(component)
28
+ dependencies(component)
27
29
 
28
- expect(component.entity.storage).toStrictEqual(NORM)
30
+ assert.deepStrictEqual(component.entity.storage, NORM)
31
+ })
29
32
  })
30
- })
31
33
 
32
34
  it('should resolve toa packages', async () => {
33
35
  component.entity = { storage: '@toa.io/core', schema: {} }
34
36
 
35
37
  dependencies(component)
36
38
 
37
- expect(component.entity.storage).toBeDefined()
39
+ assert.notStrictEqual(component.entity.storage, undefined)
38
40
  })
@@ -1,16 +1,12 @@
1
- 'use strict'
2
-
3
- const source = {
1
+ export const source = {
4
2
  entity: {
5
- schema: {
6
- properties: {
7
- foo: {
8
- type: 'string'
9
- },
10
- bar: {
11
- type: 'string',
12
- default: '.foo'
13
- }
3
+ properties: {
4
+ foo: {
5
+ type: 'string'
6
+ },
7
+ bar: {
8
+ type: 'string',
9
+ default: '.foo'
14
10
  }
15
11
  }
16
12
  },
@@ -66,16 +62,14 @@ const source = {
66
62
  }
67
63
  }
68
64
 
69
- const target = {
65
+ export const target = {
70
66
  entity: {
71
- schema: {
72
- properties: {
73
- foo: {
74
- type: 'string'
75
- },
76
- bar: {
77
- type: 'string'
78
- }
67
+ properties: {
68
+ foo: {
69
+ type: 'string'
70
+ },
71
+ bar: {
72
+ type: 'string'
79
73
  }
80
74
  }
81
75
  },
@@ -160,6 +154,3 @@ const target = {
160
154
  }
161
155
  }
162
156
  }
163
-
164
- exports.source = source
165
- exports.target = target
@@ -1,9 +1,10 @@
1
- 'use strict'
1
+ import { it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const clone = require('clone-deep')
4
+ import clone from 'clone-deep'
4
5
 
5
- const { dereference } = require('../../src/.component')
6
- const fixtures = require('./dereference.fixtures')
6
+ import { dereference } from '../../src/.component/index.js'
7
+ import * as fixtures from './dereference.fixtures.js'
7
8
 
8
9
  let source
9
10
 
@@ -14,18 +15,27 @@ beforeEach(() => {
14
15
  it('should dereference', () => {
15
16
  dereference(source)
16
17
 
17
- expect(source).toStrictEqual(fixtures.target)
18
+ assert.deepStrictEqual(source, fixtures.target)
18
19
  })
19
20
 
20
21
  it('should throw on invalid schema reference', () => {
21
22
  source.operations.transit.output.properties.baz = { type: 'string', default: '.' }
22
- expect(() => dereference(source)).toThrow(/is not defined/)
23
+ assert.throws(
24
+ () => dereference(source),
25
+ (error) => /is not defined/.test(error.message)
26
+ )
23
27
 
24
28
  source.operations.transit.output.properties.baz = { type: 'string', default: '.baz' }
25
- expect(() => dereference(source)).toThrow(/is not defined/)
29
+ assert.throws(
30
+ () => dereference(source),
31
+ (error) => /is not defined/.test(error.message)
32
+ )
26
33
  })
27
34
 
28
35
  it('should throw on invalid forwarding', () => {
29
36
  source.operations.create.forward = 'foo'
30
- expect(() => dereference(source)).toThrow(/is not defined/)
37
+ assert.throws(
38
+ () => dereference(source),
39
+ (error) => /is not defined/.test(error.message)
40
+ )
31
41
  })
@@ -1,9 +1,5 @@
1
- 'use strict'
2
-
3
- const manifest = (declaration) => {
1
+ export const manifest = (declaration) => {
4
2
  if (declaration.ok !== true) return
5
3
 
6
4
  return declaration
7
5
  }
8
-
9
- exports.manifest = manifest