@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,10 +1,11 @@
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
- const { generate } = require('randomstring')
4
+ import clone from 'clone-deep'
5
+ import { generate } from 'randomstring'
5
6
 
6
- const { expand } = require('../../src/.context')
7
- const fixtures = require('./expand.fixtures')
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
- expect(() => expand(context)).not.toThrow()
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
- expect(context.annotations).toStrictEqual(fixtures.context.annotations)
32
+ assert.deepStrictEqual(context.annotations, fixtures.context.annotations)
32
33
  })
33
34
 
34
35
  it('should recognize annotations', () => {
@@ -36,6 +37,33 @@ describe('annotations', () => {
36
37
 
37
38
  expand(context)
38
39
 
39
- expect(context.annotations['@toa.io/storages.mongodb']).toBeDefined()
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',
52
+ '@toa.io/extensions.configuration'
53
+ ])
54
+ })
55
+
56
+ it('should leave a package reference alone', () => {
57
+ context.compositions[0].services = ['@acme/extension']
58
+
59
+ expand(context)
60
+
61
+ assert.deepStrictEqual(context.compositions[0].services, ['@acme/extension'])
62
+ })
63
+
64
+ it('should not throw without compositions', () => {
65
+ delete context.compositions
66
+
67
+ assert.doesNotThrow(() => expand(context))
40
68
  })
41
69
  })
@@ -1,15 +1,12 @@
1
- 'use strict'
1
+ import { generate } from 'randomstring'
2
2
 
3
- const { generate } = require('randomstring')
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
@@ -1,10 +1,12 @@
1
- 'use strict'
1
+ import * as runtime from '@toa.io/runtime'
2
+ import { it, beforeEach } from 'node:test'
3
+ import assert from 'node:assert/strict'
2
4
 
3
- const clone = require('clone-deep')
4
- const { generate } = require('randomstring')
5
+ import clone from 'clone-deep'
6
+ import { generate } from 'randomstring'
5
7
 
6
- const fixtures = require('./normalize.fixtures')
7
- const { normalize } = require('../../src/.context')
8
+ import * as fixtures from './normalize.fixtures.js'
9
+ import { normalize } from '../../src/.context/index.js'
8
10
 
9
11
  let context
10
12
 
@@ -17,8 +19,8 @@ it('should resolve local version', () => {
17
19
 
18
20
  normalize(context)
19
21
 
20
- expect(context.runtime).not.toEqual('.')
21
- expect(context.runtime.version).toEqual(require('@toa.io/runtime').version)
22
+ assert.notDeepStrictEqual(context.runtime, '.')
23
+ assert.deepStrictEqual(context.runtime.version, runtime.version)
22
24
  })
23
25
 
24
26
  it('should expand registry', () => {
@@ -28,7 +30,29 @@ it('should expand registry', () => {
28
30
 
29
31
  normalize(context)
30
32
 
31
- expect(context.registry).toEqual({
32
- base
33
+ assert.deepStrictEqual(context.registry, {
34
+ base,
35
+ platforms: ['linux/amd64', 'linux/arm/v7', 'linux/arm64']
33
36
  })
34
37
  })
38
+
39
+ it('should set default platforms', () => {
40
+ context.registry = { base: generate() }
41
+
42
+ normalize(context)
43
+
44
+ assert.deepStrictEqual(context.registry.platforms, [
45
+ 'linux/amd64',
46
+ 'linux/arm/v7',
47
+ 'linux/arm64'
48
+ ])
49
+ })
50
+
51
+ it('should keep platforms declared as none', () => {
52
+ // `platforms: ~` in the context: the runner's own platform, not the default list
53
+ context.registry = { base: generate(), platforms: null }
54
+
55
+ normalize(context)
56
+
57
+ assert.strictEqual(context.registry.platforms, null)
58
+ })
@@ -1,13 +1,10 @@
1
- 'use strict'
2
-
3
- const context = {
1
+ export const context = {
4
2
  runtime: {
5
3
  version: '0.0.0'
6
4
  },
7
5
  name: 'test',
8
6
  description: 'context fixture',
9
7
  version: '0.0.0',
10
- packages: 'namespaces/**/*',
11
8
  build: {
12
9
  command: 'echo test'
13
10
  },
@@ -37,5 +34,3 @@ const context = {
37
34
  }
38
35
  }
39
36
  }
40
-
41
- exports.context = context
@@ -1,14 +1,15 @@
1
- 'use strict'
1
+ import { describe, it, before, 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 { validate } = require('../../src/.context')
6
- const fixtures = require('./validate.fixtures')
6
+ import { validate } from '../../src/.context/index.js'
7
+ import * as fixtures from './validate.fixtures.js'
7
8
 
8
9
  let context
9
10
 
10
- beforeAll(() => {
11
- expect(() => validate(fixtures.context)).not.toThrow()
11
+ before(() => {
12
+ assert.doesNotThrow(() => validate(fixtures.context))
12
13
  })
13
14
 
14
15
  beforeEach(() => {
@@ -18,23 +19,32 @@ beforeEach(() => {
18
19
  describe('runtime', () => {
19
20
  it('should require', () => {
20
21
  delete context.runtime
21
- expect(() => validate(context)).toThrow(/required/)
22
+ assert.throws(
23
+ () => validate(context),
24
+ (error) => /required/.test(error.message)
25
+ )
22
26
  })
23
27
 
24
28
  it('should require registry to match uri format', () => {
25
29
  context.runtime.registry = 'not-a-uri'
26
- expect(() => validate(context)).toThrow(/must match format/)
30
+ assert.throws(
31
+ () => validate(context),
32
+ (error) => /must match format/.test(error.message)
33
+ )
27
34
 
28
35
  context.runtime.registry = 'http://localhost'
29
- expect(() => validate(context)).not.toThrow()
36
+ assert.doesNotThrow(() => validate(context))
30
37
  })
31
38
 
32
39
  it('should require proxy to match uri format', () => {
33
40
  context.runtime.proxy = 'not-a-uri'
34
- expect(() => validate(context)).toThrow(/must match format/)
41
+ assert.throws(
42
+ () => validate(context),
43
+ (error) => /must match format/.test(error.message)
44
+ )
35
45
 
36
46
  context.runtime.proxy = 'http://localhost'
37
- expect(() => validate(context)).not.toThrow()
47
+ assert.doesNotThrow(() => validate(context))
38
48
  })
39
49
  })
40
50
 
@@ -42,43 +52,77 @@ describe('registry', () => {
42
52
  it('should require', () => {
43
53
  delete context.registry
44
54
 
45
- expect(() => validate(context)).toThrow(/required property 'registry'/)
46
- })
47
-
48
- it('should require base', () => {
49
- delete context.registry.base
50
-
51
- expect(() => validate(context)).toThrow(/required property 'base'/)
52
- })
53
-
54
- it('should set default platforms', () => {
55
- delete context.registry.platforms
56
-
57
- validate(context)
58
-
59
- expect(context.registry.platforms).toBeInstanceOf(Array)
60
- expect(context.registry.platforms).toStrictEqual(['linux/amd64', 'linux/arm/v7', 'linux/arm64'])
55
+ assert.throws(
56
+ () => validate(context),
57
+ (error) => /required property 'registry'/.test(error.message)
58
+ )
61
59
  })
62
60
  })
63
61
 
64
62
  it('should require name as label', () => {
65
63
  delete context.name
66
- expect(() => validate(context)).toThrow(/required/)
64
+ assert.throws(
65
+ () => validate(context),
66
+ (error) => /required/.test(error.message)
67
+ )
67
68
 
68
69
  context.name = 'foo bar'
69
- expect(() => validate(context)).toThrow(/pattern/)
70
+ assert.throws(
71
+ () => validate(context),
72
+ (error) => /pattern/.test(error.message)
73
+ )
70
74
 
71
75
  context.name = 'foo-bar'
72
- expect(() => validate(context)).not.toThrow(/pattern/)
73
- })
74
-
75
- it('should set default packages location', () => {
76
- delete context.packages
77
- expect(() => validate(context)).not.toThrow()
78
- expect(context.packages).toBe('components/*')
76
+ assert.doesNotThrow(() => validate(context))
79
77
  })
80
78
 
81
79
  it('should require registry url', () => {
82
80
  delete context.registry
83
- expect(() => validate(context)).toThrow(/required/)
81
+ assert.throws(
82
+ () => validate(context),
83
+ (error) => /required/.test(error.message)
84
+ )
85
+ })
86
+
87
+ it('should allow mono replicas and resources', () => {
88
+ context.mono = {
89
+ replicas: 2,
90
+ resources: {
91
+ cpu: ['200m', '2'],
92
+ memory: ['256Mi', '2Gi']
93
+ }
94
+ }
95
+
96
+ assert.doesNotThrow(() => validate(context))
97
+ })
98
+
99
+ describe('compositions', () => {
100
+ it('should allow services', () => {
101
+ context.compositions[0].services = ['@toa.io/extensions.exposition']
102
+
103
+ assert.doesNotThrow(() => validate(context))
104
+ })
105
+
106
+ it('should require services to be a non-empty array of strings', () => {
107
+ context.compositions[0].services = []
108
+ assert.throws(
109
+ () => validate(context),
110
+ (error) => /fewer than 1 items/.test(error.message)
111
+ )
112
+
113
+ context.compositions[0].services = 'exposition'
114
+ assert.throws(
115
+ () => validate(context),
116
+ (error) => /must be array/.test(error.message)
117
+ )
118
+ })
119
+
120
+ it('should reject an unknown property', () => {
121
+ context.compositions[0].compoments = ['a.b']
122
+
123
+ assert.throws(
124
+ () => validate(context),
125
+ (error) => /Property compoments is not expected to be here/.test(error.message)
126
+ )
127
+ })
84
128
  })
@@ -1,14 +1,9 @@
1
- 'use strict'
1
+ import { generate } from 'randomstring'
2
+ import { random } from '@toa.io/generic'
2
3
 
3
- const { generate } = require('randomstring')
4
- const { random } = require('@toa.io/generic')
5
-
6
- const SHORTCUTS = {
4
+ export const SHORTCUTS = {
7
5
  amqp: '@toa.io/bindings.amqp',
8
6
  mongodb: '@toa.io/storages.mongodb'
9
7
  }
10
8
 
11
- const object = { foo: random(), bar: { baz: generate() } }
12
-
13
- exports.object = object
14
- exports.SHORTCUTS = SHORTCUTS
9
+ export const object = { foo: random(), bar: { baz: generate() } }
@@ -1,10 +1,11 @@
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
- const { generate } = require('randomstring')
4
+ import clone from 'clone-deep'
5
+ import { generate } from 'randomstring'
5
6
 
6
- const { recognize, resolve } = require('../src/shortcuts')
7
- const fixtures = require('./shortcuts.fixtures')
7
+ import { recognize, resolve } from '../src/shortcuts.js'
8
+ import * as fixtures from './shortcuts.fixtures.js'
8
9
 
9
10
  let object
10
11
 
@@ -14,16 +15,16 @@ beforeEach(() => {
14
15
 
15
16
  describe('resolve', () => {
16
17
  it('should be defined', () => {
17
- expect(resolve).toBeDefined()
18
+ assert.notStrictEqual(resolve, undefined)
18
19
  })
19
20
 
20
21
  it('should resolve', () => {
21
- expect(Object.keys(fixtures.SHORTCUTS).length).toBeGreaterThan(0)
22
+ assert.ok(Object.keys(fixtures.SHORTCUTS).length > 0)
22
23
 
23
24
  for (const [key, value] of Object.entries(fixtures.SHORTCUTS)) {
24
25
  const resolved = resolve(key)
25
26
 
26
- expect(resolved).toStrictEqual(value)
27
+ assert.deepStrictEqual(resolved, value)
27
28
  }
28
29
  })
29
30
  })
@@ -32,7 +33,7 @@ describe('recognize', () => {
32
33
  it('should not change unknown', () => {
33
34
  recognize(fixtures.SHORTCUTS, object)
34
35
 
35
- expect(object).toStrictEqual(fixtures.object)
36
+ assert.deepStrictEqual(object, fixtures.object)
36
37
  })
37
38
 
38
39
  it('should resolve known', () => {
@@ -41,8 +42,8 @@ describe('recognize', () => {
41
42
  recognize(fixtures.SHORTCUTS, object)
42
43
 
43
44
  for (const [alias, name] of Object.entries(fixtures.SHORTCUTS)) {
44
- expect(object[alias]).toBeUndefined()
45
- expect(object[name]).toStrictEqual(known[name])
45
+ assert.strictEqual(object[alias], undefined)
46
+ assert.deepStrictEqual(object[name], known[name])
46
47
  }
47
48
  })
48
49
 
@@ -52,9 +53,10 @@ describe('recognize', () => {
52
53
 
53
54
  recognize(fixtures.SHORTCUTS, object, group)
54
55
 
55
- expect(object[group]).toStrictEqual(known)
56
+ assert.deepStrictEqual(object[group], known)
56
57
 
57
- for (const alias of Object.keys(fixtures.SHORTCUTS)) expect(object[alias]).toBeUndefined()
58
+ for (const alias of Object.keys(fixtures.SHORTCUTS))
59
+ assert.strictEqual(object[alias], undefined)
58
60
  })
59
61
 
60
62
  it('should not overwrite group', () => {
@@ -67,7 +69,7 @@ describe('recognize', () => {
67
69
 
68
70
  recognize(fixtures.SHORTCUTS, object, group)
69
71
 
70
- expect(object[group]).toStrictEqual(expect.objectContaining(existing))
72
+ assert.partialDeepStrictEqual(object[group], existing)
71
73
  })
72
74
 
73
75
  it('should not create empty group', () => {
@@ -75,7 +77,7 @@ describe('recognize', () => {
75
77
 
76
78
  recognize(object, group)
77
79
 
78
- expect(object[group]).toBeUndefined()
80
+ assert.strictEqual(object[group], undefined)
79
81
  })
80
82
 
81
83
  const append = () => {
@@ -1,4 +1,5 @@
1
- import type { Locator, operations } from '@toa.io/core'
1
+ import type { Locator } from '@toa.io/core'
2
+ import type { operations } from '@toa.io/core/types'
2
3
 
3
4
  type Map = {
4
5
  [id: string]: Component
@@ -8,6 +9,7 @@ export type Operation = {
8
9
  type: operations.type
9
10
  scope?: operations.scope
10
11
  bindings?: string[]
12
+ description?: string
11
13
  input?: any
12
14
  output?: any
13
15
  error?: any
@@ -34,10 +36,22 @@ type Receiver = {
34
36
  source?: string
35
37
  }
36
38
 
37
- type Entity = {
38
- schema: Object
39
+ type Migration = {
40
+ id: string
41
+ steps: unknown[]
42
+ /** the prototype it is inherited from; absent on the component's own */
43
+ prototype?: string
44
+ }
45
+
46
+ export type Entity = {
47
+ properties: Record<string, Object>
48
+ required?: string[]
49
+ /** what a record holds before anything is written to it */
50
+ blank?: Record<string, unknown>
39
51
  storage?: string
40
52
  associated?: boolean
53
+ custom?: boolean
54
+ migrations?: Migration[]
41
55
  }
42
56
 
43
57
  type Declaration = {
@@ -1,8 +1,30 @@
1
- import { Composition, Registry, Runtime } from '../context'
1
+ import { Registry, Runtime } from '../context.js'
2
2
 
3
+ /** A composition as declared, before its members are resolved. */
3
4
  interface Composition {
4
- name: string,
5
+ name: string
5
6
  components: string[]
7
+ services?: string[]
8
+ }
9
+
10
+ export interface Resources {
11
+ cpu?: [string, string]
12
+ memory?: [string, string]
13
+ }
14
+
15
+ export interface Mono {
16
+ replicas?: number
17
+ resources?: Resources
18
+ }
19
+
20
+ /**
21
+ * Cluster-level ingress configuration, applied to every service that declares one.
22
+ */
23
+ export interface Ingress {
24
+ hosts?: string[]
25
+ class?: string
26
+ annotations?: Record<string, string>
27
+ default?: boolean
6
28
  }
7
29
 
8
30
  export interface Declaration {
@@ -11,7 +33,8 @@ export interface Declaration {
11
33
  version?: string
12
34
  runtime?: Runtime | string
13
35
  registry?: Registry | string
14
- packages?: string
15
36
  compositions?: Composition[]
37
+ mono?: Mono
38
+ ingress?: Ingress
16
39
  annotations?: Record<string, object>
17
40
  }
@@ -1,41 +1,43 @@
1
- import { Manifest } from './component'
1
+ import { Manifest } from './component.js'
2
2
  import { Locator } from '@toa.io/core'
3
- import type { Declaration } from './context/declaration'
3
+ import type { Declaration } from './context/declaration.js'
4
4
 
5
- interface Runtime{
5
+ interface Runtime {
6
6
  version: string
7
7
  registry?: string
8
8
  proxy?: string
9
9
  }
10
10
 
11
- interface Registry{
11
+ interface Registry {
12
12
  base?: string
13
13
  platforms?: string[] | null
14
+ services?: 'build' | 'published'
14
15
  build?: {
15
16
  arguments?: string[]
16
17
  run?: string
17
- },
18
+ }
18
19
  credentials: string
19
20
  }
20
21
 
21
- interface Composition{
22
- name: string,
23
- components: _component.Component[]
22
+ interface Composition {
23
+ name: string
24
+ components: Manifest[]
25
+ services?: string[]
24
26
  }
25
27
 
26
- export interface Dependency<T = undefined>{
28
+ export interface Dependency<T = undefined> {
27
29
  locator: Locator
28
- manifest: T,
30
+ manifest: T
29
31
  component: Manifest
30
32
  }
31
33
 
32
- interface Context extends Declaration{
34
+ interface Context extends Declaration {
33
35
  runtime?: Runtime
34
36
  environment?: string
35
37
  registry?: Registry
36
38
  compositions?: Composition[]
37
- components?: _component.Component[]
39
+ components?: Manifest[]
38
40
  dependencies?: Record<string, Dependency[]>
39
41
  }
40
42
 
41
- export function context (path: string, environment?: string): Promise<Context>
43
+ export function context(path: string, environment?: string): Promise<Context>
@@ -0,0 +1,7 @@
1
+ import type { Entity } from './component.js'
2
+
3
+ /** The schema a stored record must fit. */
4
+ export function schema(entity: Entity): object
5
+
6
+ /** The schema a changeset must fit: the same properties, none of them required. */
7
+ export function changeset(entity: Entity): object
package/types/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * as context from './context'
2
- export * as component from './component'
1
+ export * as context from './context.js'
2
+ export * as component from './component.js'
3
3
 
4
- export { Manifest } from './component'
4
+ export { Manifest } from './component.js'
5
+ export * as entity from './entity.js'