@toa.io/extensions.origins 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/package.json +17 -11
- package/readme.md +70 -67
- package/schemas/annotation.cos.yaml +3 -0
- package/schemas/manifest.cos.yaml +4 -0
- package/source/Factory.ts +88 -0
- package/source/annotation.test.ts +150 -0
- package/source/annotation.ts +83 -0
- package/source/extension.test.ts +161 -0
- package/source/extension.ts +60 -0
- package/source/index.ts +2 -0
- package/source/manifest.test.ts +30 -0
- package/source/manifest.ts +11 -0
- package/source/protocols/amqp/.test/aspect.fixtures.js +1 -1
- package/source/protocols/amqp/.test/mock.comq.js +2 -2
- package/source/protocols/amqp/aspect.js +17 -24
- package/source/protocols/amqp/deployment.js +8 -2
- package/source/protocols/http/.aspect/permissions.js +13 -10
- package/source/protocols/http/aspect.js +16 -37
- package/source/protocols/index.ts +16 -0
- package/tsconfig.json +12 -0
- package/source/.credentials.js +0 -14
- package/source/.deployment/index.js +0 -5
- package/source/.deployment/uris.js +0 -37
- package/source/.test/constants.js +0 -3
- package/source/.test/deployment.fixtures.js +0 -20
- package/source/.test/factory.fixtures.js +0 -13
- package/source/deployment.js +0 -41
- package/source/deployment.test.js +0 -185
- package/source/factory.js +0 -44
- package/source/factory.test.js +0 -140
- package/source/index.js +0 -9
- package/source/manifest.js +0 -41
- package/source/manifest.test.js +0 -82
- package/source/protocols/amqp/aspect.test.js +0 -119
- package/source/protocols/http/.aspect/permissions.test.js +0 -23
- package/source/protocols/http/aspect.test.js +0 -220
- package/source/protocols/index.js +0 -6
- package/source/schemas/annotations.cos.yaml +0 -1
- package/source/schemas/index.js +0 -8
- package/source/schemas/manifest.cos.yaml +0 -2
- package/types/amqp.d.ts +0 -9
- package/types/deployment.d.ts +0 -7
- package/types/http.d.ts +0 -28
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { generate } from 'randomstring'
|
|
2
|
+
import { encode } from 'msgpackr'
|
|
3
|
+
import { Locator } from '@toa.io/core'
|
|
4
|
+
import { deployment, type Instance } from './extension'
|
|
5
|
+
import type { Annotation, Properties } from './annotation'
|
|
6
|
+
import type { Manifest } from './manifest'
|
|
7
|
+
import type { Dependency } from '@toa.io/operations'
|
|
8
|
+
|
|
9
|
+
const locator = new Locator(generate(), generate())
|
|
10
|
+
const NAMESPACE = locator.namespace.toUpperCase()
|
|
11
|
+
const NAME = locator.name.toUpperCase()
|
|
12
|
+
|
|
13
|
+
it('should deploy pointer variables', async () => {
|
|
14
|
+
const manifest: Manifest = { queue: null }
|
|
15
|
+
const instance = { locator, manifest } as unknown as Instance
|
|
16
|
+
const url = 'amqp://host-' + generate()
|
|
17
|
+
|
|
18
|
+
const annotation: Annotation = {
|
|
19
|
+
[locator.id]: {
|
|
20
|
+
queue: url
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const deploy = deployment([instance], annotation)
|
|
25
|
+
|
|
26
|
+
const expected: Dependency = {
|
|
27
|
+
variables: {
|
|
28
|
+
[locator.label]: expect.arrayContaining([
|
|
29
|
+
{
|
|
30
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}_QUEUE`,
|
|
31
|
+
value: url
|
|
32
|
+
}
|
|
33
|
+
])
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
expect(deploy)
|
|
38
|
+
.toMatchObject(expected)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should deploy default origin', async () => {
|
|
42
|
+
const example = 'http://api.example.com'
|
|
43
|
+
const manifest: Manifest = { example }
|
|
44
|
+
const instance = { locator, manifest } as unknown as Instance
|
|
45
|
+
const annotation: Annotation = {}
|
|
46
|
+
const deploy = deployment([instance], annotation)
|
|
47
|
+
|
|
48
|
+
const expected: Dependency = {
|
|
49
|
+
variables: {
|
|
50
|
+
[locator.label]: expect.arrayContaining([
|
|
51
|
+
{
|
|
52
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}_EXAMPLE`,
|
|
53
|
+
value: example
|
|
54
|
+
}
|
|
55
|
+
])
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expect(deploy)
|
|
60
|
+
.toMatchObject(expected)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('should deploy properties', async () => {
|
|
64
|
+
const manifest: Manifest = {}
|
|
65
|
+
const instance = { locator, manifest } as unknown as Instance
|
|
66
|
+
const properties: Properties = {
|
|
67
|
+
'.http': {
|
|
68
|
+
'/^http:\\/\\/\\w+api.example.com/': true
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const annotation: Annotation = {
|
|
73
|
+
[locator.id]: properties
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const deploy = deployment([instance], annotation)
|
|
77
|
+
const value = encode(properties).toString('base64')
|
|
78
|
+
|
|
79
|
+
const expected: Dependency = {
|
|
80
|
+
variables: {
|
|
81
|
+
[locator.label]: expect.arrayContaining([
|
|
82
|
+
{
|
|
83
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}__PROPERTIES`,
|
|
84
|
+
value
|
|
85
|
+
}
|
|
86
|
+
])
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
expect(deploy)
|
|
91
|
+
.toMatchObject(expected)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should deploy properties with null manifest', async () => {
|
|
95
|
+
const manifest: Manifest = null
|
|
96
|
+
const instance = { locator, manifest } as unknown as Instance
|
|
97
|
+
const properties: Properties = {
|
|
98
|
+
'.http': {
|
|
99
|
+
'/^http:\\/\\/\\w+api.example.com/': true
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const annotation: Annotation = {
|
|
104
|
+
[locator.id]: properties
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const deploy = deployment([instance], annotation)
|
|
108
|
+
const value = encode(properties).toString('base64')
|
|
109
|
+
|
|
110
|
+
const expected: Dependency = {
|
|
111
|
+
variables: {
|
|
112
|
+
[locator.label]: expect.arrayContaining([
|
|
113
|
+
{
|
|
114
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}__PROPERTIES`,
|
|
115
|
+
value
|
|
116
|
+
}
|
|
117
|
+
])
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
expect(deploy)
|
|
122
|
+
.toMatchObject(expected)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('should deploy credentials for amqp', async () => {
|
|
126
|
+
const manifest: Manifest = { queue: null }
|
|
127
|
+
const instance = { locator, manifest } as unknown as Instance
|
|
128
|
+
const url = 'amqp://host-' + generate()
|
|
129
|
+
|
|
130
|
+
const annotation: Annotation = {
|
|
131
|
+
[locator.id]: {
|
|
132
|
+
queue: url
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const deploy = deployment([instance], annotation)
|
|
137
|
+
|
|
138
|
+
const expected: Dependency = {
|
|
139
|
+
variables: {
|
|
140
|
+
[locator.label]: expect.arrayContaining([
|
|
141
|
+
{
|
|
142
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}_QUEUE_USERNAME`,
|
|
143
|
+
secret: {
|
|
144
|
+
name: `toa-origins-${locator.label}-queue`,
|
|
145
|
+
key: 'username'
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: `TOA_ORIGINS_${NAMESPACE}_${NAME}_QUEUE_PASSWORD`,
|
|
150
|
+
secret: {
|
|
151
|
+
name: `toa-origins-${locator.label}-queue`,
|
|
152
|
+
key: 'password'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
])
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
expect(deploy)
|
|
160
|
+
.toMatchObject(expected)
|
|
161
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { encode } from 'msgpackr'
|
|
2
|
+
import { createVariables, type Request } from '@toa.io/pointer'
|
|
3
|
+
import { merge } from '@toa.io/generic'
|
|
4
|
+
import { normalize, split, type Annotation, type Properties, type Origins } from './annotation'
|
|
5
|
+
import { type Manifest, validate } from './manifest'
|
|
6
|
+
import type { Locator } from '@toa.io/core'
|
|
7
|
+
import type { Dependency, Variables } from '@toa.io/operations'
|
|
8
|
+
import type { context } from '@toa.io/norm'
|
|
9
|
+
|
|
10
|
+
export function deployment (instances: Instance[], annotation: Annotation = {}): Dependency {
|
|
11
|
+
normalize(instances, annotation)
|
|
12
|
+
|
|
13
|
+
const variables: Variables = {}
|
|
14
|
+
|
|
15
|
+
for (const instance of instances) {
|
|
16
|
+
const component = annotation[instance.locator.id]
|
|
17
|
+
const { origins, properties } = split(component)
|
|
18
|
+
const instanceVariables = createInstanceVariables(instance, origins)
|
|
19
|
+
const propertiesVariable = createPropertiesVariable(instance.locator, properties)
|
|
20
|
+
|
|
21
|
+
merge(variables, instanceVariables)
|
|
22
|
+
merge(variables, propertiesVariable)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { variables }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function manifest (manifest: Manifest): Manifest {
|
|
29
|
+
validate(manifest)
|
|
30
|
+
|
|
31
|
+
return manifest
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createInstanceVariables (instance: Instance, origins: Origins): Variables {
|
|
35
|
+
if (instance.manifest === null) return {}
|
|
36
|
+
|
|
37
|
+
const label: string = instance.locator.label
|
|
38
|
+
const id = ID_PREFIX + label
|
|
39
|
+
const selectors = Object.keys(instance.manifest)
|
|
40
|
+
const request: Request = { group: label, selectors }
|
|
41
|
+
|
|
42
|
+
return createVariables(id, origins, [request])
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createPropertiesVariable (locator: Locator, properties: Properties): Variables {
|
|
46
|
+
const name = ENV_PREFIX + locator.uppercase + PROPERTIES_SUFFIX
|
|
47
|
+
const value = encode(properties).toString('base64')
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
[locator.label]: [
|
|
51
|
+
{ name, value }
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const ID_PREFIX = 'origins-'
|
|
57
|
+
export const ENV_PREFIX = 'TOA_ORIGINS_'
|
|
58
|
+
export const PROPERTIES_SUFFIX = '__PROPERTIES'
|
|
59
|
+
|
|
60
|
+
export type Instance = context.Dependency<Manifest>
|
package/source/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Manifest, validate } from './manifest'
|
|
2
|
+
|
|
3
|
+
let manifest: Manifest
|
|
4
|
+
|
|
5
|
+
it('should not throw if valid', async () => {
|
|
6
|
+
manifest = {
|
|
7
|
+
one: 'http://localhost',
|
|
8
|
+
two: null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
expect(run).not.toThrow()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('should throw if not a uri', async () => {
|
|
15
|
+
manifest = {
|
|
16
|
+
one: 'not a URI'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
expect(run).toThrow('must match format')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should not throw on null manifest', async () => {
|
|
23
|
+
manifest = null
|
|
24
|
+
|
|
25
|
+
expect(run).not.toThrow()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
function run (): void {
|
|
29
|
+
validate(manifest)
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
|
+
import * as schemas from '@toa.io/schemas'
|
|
3
|
+
|
|
4
|
+
export function validate (manifest: Manifest): void {
|
|
5
|
+
if (manifest !== null) schema.validate(manifest)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const path = resolve(__dirname, '../schemas/manifest.cos.yaml')
|
|
9
|
+
const schema = schemas.schema(path)
|
|
10
|
+
|
|
11
|
+
export type Manifest = Record<string, string | null> | null
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { generate } = require('randomstring')
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const assert = jest.fn(async () => ({
|
|
6
6
|
emit: jest.fn(async () => undefined),
|
|
7
7
|
request: jest.fn(async () => generate()),
|
|
8
8
|
reply: jest.fn(async () => undefined),
|
|
@@ -10,4 +10,4 @@ const connect = jest.fn(async () => ({
|
|
|
10
10
|
close: jest.fn(async () => undefined)
|
|
11
11
|
}))
|
|
12
12
|
|
|
13
|
-
exports.
|
|
13
|
+
exports.assert = assert
|
|
@@ -1,33 +1,26 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { assert } = require('comq')
|
|
4
4
|
const { Connector } = require('@toa.io/core')
|
|
5
|
-
const
|
|
5
|
+
const protocol = require('./index')
|
|
6
6
|
|
|
7
|
-
const { id } = require('./id')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @implements {toa.origins.amqp.Aspect}
|
|
11
|
-
*/
|
|
12
7
|
class Aspect extends Connector {
|
|
13
|
-
name = id
|
|
14
|
-
|
|
15
|
-
#
|
|
8
|
+
name = protocol.id
|
|
9
|
+
|
|
10
|
+
#resolve
|
|
16
11
|
|
|
17
12
|
/** @type {Record<string, Partial<comq.IO>>} */
|
|
18
13
|
#origins = {}
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
* @param {toa.origins.Manifest} manifest
|
|
22
|
-
*/
|
|
23
|
-
constructor (manifest) {
|
|
15
|
+
constructor (resolve) {
|
|
24
16
|
super()
|
|
25
17
|
|
|
26
|
-
this.#
|
|
18
|
+
this.#resolve = resolve
|
|
27
19
|
}
|
|
28
20
|
|
|
29
21
|
async open () {
|
|
30
|
-
const
|
|
22
|
+
const cfg = await this.#resolve()
|
|
23
|
+
const promises = Object.entries(cfg.origins).map(this.#open)
|
|
31
24
|
|
|
32
25
|
await Promise.all(promises)
|
|
33
26
|
}
|
|
@@ -39,12 +32,15 @@ class Aspect extends Connector {
|
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
async invoke (origin, method, ...args) {
|
|
35
|
+
if (this.#origins[origin]?.[method] === undefined) {
|
|
36
|
+
throw new Error(`Origin "${origin}" or method "${method}" is undefined`)
|
|
37
|
+
}
|
|
38
|
+
|
|
42
39
|
return this.#origins[origin][method](...args)
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
#open = async ([origin,
|
|
46
|
-
const
|
|
47
|
-
const io = await connect(...references)
|
|
42
|
+
#open = async ([origin, references]) => {
|
|
43
|
+
const io = await assert(...references)
|
|
48
44
|
|
|
49
45
|
this.#origins[origin] = restrict(io)
|
|
50
46
|
}
|
|
@@ -67,11 +63,8 @@ function restrict (io) {
|
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*/
|
|
73
|
-
function create (manifest) {
|
|
74
|
-
return new Aspect(manifest)
|
|
66
|
+
function create (resolve) {
|
|
67
|
+
return new Aspect(resolve)
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
exports.create = create
|
|
@@ -15,9 +15,13 @@ function deployment (instances) {
|
|
|
15
15
|
const secrets = []
|
|
16
16
|
|
|
17
17
|
for (const [origin, reference] of Object.entries(manifest)) {
|
|
18
|
-
|
|
18
|
+
let protocol
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const match = reference.match(RX)
|
|
21
|
+
|
|
22
|
+
if (match !== null) protocol = match.groups.protocol
|
|
23
|
+
|
|
24
|
+
if (protocols.includes(protocol)) {
|
|
21
25
|
const originSecrets = createSecrets(locator, origin)
|
|
22
26
|
|
|
23
27
|
secrets.push(...originSecrets)
|
|
@@ -60,4 +64,6 @@ function createSecret (locator, origin, property) {
|
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
|
|
67
|
+
const RX = /^(?<protocol>\w{1,12}:)/
|
|
68
|
+
|
|
63
69
|
exports.deployment = deployment
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { echo } = require('@toa.io/generic')
|
|
4
|
+
const { Connector } = require('@toa.io/core')
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
* @implements {toa.origins.http.Permissions}
|
|
7
|
-
*/
|
|
8
|
-
class Permissions {
|
|
9
|
-
#default = process.env.TOA_DEV === '1'
|
|
10
|
-
|
|
6
|
+
class Permissions extends Connector {
|
|
11
7
|
/** @type {RegExp[]} */
|
|
12
8
|
#allowances = []
|
|
13
9
|
|
|
14
10
|
/** @type {RegExp[]} */
|
|
15
11
|
#denials = []
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
#resolve
|
|
14
|
+
|
|
15
|
+
constructor (resolve) {
|
|
16
|
+
super()
|
|
17
|
+
|
|
18
|
+
this.#resolve = resolve
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async open () {
|
|
22
|
+
const { properties } = await this.#resolve()
|
|
23
|
+
|
|
21
24
|
if (properties !== undefined) this.#parse(properties)
|
|
22
25
|
}
|
|
23
26
|
|
|
@@ -1,41 +1,35 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {import('node-fetch').RequestInit} Request
|
|
5
|
-
* @typedef {import('node-fetch').Response} Response
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
3
|
const fetch = require('node-fetch')
|
|
9
4
|
|
|
10
5
|
const { Connector } = require('@toa.io/core')
|
|
11
6
|
const { retry } = require('@toa.io/generic')
|
|
12
7
|
|
|
13
8
|
const { Permissions } = require('./.aspect/permissions')
|
|
14
|
-
const { id } = require('./id')
|
|
15
9
|
const protocols = require('./protocols')
|
|
10
|
+
const protocol = require('./index')
|
|
16
11
|
|
|
17
|
-
/**
|
|
18
|
-
* @implements {toa.origins.http.Aspect}
|
|
19
|
-
*/
|
|
20
12
|
class Aspect extends Connector {
|
|
21
13
|
/** @readonly */
|
|
22
|
-
name = id
|
|
14
|
+
name = protocol.id
|
|
23
15
|
|
|
24
|
-
|
|
16
|
+
#resolve
|
|
25
17
|
#origins
|
|
26
|
-
|
|
27
|
-
/** @type {toa.origins.http.Permissions} */
|
|
28
18
|
#permissions
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
* @param {toa.origins.Manifest} manifest
|
|
32
|
-
* @param {toa.origins.http.Permissions} permissions
|
|
33
|
-
*/
|
|
34
|
-
constructor (manifest, permissions) {
|
|
20
|
+
constructor (resolve, permissions) {
|
|
35
21
|
super()
|
|
36
22
|
|
|
37
|
-
this.#
|
|
23
|
+
this.#resolve = resolve
|
|
38
24
|
this.#permissions = permissions
|
|
25
|
+
|
|
26
|
+
this.depends(permissions)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async open () {
|
|
30
|
+
const { origins } = await this.#resolve()
|
|
31
|
+
|
|
32
|
+
this.#origins = origins
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
async invoke (name, path, request, options) {
|
|
@@ -56,23 +50,12 @@ class Aspect extends Connector {
|
|
|
56
50
|
return this.#request(url.href, request, options?.retry)
|
|
57
51
|
}
|
|
58
52
|
|
|
59
|
-
/**
|
|
60
|
-
* @param {string} url
|
|
61
|
-
* @param {Request} request
|
|
62
|
-
* @return {Promise<Response>}
|
|
63
|
-
*/
|
|
64
53
|
async #invokeURL (url, request) {
|
|
65
54
|
if (this.#permissions.test(url) === false) throw new Error(`URL '${url}' is not allowed`)
|
|
66
55
|
|
|
67
56
|
return this.#request(url, request)
|
|
68
57
|
}
|
|
69
58
|
|
|
70
|
-
/**
|
|
71
|
-
* @param {string} url
|
|
72
|
-
* @param {Request} request
|
|
73
|
-
* @param {toa.generic.retry.Options} [options]
|
|
74
|
-
* @return {Promise<Response>}
|
|
75
|
-
*/
|
|
76
59
|
async #request (url, request, options) {
|
|
77
60
|
const call = () => fetch(url, request)
|
|
78
61
|
|
|
@@ -117,14 +100,10 @@ function isAbsoluteURL (path) {
|
|
|
117
100
|
|
|
118
101
|
const PLACEHOLDER = /\*/g
|
|
119
102
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
* @param {toa.origins.http.Properties} [properties]
|
|
123
|
-
*/
|
|
124
|
-
function create (manifest, properties) {
|
|
125
|
-
const permissions = new Permissions(properties)
|
|
103
|
+
function create (resolve) {
|
|
104
|
+
const permissions = new Permissions(resolve)
|
|
126
105
|
|
|
127
|
-
return new Aspect(
|
|
106
|
+
return new Aspect(resolve, permissions)
|
|
128
107
|
}
|
|
129
108
|
|
|
130
109
|
exports.create = create
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { type Resolver } from '../Factory'
|
|
4
|
+
import amqp from './amqp'
|
|
5
|
+
import http from './http'
|
|
6
|
+
import type { extensions } from '@toa.io/core'
|
|
7
|
+
|
|
8
|
+
export const protocols: Protocol[] = [http, amqp]
|
|
9
|
+
|
|
10
|
+
export interface Protocol {
|
|
11
|
+
id: ProtocolID
|
|
12
|
+
protocols: string[]
|
|
13
|
+
create: (resolver: Resolver) => extensions.Aspect
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type ProtocolID = 'http' | 'amqp'
|
package/tsconfig.json
ADDED
package/source/.credentials.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {string} reference
|
|
5
|
-
*/
|
|
6
|
-
function check (reference) {
|
|
7
|
-
if (typeof reference !== 'string') return // aspect properties object
|
|
8
|
-
|
|
9
|
-
const url = new URL(reference)
|
|
10
|
-
|
|
11
|
-
if (url.username !== '' || url.password !== '') throw new Error('Origins must not contain credentials. Please use environment secrets instead.')
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.check = check
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { PREFIX } = require('../constants')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {toa.norm.context.dependencies.Instance[]} instances
|
|
7
|
-
* @param {toa.origins.Annotations} annotations
|
|
8
|
-
* @returns {toa.deployment.dependency.Variables}
|
|
9
|
-
*/
|
|
10
|
-
function uris (instances, annotations) {
|
|
11
|
-
const variables = {}
|
|
12
|
-
|
|
13
|
-
for (const [id, annotation] of Object.entries(annotations)) {
|
|
14
|
-
const component = instances.find((instance) => instance.locator.id === id)
|
|
15
|
-
|
|
16
|
-
if (component === undefined) throw new Error(`Origins annotations error: component '${id}' is not found`)
|
|
17
|
-
|
|
18
|
-
for (const origin of Object.keys(annotation)) {
|
|
19
|
-
const properties = origin[0] === '.'
|
|
20
|
-
|
|
21
|
-
if (!properties && !(origin in component.manifest)) {
|
|
22
|
-
throw new Error(`Origins annotations error: component '${id}' doesn't have '${origin}' origin`)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const name = PREFIX + component.locator.uppercase
|
|
27
|
-
const json = JSON.stringify(annotation)
|
|
28
|
-
const value = btoa(json)
|
|
29
|
-
const variable = { name, value }
|
|
30
|
-
|
|
31
|
-
variables[component.locator.label] = [variable]
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return variables
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
exports.uris = uris
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { generate } = require('randomstring')
|
|
4
|
-
const { Locator } = require('@toa.io/core')
|
|
5
|
-
const { random, sample } = require('@toa.io/generic')
|
|
6
|
-
|
|
7
|
-
const { PROTOCOLS } = require('./constants')
|
|
8
|
-
|
|
9
|
-
const component = () => ({
|
|
10
|
-
locator: new Locator(generate(), generate()),
|
|
11
|
-
manifest: { [generate()]: sample(PROTOCOLS) + '//' + generate() }
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
const components = () => {
|
|
15
|
-
const length = random(20) + 10
|
|
16
|
-
|
|
17
|
-
return Array.from({ length }, component)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
exports.components = components
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { generate } = require('randomstring')
|
|
4
|
-
|
|
5
|
-
/** @type {Record<string, string>} */
|
|
6
|
-
const manifest = {
|
|
7
|
-
[generate()]: 'https://toa.io',
|
|
8
|
-
[generate()]: 'https://api.domain.com',
|
|
9
|
-
[generate()]: 'amqp://localhost',
|
|
10
|
-
[generate()]: 'amqps://localhost'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
exports.manifest = manifest
|