@toa.io/extensions.exposition 0.20.0-dev.8 → 0.20.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 (191) hide show
  1. package/components/context.toa.yaml +15 -0
  2. package/components/identity.bans/manifest.toa.yaml +18 -0
  3. package/components/identity.basic/events/principal.js +9 -0
  4. package/components/identity.basic/manifest.toa.yaml +50 -0
  5. package/components/identity.basic/source/authenticate.ts +29 -0
  6. package/components/identity.basic/source/create.ts +19 -0
  7. package/components/identity.basic/source/transit.ts +64 -0
  8. package/components/identity.basic/source/types.ts +42 -0
  9. package/components/identity.basic/tsconfig.json +9 -0
  10. package/components/identity.roles/manifest.toa.yaml +31 -0
  11. package/components/identity.roles/source/list.ts +7 -0
  12. package/components/identity.roles/source/principal.ts +20 -0
  13. package/components/identity.roles/tsconfig.json +9 -0
  14. package/components/identity.tokens/manifest.toa.yaml +39 -0
  15. package/components/identity.tokens/receivers/identity.bans.updated.js +3 -0
  16. package/components/identity.tokens/source/authenticate.test.ts +56 -0
  17. package/components/identity.tokens/source/authenticate.ts +38 -0
  18. package/components/identity.tokens/source/decrypt.test.ts +59 -0
  19. package/components/identity.tokens/source/decrypt.ts +25 -0
  20. package/components/identity.tokens/source/encrypt.test.ts +35 -0
  21. package/components/identity.tokens/source/encrypt.ts +25 -0
  22. package/components/identity.tokens/source/revoke.ts +5 -0
  23. package/components/identity.tokens/source/types.ts +48 -0
  24. package/components/identity.tokens/tsconfig.json +9 -0
  25. package/cucumber.js +9 -0
  26. package/documentation/.assets/ia3-dark.jpg +0 -0
  27. package/documentation/.assets/ia3-light.jpg +0 -0
  28. package/documentation/.assets/overview-dark.jpg +0 -0
  29. package/documentation/.assets/overview-light.jpg +0 -0
  30. package/documentation/.assets/role-scopes-dark.jpg +0 -0
  31. package/documentation/.assets/role-scopes-light.jpg +0 -0
  32. package/documentation/.assets/rtd-dark.jpg +0 -0
  33. package/documentation/.assets/rtd-light.jpg +0 -0
  34. package/documentation/access.md +256 -0
  35. package/documentation/components.md +276 -0
  36. package/documentation/identity.md +156 -0
  37. package/documentation/notes/sse.md +71 -0
  38. package/documentation/protocol.md +18 -0
  39. package/documentation/query.md +226 -0
  40. package/documentation/tree.md +169 -0
  41. package/features/access.feature +448 -0
  42. package/features/annotation.feature +30 -0
  43. package/features/body.feature +45 -0
  44. package/features/directives.feature +56 -0
  45. package/features/dynamic.feature +99 -0
  46. package/features/errors.feature +193 -0
  47. package/features/identity.basic.feature +276 -0
  48. package/features/identity.feature +61 -0
  49. package/features/identity.roles.feature +51 -0
  50. package/features/identity.tokens.feature +119 -0
  51. package/features/queries.feature +214 -0
  52. package/features/routes.feature +49 -0
  53. package/features/steps/Common.ts +10 -0
  54. package/features/steps/Components.ts +43 -0
  55. package/features/steps/Database.ts +58 -0
  56. package/features/steps/Gateway.ts +113 -0
  57. package/features/steps/HTTP.ts +71 -0
  58. package/features/steps/Parameters.ts +12 -0
  59. package/features/steps/Workspace.ts +40 -0
  60. package/features/steps/components/echo/manifest.toa.yaml +9 -0
  61. package/features/steps/components/echo/operations/affect.js +7 -0
  62. package/features/steps/components/echo/operations/compute.js +7 -0
  63. package/features/steps/components/greeter/manifest.toa.yaml +5 -0
  64. package/features/steps/components/greeter/operations/greet.js +7 -0
  65. package/features/steps/components/pots/manifest.toa.yaml +20 -0
  66. package/features/steps/components/sequences/manifest.toa.yaml +10 -0
  67. package/features/steps/components/sequences/operations/numbers.js +7 -0
  68. package/features/steps/components/sequences/operations/tokens.js +16 -0
  69. package/features/steps/components/users/manifest.toa.yaml +11 -0
  70. package/features/steps/tsconfig.json +9 -0
  71. package/features/streams.feature +26 -0
  72. package/package.json +32 -17
  73. package/readme.md +183 -0
  74. package/schemas/annotation.cos.yaml +5 -0
  75. package/schemas/directive.cos.yaml +3 -0
  76. package/schemas/method.cos.yaml +8 -0
  77. package/schemas/node.cos.yaml +5 -0
  78. package/schemas/query.cos.yaml +17 -0
  79. package/schemas/querystring.cos.yaml +5 -0
  80. package/schemas/range.cos.yaml +2 -0
  81. package/schemas/route.cos.yaml +2 -0
  82. package/source/Annotation.ts +7 -0
  83. package/source/Branch.ts +8 -0
  84. package/source/Composition.ts +57 -0
  85. package/source/Context.ts +6 -0
  86. package/source/Directive.test.ts +91 -0
  87. package/source/Directive.ts +120 -0
  88. package/source/Endpoint.ts +59 -0
  89. package/source/Factory.ts +51 -0
  90. package/source/Gateway.ts +93 -0
  91. package/source/HTTP/Server.fixtures.ts +45 -0
  92. package/source/HTTP/Server.test.ts +221 -0
  93. package/source/HTTP/Server.ts +135 -0
  94. package/source/HTTP/exceptions.ts +77 -0
  95. package/source/HTTP/formats/index.ts +19 -0
  96. package/source/HTTP/formats/json.ts +13 -0
  97. package/source/HTTP/formats/msgpack.ts +10 -0
  98. package/source/HTTP/formats/text.ts +9 -0
  99. package/source/HTTP/formats/yaml.ts +14 -0
  100. package/source/HTTP/index.ts +3 -0
  101. package/source/HTTP/messages.test.ts +116 -0
  102. package/source/HTTP/messages.ts +89 -0
  103. package/source/Mapping.ts +51 -0
  104. package/source/Query.test.ts +37 -0
  105. package/source/Query.ts +105 -0
  106. package/source/RTD/Context.ts +16 -0
  107. package/source/RTD/Directives.ts +9 -0
  108. package/source/RTD/Endpoint.ts +11 -0
  109. package/source/RTD/Match.ts +16 -0
  110. package/source/RTD/Method.ts +24 -0
  111. package/source/RTD/Node.ts +85 -0
  112. package/source/RTD/Route.ts +59 -0
  113. package/source/RTD/Tree.ts +54 -0
  114. package/source/RTD/factory.ts +47 -0
  115. package/source/RTD/index.ts +8 -0
  116. package/source/RTD/segment.test.ts +32 -0
  117. package/source/RTD/segment.ts +25 -0
  118. package/source/RTD/syntax/index.ts +2 -0
  119. package/source/RTD/syntax/parse.test.ts +188 -0
  120. package/source/RTD/syntax/parse.ts +153 -0
  121. package/source/RTD/syntax/types.ts +48 -0
  122. package/source/Remotes.test.ts +42 -0
  123. package/source/Remotes.ts +22 -0
  124. package/source/Tenant.ts +38 -0
  125. package/source/deployment.ts +49 -0
  126. package/source/directives/auth/Anonymous.ts +14 -0
  127. package/source/directives/auth/Echo.ts +12 -0
  128. package/source/directives/auth/Family.ts +145 -0
  129. package/source/directives/auth/Id.ts +19 -0
  130. package/source/directives/auth/Incept.ts +42 -0
  131. package/source/directives/auth/Role.test.ts +62 -0
  132. package/source/directives/auth/Role.ts +56 -0
  133. package/source/directives/auth/Rule.ts +28 -0
  134. package/source/directives/auth/Scheme.ts +26 -0
  135. package/source/directives/auth/index.ts +3 -0
  136. package/source/directives/auth/schemes.ts +8 -0
  137. package/source/directives/auth/split.ts +15 -0
  138. package/source/directives/auth/types.ts +37 -0
  139. package/source/directives/dev/Family.ts +36 -0
  140. package/source/directives/dev/Stub.ts +14 -0
  141. package/source/directives/dev/Throw.ts +14 -0
  142. package/source/directives/dev/index.ts +3 -0
  143. package/source/directives/dev/types.ts +5 -0
  144. package/source/directives/index.ts +5 -0
  145. package/source/discovery.ts +1 -0
  146. package/source/exceptions.ts +17 -0
  147. package/source/index.test.ts +9 -0
  148. package/source/index.ts +6 -0
  149. package/source/manifest.test.ts +59 -0
  150. package/source/manifest.ts +48 -0
  151. package/source/root.ts +38 -0
  152. package/source/schemas.ts +9 -0
  153. package/tsconfig.json +12 -0
  154. package/src/.manifest/index.js +0 -7
  155. package/src/.manifest/normalize.js +0 -58
  156. package/src/.manifest/schema.yaml +0 -71
  157. package/src/.manifest/validate.js +0 -17
  158. package/src/constants.js +0 -3
  159. package/src/deployment.js +0 -23
  160. package/src/exposition.js +0 -68
  161. package/src/factory.js +0 -76
  162. package/src/index.js +0 -9
  163. package/src/manifest.js +0 -12
  164. package/src/query/criteria.js +0 -55
  165. package/src/query/enum.js +0 -35
  166. package/src/query/index.js +0 -17
  167. package/src/query/query.js +0 -60
  168. package/src/query/range.js +0 -28
  169. package/src/query/sort.js +0 -19
  170. package/src/remote.js +0 -88
  171. package/src/server.js +0 -83
  172. package/src/tenant.js +0 -29
  173. package/src/translate/etag.js +0 -14
  174. package/src/translate/index.js +0 -7
  175. package/src/translate/request.js +0 -68
  176. package/src/translate/response.js +0 -62
  177. package/src/tree.js +0 -109
  178. package/test/manifest.normalize.fixtures.js +0 -37
  179. package/test/manifest.normalize.test.js +0 -37
  180. package/test/manifest.validate.test.js +0 -40
  181. package/test/query.range.test.js +0 -18
  182. package/test/tree.fixtures.js +0 -21
  183. package/test/tree.test.js +0 -44
  184. package/types/annotations.d.ts +0 -10
  185. package/types/declarations.d.ts +0 -31
  186. package/types/exposition.d.ts +0 -13
  187. package/types/http.d.ts +0 -13
  188. package/types/query.d.ts +0 -16
  189. package/types/remote.d.ts +0 -19
  190. package/types/server.d.ts +0 -13
  191. package/types/tree.d.ts +0 -33
@@ -0,0 +1,59 @@
1
+ import { type Manifest } from '@toa.io/norm'
2
+ import { generate } from 'randomstring'
3
+ import { manifest } from './manifest'
4
+
5
+ const name = 'cm-' + generate()
6
+ const namespace = 'ns' + generate()
7
+
8
+ let mf: Manifest
9
+
10
+ const operations = { observe: {} }
11
+
12
+ beforeEach(() => {
13
+ mf = { namespace, name, operations } as unknown as Manifest
14
+ })
15
+
16
+ const declaration = {
17
+ '/': { GET: 'observe' }
18
+ }
19
+
20
+ it('should create branch', async () => {
21
+ const node = manifest(declaration, mf)
22
+
23
+ expect(node).toBeDefined()
24
+
25
+ // namespace route
26
+ expect(node.routes).toHaveLength(1)
27
+ expect(node.routes[0].path).toBe('/' + namespace)
28
+
29
+ const ns = node.routes[0].node
30
+
31
+ // component route
32
+ expect(ns.routes).toHaveLength(1)
33
+ expect(ns.routes[0].path).toBe('/' + name)
34
+ })
35
+
36
+ it('should not create node for default namespace', async () => {
37
+ mf.namespace = 'default'
38
+
39
+ const node = manifest(declaration, mf)
40
+
41
+ expect(node.routes).toHaveLength(1)
42
+ expect(node.routes[0].path).toBe('/' + name)
43
+ })
44
+
45
+ it('should throw on invalid declaration type', async () => {
46
+ expect(() => manifest('hello' as unknown as object, mf)).toThrow('RTD parse error')
47
+ })
48
+
49
+ it('should set namespace and component', async () => {
50
+ const node = manifest(declaration, mf)
51
+
52
+ const ns = node.routes[0].node
53
+ const cm = ns.routes[0].node
54
+ const root = cm.routes[0].node
55
+ const GET = root.methods[0]
56
+
57
+ expect(GET.mapping?.namespace).toBe(namespace)
58
+ expect(GET.mapping?.component).toBe(name)
59
+ })
@@ -0,0 +1,48 @@
1
+ import { parse, type Node, type Method, type Query } from './RTD/syntax'
2
+ import { shortcuts } from './Directive'
3
+ import * as schemas from './schemas'
4
+ import type { Manifest } from '@toa.io/norm'
5
+
6
+ export function manifest (declaration: object, manifest: Manifest): Node {
7
+ declaration = wrap(manifest.name, declaration)
8
+
9
+ if (manifest.namespace !== undefined && manifest.namespace !== 'default')
10
+ declaration = wrap(manifest.namespace, declaration)
11
+
12
+ const node = parse(declaration, shortcuts)
13
+
14
+ concretize(node, manifest)
15
+
16
+ schemas.node.validate(node)
17
+
18
+ return node
19
+ }
20
+
21
+ function wrap (segment: string, declaration: object): object {
22
+ return { ['/' + segment]: { protected: true, ...declaration } }
23
+ }
24
+
25
+ function concretize (node: Node, manifest: Manifest): void {
26
+ for (const route of node.routes) {
27
+ for (const method of route.node.methods)
28
+ concretizeMethod(method, manifest)
29
+
30
+ concretize(route.node, manifest)
31
+ }
32
+ }
33
+
34
+ function concretizeMethod (method: Method, manifest: Manifest): void {
35
+ if (method.mapping === undefined)
36
+ return
37
+
38
+ const operation = manifest.operations[method.mapping.endpoint]
39
+
40
+ if (operation === undefined)
41
+ throw new Error(`Operation '${method.mapping.endpoint}' not found`)
42
+
43
+ if (method.mapping.query === undefined && operation.query !== false)
44
+ method.mapping.query = {} as unknown as Query // schema will substitute default values
45
+
46
+ method.mapping.namespace = manifest.namespace
47
+ method.mapping.component = manifest.name
48
+ }
package/source/root.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { decode, merge } from '@toa.io/generic'
2
+ import { syntax } from './RTD'
3
+
4
+ export function resolve (): syntax.Node {
5
+ const value = process.env.TOA_EXPOSITION
6
+ const root = value !== undefined ? decode<syntax.Node>(value) : syntax.createNode()
7
+
8
+ merge(root, PREDEFINED)
9
+
10
+ return root
11
+ }
12
+
13
+ const PREDEFINED: syntax.Node = {
14
+ routes: [
15
+ {
16
+ path: '/identity',
17
+ node: {
18
+ isolated: true,
19
+ routes: [],
20
+ methods: [
21
+ {
22
+ verb: 'GET',
23
+ directives: [
24
+ {
25
+ family: 'auth',
26
+ name: 'echo',
27
+ value: null
28
+ }
29
+ ]
30
+ }
31
+ ],
32
+ directives: []
33
+ }
34
+ }
35
+ ],
36
+ methods: [],
37
+ directives: []
38
+ }
@@ -0,0 +1,9 @@
1
+ import { resolve } from 'node:path'
2
+ import schemas from '@toa.io/schemas'
3
+
4
+ const path = resolve(__dirname, '../schemas')
5
+ const namespace = schemas.namespace(path)
6
+
7
+ export const querystring = namespace.schema('querystring')
8
+ export const annotaion = namespace.schema('annotation')
9
+ export const node = namespace.schema('node')
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./transpiled"
5
+ },
6
+ "include": [
7
+ "source"
8
+ ],
9
+ "exclude": [
10
+ "**/*.test.ts"
11
+ ]
12
+ }
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- const { normalize } = require('./normalize')
4
- const { validate } = require('./validate')
5
-
6
- exports.normalize = normalize
7
- exports.validate = validate
@@ -1,58 +0,0 @@
1
- 'use strict'
2
-
3
- /**
4
- * @returns {toa.extensions.exposition.declarations.Node}
5
- */
6
- const normalize = (node, manifest) => {
7
- if (node instanceof Array) node = { operations: node }
8
-
9
- node.operations = operations(node.operations, manifest)
10
- node.query = query(node.query)
11
-
12
- for (const [key, value] of Object.entries(node)) {
13
- if (key.substring(0, 1) === '/') node[key] = normalize(value, manifest)
14
- }
15
-
16
- return node
17
- }
18
-
19
- /**
20
- * @returns {toa.extensions.exposition.declarations.Operation[] | undefined}
21
- */
22
- const operations = (operations, manifest) => {
23
- if (operations === undefined) return
24
-
25
- return operations.map((operation) => {
26
- if (typeof operation === 'object') operation = operation.operation
27
-
28
- if (manifest.operations[operation] === undefined) {
29
- throw new Error(`Resource references undefined operation '${operation}'`)
30
- }
31
-
32
- const { type, scope, query } = manifest.operations[operation]
33
- const normal = { operation, type, scope }
34
-
35
- if (query !== undefined) normal.query = query
36
-
37
- return normal
38
- })
39
- }
40
-
41
- /**
42
- * @returns {toa.extensions.exposition.declarations.Query | undefined}
43
- */
44
- const query = (query) => {
45
- if (query === undefined) return
46
-
47
- if (query.omit !== undefined && typeof query.omit !== 'object') {
48
- query.omit = { value: query.omit, range: [] }
49
- }
50
-
51
- if (query.limit !== undefined && typeof query.limit !== 'object') {
52
- query.limit = { value: query.limit, range: [] }
53
- }
54
-
55
- return query
56
- }
57
-
58
- exports.normalize = normalize
@@ -1,71 +0,0 @@
1
- $schema: https://json-schema.org/draft/2019-09/schema
2
- $id: https://schemas.toa.io/0.0.0/rtd
3
-
4
- definitions:
5
- resource:
6
- type: 'object'
7
- patternProperties:
8
- ^(\/([^\/#\?]+)?)+\/?$:
9
- $ref: "#/definitions/resource"
10
- properties:
11
- query:
12
- type: object
13
- properties:
14
- criteria:
15
- nullable: true
16
- type: string
17
- minLength: 1
18
- sort:
19
- type: array
20
- uniqueItems: true
21
- minItems: 1
22
- items:
23
- type: string
24
- projection:
25
- type: array
26
- uniqueItems: true
27
- minItems: 1
28
- items:
29
- type: string
30
- omit:
31
- $ref: "#/definitions/range"
32
- limit:
33
- $ref: "#/definitions/range"
34
- additionalProperties: false
35
- operations:
36
- type: array
37
- uniqueItems: true
38
- minItems: 1
39
- items:
40
- type: object
41
- properties:
42
- operation:
43
- $ref: definitions#/definitions/token
44
- type:
45
- enum: [ transition, observation, assignment, computation, effect ]
46
- scope:
47
- type: string
48
- enum: [ object, objects, changeset, none ]
49
- query:
50
- type: boolean
51
- additionalProperties: false
52
- additionalProperties: false
53
- range:
54
- type: object
55
- properties:
56
- value:
57
- type: integer
58
- minimum: 0
59
- range:
60
- type: array
61
- uniqueItems: true
62
- minItems: 0
63
- items:
64
- $ref: "#/definitions/range/properties/value"
65
- additionalProperties: false
66
- required: [ range ]
67
-
68
- $ref: "#/definitions/resource"
69
- not:
70
- type: object
71
- required: [ operations ] # root doesn't have path
@@ -1,17 +0,0 @@
1
- 'use strict'
2
-
3
- const path = require('path')
4
-
5
- const { Schema } = require('@toa.io/schema')
6
- const { load } = require('@toa.io/yaml')
7
-
8
- const schema = load.sync(path.resolve(__dirname, 'schema.yaml'))
9
- const validator = new Schema(schema)
10
-
11
- const validate = (declaration) => {
12
- const error = validator.fit(declaration)
13
-
14
- if (error) throw new Error(error.message)
15
- }
16
-
17
- exports.validate = validate
package/src/constants.js DELETED
@@ -1,3 +0,0 @@
1
- 'use strict'
2
-
3
- exports.PORT = 8000
package/src/deployment.js DELETED
@@ -1,23 +0,0 @@
1
- 'use strict'
2
-
3
- const { PORT } = require('./constants')
4
-
5
- /**
6
- * @param {toa.norm.context.dependencies.Instance[]} components
7
- * @param {toa.extensions.exposition.Annotations} annotations
8
- * @type {toa.deployment.dependency.Constructor}
9
- */
10
- const deployment = (components, annotations) => {
11
- const group = 'exposition'
12
- const name = 'resources'
13
- const version = require('../package.json').version
14
- const port = PORT
15
- const ingress = annotations
16
-
17
- /** @type {toa.deployment.dependency.Service} */
18
- const exposition = { group, name, version, port, ingress }
19
-
20
- return { services: [exposition] }
21
- }
22
-
23
- exports.deployment = deployment
package/src/exposition.js DELETED
@@ -1,68 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
- const { console } = require('@toa.io/console')
5
-
6
- class Exposition extends Connector {
7
- /** @type {toa.core.bindings.Broadcast} */
8
- #broadcast
9
-
10
- /** @type {toa.extensions.exposition.remotes.Factory} */
11
- #remote
12
-
13
- /** @type {toa.extensions.exposition.exposition.Remotes} */
14
- #remotes = {}
15
-
16
- /**
17
- * @param {toa.core.bindings.Broadcast} broadcast
18
- * @param {toa.extensions.exposition.remotes.Factory} connect
19
- */
20
- constructor (broadcast, connect) {
21
- super()
22
-
23
- this.#broadcast = broadcast
24
- this.#remote = connect
25
-
26
- this.depends(broadcast)
27
- }
28
-
29
- /** @override */
30
- async open () {
31
- await this.#broadcast.receive('expose', this.#expose.bind(this))
32
- this.#broadcast.transmit('ping', {}).then()
33
-
34
- console.info(this.constructor.name + ' started')
35
- }
36
-
37
- /**
38
- * @param {toa.extensions.exposition.declarations.Exposition} declaration
39
- * @returns {Promise<void>}
40
- */
41
- async #expose (declaration) {
42
- const { namespace, name, resources } = declaration
43
- const key = namespace + '/' + name
44
-
45
- if (this.#remotes[key] === undefined) this.#remotes[key] = this.#connect(namespace, name)
46
-
47
- const remote = await this.#remotes[key]
48
-
49
- remote.update(resources)
50
- }
51
-
52
- /**
53
- * @param {string} namespace
54
- * @param {string} name
55
- * @returns {Promise<toa.extensions.exposition.Remote>}
56
- */
57
- async #connect (namespace, name) {
58
- const remote = await this.#remote(namespace, name)
59
-
60
- await remote.connect()
61
-
62
- this.depends(remote)
63
-
64
- return remote
65
- }
66
- }
67
-
68
- exports.Exposition = Exposition
package/src/factory.js DELETED
@@ -1,76 +0,0 @@
1
- 'use strict'
2
-
3
- const { Locator } = require('@toa.io/core')
4
- const { remap } = require('@toa.io/generic')
5
-
6
- const { Tenant } = require('./tenant')
7
- const { Exposition } = require('./exposition')
8
- const { Server } = require('./server')
9
- const { Remote } = require('./remote')
10
- const { Tree } = require('./tree')
11
- const { Query, constraints } = require('./query')
12
-
13
- /**
14
- * @implements {toa.core.extensions.Factory}
15
- */
16
- class Factory {
17
- #boot
18
-
19
- /** @type {toa.extensions.exposition.Server} */
20
- #server
21
-
22
- constructor (boot) {
23
- this.#boot = boot
24
- this.#server = new Server()
25
- }
26
-
27
- tenant (locator, declaration) {
28
- const broadcast = this.#boot.bindings.broadcast(BINDING, NAME, locator.id)
29
-
30
- return new Tenant(broadcast, locator, declaration)
31
- }
32
-
33
- service (name) {
34
- if (name === undefined || name === 'default' || name === 'resources') return this.#expose()
35
- }
36
-
37
- #expose () {
38
- const broadcast = this.#boot.bindings.broadcast(BINDING, NAME)
39
- const connect = this.#connect.bind(this)
40
- const exposition = new Exposition(broadcast, connect)
41
-
42
- exposition.depends(this.#server)
43
-
44
- return exposition
45
- }
46
-
47
- /**
48
- * @param {string} namespace
49
- * @param {string} name
50
- * @returns {Promise<toa.extensions.exposition.Remote>}
51
- */
52
- async #connect (namespace, name) {
53
- const locator = new Locator(name, namespace)
54
- const remote = await this.#boot.remote(locator)
55
- const query = this.#query.bind(this)
56
- const tree = new Tree(query)
57
-
58
- return new Remote(this.#server, remote, tree)
59
- }
60
-
61
- /**
62
- * @param {toa.extensions.exposition.declarations.Node | any} node
63
- * @returns {toa.extensions.exposition.Query}
64
- */
65
- #query (node) {
66
- const query = Query.merge(node)
67
- const properties = remap(query, (value, key) => new constraints[key](value))
68
-
69
- return new Query(properties)
70
- }
71
- }
72
-
73
- const BINDING = '@toa.io/bindings.amqp'
74
- const NAME = 'exposition'
75
-
76
- exports.Factory = Factory
package/src/index.js DELETED
@@ -1,9 +0,0 @@
1
- 'use strict'
2
-
3
- const { Factory } = require('./factory')
4
- const { deployment } = require('./deployment')
5
- const { manifest } = require('./manifest')
6
-
7
- exports.Factory = Factory
8
- exports.deployment = deployment
9
- exports.manifest = manifest
package/src/manifest.js DELETED
@@ -1,12 +0,0 @@
1
- 'use strict'
2
-
3
- const { normalize, validate } = require('./.manifest')
4
-
5
- const manifest = (node, manifest) => {
6
- normalize(node, manifest)
7
- validate(node)
8
-
9
- return node
10
- }
11
-
12
- exports.manifest = manifest
@@ -1,55 +0,0 @@
1
- 'use strict'
2
-
3
- const { exceptions: { RequestConflictException } } = require('@toa.io/core')
4
-
5
- class Criteria {
6
- #value
7
- #open
8
- #logic
9
- #right
10
-
11
- constructor (value) {
12
- if (value === null) return
13
-
14
- const last = value.slice(-1)
15
-
16
- if (last === ',' || last === ';') {
17
- this.#open = true
18
- this.#right = true
19
- this.#logic = last
20
-
21
- value = value.substring(0, value.length - 1)
22
- } else {
23
- const first = value.substring(0, 1)
24
-
25
- this.#open = first === ',' || first === ';'
26
-
27
- if (this.#open === true) {
28
- this.#right = false
29
- this.#logic = first
30
-
31
- value = value.substring(1)
32
- }
33
- }
34
-
35
- this.#value = value
36
- }
37
-
38
- /** @hot */
39
- parse (value, operation) {
40
- if (operation.query === false) return value
41
-
42
- if (value !== undefined) {
43
- if (this.#open === true) {
44
- if (this.#right) value = this.#value + this.#logic + value
45
- else value = value + this.#logic + this.#value
46
- } else {
47
- throw new RequestConflictException('Query criteria is defined as closed')
48
- }
49
- } else value = this.#value
50
-
51
- return value
52
- }
53
- }
54
-
55
- exports.Criteria = Criteria
package/src/query/enum.js DELETED
@@ -1,35 +0,0 @@
1
- 'use strict'
2
-
3
- const { exceptions: { RequestConflictException } } = require('@toa.io/core')
4
-
5
- class Enum {
6
- #value
7
- #keys
8
-
9
- constructor (value) {
10
- this.#value = value
11
-
12
- this.#keys = value.reduce((acc, key) => {
13
- acc[key] = true
14
- return acc
15
- }, {})
16
- }
17
-
18
- /** @hot */
19
- parse (value, operation) {
20
- if (operation.type !== 'observation') return value
21
-
22
- if (value === undefined) return this.#value
23
- else if (value instanceof Array) {
24
- const key = value.find((key) => !(key in this.#keys))
25
-
26
- if (key !== undefined) {
27
- throw new RequestConflictException(`Query projection must not contain '${key}'`)
28
- }
29
- }
30
-
31
- return value
32
- }
33
- }
34
-
35
- exports.Enum = Enum
@@ -1,17 +0,0 @@
1
- 'use strict'
2
-
3
- const { Query } = require('./query')
4
- const { Range } = require('./range')
5
- const { Criteria } = require('./criteria')
6
- const { Enum } = require('./enum')
7
- const { Sort } = require('./sort')
8
-
9
- exports.Query = Query
10
-
11
- exports.constraints = {
12
- criteria: Criteria,
13
- sort: Sort,
14
- omit: Range,
15
- limit: Range,
16
- projection: Enum
17
- }
@@ -1,60 +0,0 @@
1
- 'use strict'
2
-
3
- const { merge } = require('@toa.io/generic')
4
-
5
- /**
6
- * @implements {toa.extensions.exposition.Query}
7
- */
8
- class Query {
9
- #constraints
10
-
11
- constructor (constraints) {
12
- this.#constraints = Object.entries(constraints)
13
- }
14
-
15
- /** @hot */
16
- parse (query, operation) {
17
- for (const [key, constraint] of this.#constraints) {
18
- const value = constraint.parse(query?.[key], operation)
19
-
20
- if (value !== undefined) {
21
- if (query === undefined) query = {}
22
-
23
- query[key] = value
24
- }
25
- }
26
-
27
- return query
28
- }
29
-
30
- /**
31
- * @param {toa.extensions.exposition.declarations.Node} node
32
- * @returns {toa.extensions.exposition.declarations.Query}
33
- */
34
- static merge (node) {
35
- const query = {}
36
- let current = node
37
-
38
- do {
39
- if (current.query !== undefined) merge(query, current.query, { ignore: true })
40
-
41
- current = current.parent
42
- } while (current !== undefined)
43
-
44
- merge(query, DEFAULTS, { ignore: true })
45
-
46
- return query
47
- }
48
- }
49
-
50
- const DEFAULTS = {
51
- omit: {
52
- range: [0, 1000]
53
- },
54
- limit: {
55
- value: 100,
56
- range: [1, 100]
57
- }
58
- }
59
-
60
- exports.Query = Query