@toa.io/norm 1.0.0-alpha.2 → 1.0.0-alpha.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/norm",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.20",
4
4
  "description": "Toa declarations normalization and validation",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -20,11 +20,11 @@
20
20
  "test": "echo \"Error: run tests from root\" && exit 1"
21
21
  },
22
22
  "dependencies": {
23
- "@toa.io/core": "1.0.0-alpha.2",
24
- "@toa.io/generic": "1.0.0-alpha.2",
25
- "@toa.io/schema": "1.0.0-alpha.2",
26
- "@toa.io/schemas": "1.0.0-alpha.2",
27
- "@toa.io/yaml": "1.0.0-alpha.2"
23
+ "@toa.io/core": "1.0.0-alpha.20",
24
+ "@toa.io/generic": "1.0.0-alpha.20",
25
+ "@toa.io/schema": "1.0.0-alpha.20",
26
+ "@toa.io/schemas": "1.0.0-alpha.20",
27
+ "@toa.io/yaml": "1.0.0-alpha.20"
28
28
  },
29
- "gitHead": "7688e6e980a65c82ac2e459be4e355eebf406cd0"
29
+ "gitHead": "dcde3389a86ab38e377ebc5ab18e5d5a512b85bc"
30
30
  }
@@ -7,6 +7,7 @@ const { extensions } = require('./extensions')
7
7
  const { operations } = require('./operations')
8
8
  const { properties } = require('./properties')
9
9
  const { receivers } = require('./receivers')
10
+ const { version } = require('./version')
10
11
 
11
12
  exports.bridge = bridge
12
13
  exports.entity = entity
@@ -15,3 +16,4 @@ exports.extensions = extensions
15
16
  exports.operations = operations
16
17
  exports.properties = properties
17
18
  exports.receivers = receivers
19
+ exports.version = version
@@ -0,0 +1,45 @@
1
+ 'use strict'
2
+
3
+ const { join } = require('node:path')
4
+ const { createHash } = require('node:crypto')
5
+ const fs = require('node:fs/promises')
6
+ const { createReadStream } = require('node:fs')
7
+ const { once } = require('node:events')
8
+
9
+ async function version (manifest) {
10
+ manifest.version ??= await hash(manifest.path)
11
+ }
12
+
13
+ async function hash (path) {
14
+ const hash = await hashd(path)
15
+
16
+ return hash.digest('hex').slice(0, 8)
17
+ }
18
+
19
+ /**
20
+ * @param {string} path
21
+ * @param {import('node:crypto').Hash} hash
22
+ */
23
+ async function hashd (path, hash = createHash('sha256')) {
24
+ const stat = await fs.stat(path)
25
+
26
+ if (stat.isFile()) {
27
+ const stream = createReadStream(path)
28
+
29
+ stream.pipe(hash, { end: false })
30
+
31
+ return await once(stream, 'end')
32
+ }
33
+
34
+ if (stat.isDirectory()) {
35
+ const entries = await fs.opendir(path)
36
+
37
+ for await (const entry of entries) {
38
+ await hashd(join(path, entry.name), hash)
39
+ }
40
+
41
+ return hash
42
+ }
43
+ }
44
+
45
+ exports.version = version
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { hash } = require('@toa.io/generic')
4
+ const assert = require('node:assert')
4
5
 
5
6
  // these defaults are required before validation
6
7
  const defaults = (manifest) => {
@@ -17,9 +18,6 @@ const defaults = (manifest) => {
17
18
  }
18
19
 
19
20
  if (manifest.prototype === undefined) manifest.prototype = '@toa.io/prototype'
20
-
21
- // TODO: bridge.version()
22
- if (manifest.version === undefined) manifest.version = '0.0.0'
23
21
  }
24
22
 
25
23
  function protoName (manifest) {
@@ -7,10 +7,11 @@ const {
7
7
  events,
8
8
  receivers,
9
9
  extensions,
10
- properties
10
+ properties,
11
+ version
11
12
  } = require('./.expand')
12
13
 
13
- const expand = (manifest) => {
14
+ async function expand (manifest) {
14
15
  entity(manifest)
15
16
  bridge(manifest)
16
17
  operations(manifest)
@@ -18,6 +19,8 @@ const expand = (manifest) => {
18
19
  receivers(manifest)
19
20
  properties(manifest)
20
21
  extensions(manifest)
22
+
23
+ await version(manifest)
21
24
  }
22
25
 
23
26
  exports.expand = expand
@@ -53,7 +53,7 @@ properties:
53
53
  - const: 'system'
54
54
 
55
55
  version:
56
- $ref: 'definitions#/definitions/version'
56
+ type: string
57
57
 
58
58
  build:
59
59
  type: object
@@ -79,8 +79,24 @@ properties:
79
79
  propertyNames:
80
80
  oneOf:
81
81
  - $ref: '#/definitions/name'
82
- - enum: [_version]
83
- dependent:
82
+ - enum: [_version, _created, _updated, _deleted]
83
+ unique:
84
+ type: object
85
+ patternProperties:
86
+ '.*':
87
+ type: array
88
+ items:
89
+ type: string
90
+ index:
91
+ type: object
92
+ patternProperties:
93
+ '.*':
94
+ type: object
95
+ patternProperties:
96
+ '.*':
97
+ type: string
98
+ enum: [asc, desc, hash]
99
+ associated:
84
100
  type: boolean
85
101
  default: false
86
102
  custom:
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ const { resolve } = require('node:path')
4
+
3
5
  const connectors = (context, extracted) => {
4
6
  const connectors = {}
5
7
 
@@ -10,11 +12,14 @@ const connectors = (context, extracted) => {
10
12
 
11
13
  for (const component of components) {
12
14
  if (component.entity !== undefined) {
13
- if (connectors[component.entity.storage] === undefined) {
14
- connectors[component.entity.storage] = []
15
+ let storage = component.entity.storage
16
+
17
+ if (storage[0] === '.') {
18
+ storage = resolve(component.path, storage)
15
19
  }
16
20
 
17
- connectors[component.entity.storage].push(component)
21
+ connectors[storage] ??= []
22
+ connectors[storage].push(component)
18
23
  }
19
24
 
20
25
  const bindings = new Set()
@@ -4,13 +4,14 @@ $id: https://schemas.toa.io/0.0.0/context
4
4
  type: object
5
5
  properties:
6
6
  version:
7
- $ref: 'definitions#/definitions/version'
7
+ type: string
8
8
  name:
9
9
  $ref: 'definitions#/definitions/label'
10
10
  description:
11
11
  type: string
12
12
  packages:
13
13
  type: string
14
+ default: components/*
14
15
  build:
15
16
  type: object
16
17
  properties:
@@ -20,7 +21,7 @@ properties:
20
21
  type: object
21
22
  properties:
22
23
  version:
23
- $ref: 'definitions#/definitions/version'
24
+ type: string
24
25
  registry:
25
26
  type: string
26
27
  format: uri
@@ -64,5 +65,5 @@ properties:
64
65
  required: [name, components]
65
66
  annotations:
66
67
  type: object
67
- required: [runtime, name, packages, registry]
68
+ required: [runtime, name, registry]
68
69
  additionalProperties: false
package/src/component.js CHANGED
@@ -13,7 +13,6 @@ const {
13
13
  collapse,
14
14
  dereference,
15
15
  defaults,
16
- dependencies,
17
16
  normalize,
18
17
  extensions
19
18
  } = require('./.component')
@@ -39,7 +38,7 @@ const load = async (path, base) => {
39
38
  manifest.path = path
40
39
 
41
40
  defaults(manifest)
42
- expand(manifest)
41
+ await expand(manifest)
43
42
 
44
43
  await merge(path, manifest)
45
44
 
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const source = {
4
+ path: '',
4
5
  entity: {
5
6
  schema: {
6
7
  properties: {
@@ -112,15 +112,18 @@ describe('entity', () => {
112
112
  })
113
113
 
114
114
  it('should allow default id', () => {
115
- manifest.entity.schema.properties.id = { type: 'string', pattern: '^[a-fA-F0-9]+$' }
115
+ manifest.entity.schema.properties.id = {
116
+ type: 'string',
117
+ pattern: '^[a-fA-F0-9]+$'
118
+ }
116
119
  expect(() => validate(manifest)).not.toThrow()
117
120
  })
118
121
  })
119
122
 
120
- describe('dependent', () => {
123
+ describe('associated', () => {
121
124
  it('should provide default', () => {
122
125
  expect(() => validate(manifest)).not.toThrow()
123
- expect(manifest.entity.dependent).toBe(false)
126
+ expect(manifest.entity.associated).toBe(false)
124
127
  })
125
128
  })
126
129
  })
@@ -21,14 +21,6 @@ describe('runtime', () => {
21
21
  expect(() => validate(context)).toThrow(/required/)
22
22
  })
23
23
 
24
- it('should require version as semver', () => {
25
- delete context.runtime.version
26
- expect(() => validate(context)).toThrow(/required/)
27
-
28
- context.runtime.version = '.'
29
- expect(() => validate(context)).toThrow(/pattern/)
30
- })
31
-
32
24
  it('should require registry to match uri format', () => {
33
25
  context.runtime.registry = 'not-a-uri'
34
26
  expect(() => validate(context)).toThrow(/must match format/)
@@ -80,9 +72,10 @@ it('should require name as label', () => {
80
72
  expect(() => validate(context)).not.toThrow(/pattern/)
81
73
  })
82
74
 
83
- it('should require packages location', () => {
75
+ it('should set default packages location', () => {
84
76
  delete context.packages
85
- expect(() => validate(context)).toThrow(/required/)
77
+ expect(() => validate(context)).not.toThrow()
78
+ expect(context.packages).toBe('components/*')
86
79
  })
87
80
 
88
81
  it('should require registry url', () => {
@@ -37,7 +37,7 @@ type Receiver = {
37
37
  type Entity = {
38
38
  schema: Object
39
39
  storage?: string
40
- dependent?: boolean
40
+ associated?: boolean
41
41
  }
42
42
 
43
43
  type Declaration = {