@toa.io/extensions.exposition 0.20.0-dev.9 → 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.
- package/components/context.toa.yaml +15 -0
- package/components/identity.bans/manifest.toa.yaml +18 -0
- package/components/identity.basic/events/principal.js +9 -0
- package/components/identity.basic/manifest.toa.yaml +50 -0
- package/components/identity.basic/source/authenticate.ts +29 -0
- package/components/identity.basic/source/create.ts +19 -0
- package/components/identity.basic/source/transit.ts +64 -0
- package/components/identity.basic/source/types.ts +42 -0
- package/components/identity.basic/tsconfig.json +9 -0
- package/components/identity.roles/manifest.toa.yaml +31 -0
- package/components/identity.roles/source/list.ts +7 -0
- package/components/identity.roles/source/principal.ts +20 -0
- package/components/identity.roles/tsconfig.json +9 -0
- package/components/identity.tokens/manifest.toa.yaml +39 -0
- package/components/identity.tokens/receivers/identity.bans.updated.js +3 -0
- package/components/identity.tokens/source/authenticate.test.ts +56 -0
- package/components/identity.tokens/source/authenticate.ts +38 -0
- package/components/identity.tokens/source/decrypt.test.ts +59 -0
- package/components/identity.tokens/source/decrypt.ts +25 -0
- package/components/identity.tokens/source/encrypt.test.ts +35 -0
- package/components/identity.tokens/source/encrypt.ts +25 -0
- package/components/identity.tokens/source/revoke.ts +5 -0
- package/components/identity.tokens/source/types.ts +48 -0
- package/components/identity.tokens/tsconfig.json +9 -0
- package/cucumber.js +9 -0
- package/documentation/.assets/ia3-dark.jpg +0 -0
- package/documentation/.assets/ia3-light.jpg +0 -0
- package/documentation/.assets/overview-dark.jpg +0 -0
- package/documentation/.assets/overview-light.jpg +0 -0
- package/documentation/.assets/role-scopes-dark.jpg +0 -0
- package/documentation/.assets/role-scopes-light.jpg +0 -0
- package/documentation/.assets/rtd-dark.jpg +0 -0
- package/documentation/.assets/rtd-light.jpg +0 -0
- package/documentation/access.md +256 -0
- package/documentation/components.md +276 -0
- package/documentation/identity.md +156 -0
- package/documentation/notes/sse.md +71 -0
- package/documentation/protocol.md +18 -0
- package/documentation/query.md +226 -0
- package/documentation/tree.md +169 -0
- package/features/access.feature +448 -0
- package/features/annotation.feature +30 -0
- package/features/body.feature +45 -0
- package/features/directives.feature +56 -0
- package/features/dynamic.feature +99 -0
- package/features/errors.feature +193 -0
- package/features/identity.basic.feature +276 -0
- package/features/identity.feature +61 -0
- package/features/identity.roles.feature +51 -0
- package/features/identity.tokens.feature +119 -0
- package/features/queries.feature +214 -0
- package/features/routes.feature +49 -0
- package/features/steps/Common.ts +10 -0
- package/features/steps/Components.ts +43 -0
- package/features/steps/Database.ts +58 -0
- package/features/steps/Gateway.ts +113 -0
- package/features/steps/HTTP.ts +71 -0
- package/features/steps/Parameters.ts +12 -0
- package/features/steps/Workspace.ts +40 -0
- package/features/steps/components/echo/manifest.toa.yaml +9 -0
- package/features/steps/components/echo/operations/affect.js +7 -0
- package/features/steps/components/echo/operations/compute.js +7 -0
- package/features/steps/components/greeter/manifest.toa.yaml +5 -0
- package/features/steps/components/greeter/operations/greet.js +7 -0
- package/features/steps/components/pots/manifest.toa.yaml +20 -0
- package/features/steps/components/sequences/manifest.toa.yaml +10 -0
- package/features/steps/components/sequences/operations/numbers.js +7 -0
- package/features/steps/components/sequences/operations/tokens.js +16 -0
- package/features/steps/components/users/manifest.toa.yaml +11 -0
- package/features/steps/tsconfig.json +9 -0
- package/features/streams.feature +26 -0
- package/package.json +32 -17
- package/readme.md +183 -0
- package/schemas/annotation.cos.yaml +5 -0
- package/schemas/directive.cos.yaml +3 -0
- package/schemas/method.cos.yaml +8 -0
- package/schemas/node.cos.yaml +5 -0
- package/schemas/query.cos.yaml +17 -0
- package/schemas/querystring.cos.yaml +5 -0
- package/schemas/range.cos.yaml +2 -0
- package/schemas/route.cos.yaml +2 -0
- package/source/Annotation.ts +7 -0
- package/source/Branch.ts +8 -0
- package/source/Composition.ts +57 -0
- package/source/Context.ts +6 -0
- package/source/Directive.test.ts +91 -0
- package/source/Directive.ts +120 -0
- package/source/Endpoint.ts +59 -0
- package/source/Factory.ts +51 -0
- package/source/Gateway.ts +93 -0
- package/source/HTTP/Server.fixtures.ts +45 -0
- package/source/HTTP/Server.test.ts +221 -0
- package/source/HTTP/Server.ts +135 -0
- package/source/HTTP/exceptions.ts +77 -0
- package/source/HTTP/formats/index.ts +19 -0
- package/source/HTTP/formats/json.ts +13 -0
- package/source/HTTP/formats/msgpack.ts +10 -0
- package/source/HTTP/formats/text.ts +9 -0
- package/source/HTTP/formats/yaml.ts +14 -0
- package/source/HTTP/index.ts +3 -0
- package/source/HTTP/messages.test.ts +116 -0
- package/source/HTTP/messages.ts +89 -0
- package/source/Mapping.ts +51 -0
- package/source/Query.test.ts +37 -0
- package/source/Query.ts +105 -0
- package/source/RTD/Context.ts +16 -0
- package/source/RTD/Directives.ts +9 -0
- package/source/RTD/Endpoint.ts +11 -0
- package/source/RTD/Match.ts +16 -0
- package/source/RTD/Method.ts +24 -0
- package/source/RTD/Node.ts +85 -0
- package/source/RTD/Route.ts +59 -0
- package/source/RTD/Tree.ts +54 -0
- package/source/RTD/factory.ts +47 -0
- package/source/RTD/index.ts +8 -0
- package/source/RTD/segment.test.ts +32 -0
- package/source/RTD/segment.ts +25 -0
- package/source/RTD/syntax/index.ts +2 -0
- package/source/RTD/syntax/parse.test.ts +188 -0
- package/source/RTD/syntax/parse.ts +153 -0
- package/source/RTD/syntax/types.ts +48 -0
- package/source/Remotes.test.ts +42 -0
- package/source/Remotes.ts +22 -0
- package/source/Tenant.ts +38 -0
- package/source/deployment.ts +49 -0
- package/source/directives/auth/Anonymous.ts +14 -0
- package/source/directives/auth/Echo.ts +12 -0
- package/source/directives/auth/Family.ts +145 -0
- package/source/directives/auth/Id.ts +19 -0
- package/source/directives/auth/Incept.ts +42 -0
- package/source/directives/auth/Role.test.ts +62 -0
- package/source/directives/auth/Role.ts +56 -0
- package/source/directives/auth/Rule.ts +28 -0
- package/source/directives/auth/Scheme.ts +26 -0
- package/source/directives/auth/index.ts +3 -0
- package/source/directives/auth/schemes.ts +8 -0
- package/source/directives/auth/split.ts +15 -0
- package/source/directives/auth/types.ts +37 -0
- package/source/directives/dev/Family.ts +36 -0
- package/source/directives/dev/Stub.ts +14 -0
- package/source/directives/dev/Throw.ts +14 -0
- package/source/directives/dev/index.ts +3 -0
- package/source/directives/dev/types.ts +5 -0
- package/source/directives/index.ts +5 -0
- package/source/discovery.ts +1 -0
- package/source/exceptions.ts +17 -0
- package/source/index.test.ts +9 -0
- package/source/index.ts +6 -0
- package/source/manifest.test.ts +59 -0
- package/source/manifest.ts +48 -0
- package/source/root.ts +38 -0
- package/source/schemas.ts +9 -0
- package/tsconfig.json +12 -0
- package/src/.manifest/index.js +0 -7
- package/src/.manifest/normalize.js +0 -58
- package/src/.manifest/schema.yaml +0 -71
- package/src/.manifest/validate.js +0 -17
- package/src/constants.js +0 -3
- package/src/deployment.js +0 -23
- package/src/exposition.js +0 -68
- package/src/factory.js +0 -76
- package/src/index.js +0 -9
- package/src/manifest.js +0 -12
- package/src/query/criteria.js +0 -55
- package/src/query/enum.js +0 -35
- package/src/query/index.js +0 -17
- package/src/query/query.js +0 -60
- package/src/query/range.js +0 -28
- package/src/query/sort.js +0 -19
- package/src/remote.js +0 -88
- package/src/server.js +0 -83
- package/src/tenant.js +0 -29
- package/src/translate/etag.js +0 -14
- package/src/translate/index.js +0 -7
- package/src/translate/request.js +0 -68
- package/src/translate/response.js +0 -62
- package/src/tree.js +0 -109
- package/test/manifest.normalize.fixtures.js +0 -37
- package/test/manifest.normalize.test.js +0 -37
- package/test/manifest.validate.test.js +0 -40
- package/test/query.range.test.js +0 -18
- package/test/tree.fixtures.js +0 -21
- package/test/tree.test.js +0 -44
- package/types/annotations.d.ts +0 -10
- package/types/declarations.d.ts +0 -31
- package/types/exposition.d.ts +0 -13
- package/types/http.d.ts +0 -13
- package/types/query.d.ts +0 -16
- package/types/remote.d.ts +0 -19
- package/types/server.d.ts +0 -13
- 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
package/src/.manifest/index.js
DELETED
|
@@ -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
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
package/src/manifest.js
DELETED
package/src/query/criteria.js
DELETED
|
@@ -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
|
package/src/query/index.js
DELETED
|
@@ -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
|
-
}
|
package/src/query/query.js
DELETED
|
@@ -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
|