@toa.io/extensions.exposition 1.0.0-alpha.3 → 1.0.0-alpha.4
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/identity.bans/manifest.toa.yaml +1 -0
- package/components/identity.basic/manifest.toa.yaml +1 -0
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/manifest.toa.yaml +1 -0
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/manifest.toa.yaml +1 -0
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/manifest.toa.yaml +1 -0
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/octets.storage/manifest.toa.yaml +1 -0
- package/components/octets.storage/operations/store.js +1 -1
- package/documentation/components.md +5 -5
- package/documentation/query.md +45 -2
- package/features/body.feature +1 -1
- package/features/errors.feature +1 -1
- package/features/etag.feature +86 -0
- package/features/octets.entries.feature +1 -1
- package/features/steps/Gateway.ts +3 -0
- package/features/steps/components/echo/manifest.toa.yaml +1 -0
- package/features/steps/components/greeter/manifest.toa.yaml +1 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +1 -0
- package/features/steps/components/pots/manifest.toa.yaml +10 -3
- package/features/steps/components/sequences/manifest.toa.yaml +1 -0
- package/features/timing.feature +43 -0
- package/package.json +7 -10
- package/readme.md +7 -6
- package/schemas/annotation.cos.yaml +1 -0
- package/schemas/querystring.cos.yaml +1 -0
- package/source/Annotation.ts +1 -0
- package/source/Directive.test.ts +3 -3
- package/source/Directive.ts +11 -11
- package/source/Endpoint.ts +18 -4
- package/source/Factory.ts +8 -4
- package/source/Gateway.ts +55 -42
- package/source/HTTP/Context.ts +67 -0
- package/source/HTTP/Server.test.ts +1 -1
- package/source/HTTP/Server.ts +60 -95
- package/source/HTTP/Timing.ts +40 -0
- package/source/HTTP/index.ts +1 -0
- package/source/HTTP/messages.test.ts +27 -8
- package/source/HTTP/messages.ts +32 -48
- package/source/Mapping.ts +7 -8
- package/source/deployment.ts +6 -0
- package/source/directives/auth/Anonymous.ts +3 -2
- package/source/directives/auth/Authorization.ts +5 -3
- package/source/directives/auth/Incept.ts +11 -6
- package/source/directives/auth/Role.ts +5 -3
- package/source/directives/auth/Scheme.ts +2 -2
- package/source/directives/cache/Cache.ts +2 -2
- package/source/directives/cache/Control.ts +5 -5
- package/source/directives/cache/types.ts +1 -1
- package/source/directives/cors/CORS.ts +5 -3
- package/source/directives/octets/Context.ts +1 -1
- package/source/directives/octets/Delete.ts +19 -9
- package/source/directives/octets/Fetch.ts +29 -14
- package/source/directives/octets/List.ts +14 -6
- package/source/directives/octets/Octets.ts +4 -2
- package/source/directives/octets/Permute.ts +12 -6
- package/source/directives/octets/Store.ts +18 -16
- package/source/directives/octets/Workflow.ts +3 -3
- package/source/directives/octets/workflows/Workflow.ts +2 -2
- package/source/directives/vary/Vary.ts +1 -1
- package/source/directives/vary/embeddings/Header.ts +1 -1
- package/source/directives/vary/embeddings/Language.ts +1 -1
- package/source/io.ts +2 -2
- package/transpiled/Annotation.d.ts +1 -0
- package/transpiled/Directive.d.ts +6 -6
- package/transpiled/Directive.js +8 -8
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +3 -3
- package/transpiled/Endpoint.js +34 -1
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.js +4 -2
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +5 -6
- package/transpiled/Gateway.js +38 -32
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +24 -0
- package/transpiled/HTTP/Context.js +47 -0
- package/transpiled/HTTP/Context.js.map +1 -0
- package/transpiled/HTTP/Server.d.ts +8 -7
- package/transpiled/HTTP/Server.js +68 -76
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/Timing.d.ts +10 -0
- package/transpiled/HTTP/Timing.js +29 -0
- package/transpiled/HTTP/Timing.js.map +1 -0
- package/transpiled/HTTP/index.d.ts +1 -0
- package/transpiled/HTTP/index.js +1 -0
- package/transpiled/HTTP/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +7 -21
- package/transpiled/HTTP/messages.js +24 -26
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Mapping.js +7 -7
- package/transpiled/Mapping.js.map +1 -1
- package/transpiled/deployment.js +5 -0
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Anonymous.js +3 -4
- package/transpiled/directives/auth/Anonymous.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +1 -1
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Incept.d.ts +1 -1
- package/transpiled/directives/auth/Incept.js +11 -6
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Role.js +5 -3
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/Scheme.js +2 -2
- package/transpiled/directives/auth/Scheme.js.map +1 -1
- package/transpiled/directives/cache/Cache.d.ts +1 -1
- package/transpiled/directives/cache/Cache.js +2 -2
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.d.ts +3 -3
- package/transpiled/directives/cache/Control.js +3 -3
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/cache/types.d.ts +1 -1
- package/transpiled/directives/cors/CORS.js +4 -3
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/octets/Context.d.ts +1 -1
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Delete.d.ts +1 -1
- package/transpiled/directives/octets/Delete.js +19 -9
- package/transpiled/directives/octets/Delete.js.map +1 -1
- package/transpiled/directives/octets/Fetch.d.ts +1 -1
- package/transpiled/directives/octets/Fetch.js +28 -14
- package/transpiled/directives/octets/Fetch.js.map +1 -1
- package/transpiled/directives/octets/List.d.ts +1 -1
- package/transpiled/directives/octets/List.js +13 -6
- package/transpiled/directives/octets/List.js.map +1 -1
- package/transpiled/directives/octets/Octets.js +4 -2
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Permute.d.ts +1 -1
- package/transpiled/directives/octets/Permute.js +11 -6
- package/transpiled/directives/octets/Permute.js.map +1 -1
- package/transpiled/directives/octets/Store.d.ts +1 -1
- package/transpiled/directives/octets/Store.js +11 -11
- package/transpiled/directives/octets/Store.js.map +1 -1
- package/transpiled/directives/octets/Workflow.d.ts +1 -1
- package/transpiled/directives/octets/Workflow.js +3 -3
- package/transpiled/directives/octets/Workflow.js.map +1 -1
- package/transpiled/directives/octets/workflows/Workflow.d.ts +1 -1
- package/transpiled/directives/octets/workflows/Workflow.js +2 -2
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
- package/transpiled/directives/vary/Vary.js +1 -1
- package/transpiled/directives/vary/embeddings/Header.js +1 -1
- package/transpiled/directives/vary/embeddings/Header.js.map +1 -1
- package/transpiled/directives/vary/embeddings/Language.js +1 -1
- package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
- package/transpiled/io.d.ts +2 -2
- package/transpiled/tsconfig.tsbuildinfo +1 -1
- package/source/HTTP/Server.fixtures.ts +0 -40
- package/transpiled/HTTP/Server.fixtures.d.ts +0 -10
- package/transpiled/HTTP/Server.fixtures.js +0 -31
- package/transpiled/HTTP/Server.fixtures.js.map +0 -1
|
@@ -12,10 +12,10 @@ export class Scheme implements Directive {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
public authorize (_: Identity | null, input: Input): boolean {
|
|
15
|
-
if (input.headers.authorization === undefined)
|
|
15
|
+
if (input.request.headers.authorization === undefined)
|
|
16
16
|
return false
|
|
17
17
|
|
|
18
|
-
const [scheme] = split(input.headers.authorization)
|
|
18
|
+
const [scheme] = split(input.request.headers.authorization)
|
|
19
19
|
|
|
20
20
|
if (scheme !== this.scheme)
|
|
21
21
|
throw new http.Forbidden(this.Scheme +
|
|
@@ -23,9 +23,9 @@ export class Cache implements Family<Directive> {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async settle
|
|
26
|
-
(directives: Directive[],
|
|
26
|
+
(directives: Directive[], input: Input, response: http.OutgoingMessage): Promise<void> {
|
|
27
27
|
response.headers ??= new Headers()
|
|
28
|
-
directives[0]?.set(
|
|
28
|
+
directives[0]?.set(input, response.headers)
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { match } from 'matchacho'
|
|
2
|
-
import type {
|
|
2
|
+
import type { AuthenticatedContext, Directive } from './types'
|
|
3
3
|
|
|
4
4
|
export class Control implements Directive {
|
|
5
5
|
protected readonly value: string
|
|
@@ -9,16 +9,16 @@ export class Control implements Directive {
|
|
|
9
9
|
this.value = value
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
public set (
|
|
13
|
-
if (!['GET', 'HEAD', 'OPTIONS'].includes(request.method))
|
|
12
|
+
public set (context: AuthenticatedContext, headers: Headers): void {
|
|
13
|
+
if (!['GET', 'HEAD', 'OPTIONS'].includes(context.request.method))
|
|
14
14
|
return
|
|
15
15
|
|
|
16
|
-
this.cache ??= this.resolve(
|
|
16
|
+
this.cache ??= this.resolve(context)
|
|
17
17
|
|
|
18
18
|
headers.set('cache-control', this.cache)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
protected resolve (request:
|
|
21
|
+
protected resolve (request: AuthenticatedContext): string {
|
|
22
22
|
if (request.identity === null)
|
|
23
23
|
return this.value
|
|
24
24
|
|
|
@@ -17,12 +17,12 @@ export class CORS implements Interceptor {
|
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
public intercept (input: Input): Output {
|
|
20
|
-
const origin = input.headers.origin
|
|
20
|
+
const origin = input.request.headers.origin
|
|
21
21
|
|
|
22
22
|
if (origin === undefined)
|
|
23
23
|
return null
|
|
24
24
|
|
|
25
|
-
if (input.method === 'OPTIONS')
|
|
25
|
+
if (input.request.method === 'OPTIONS')
|
|
26
26
|
return this.preflightResponse(origin)
|
|
27
27
|
|
|
28
28
|
input.pipelines.response.push((output) => {
|
|
@@ -31,7 +31,9 @@ export class CORS implements Interceptor {
|
|
|
31
31
|
output.headers.set('access-control-expose-headers',
|
|
32
32
|
'authorization, content-type, content-length, etag')
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const method = input.request.method
|
|
35
|
+
|
|
36
|
+
if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS')
|
|
35
37
|
output.headers.append('vary', 'origin')
|
|
36
38
|
})
|
|
37
39
|
|
|
@@ -27,11 +27,16 @@ export class Delete implements Directive {
|
|
|
27
27
|
this.discovery = discovery
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
public async apply (storage: string,
|
|
30
|
+
public async apply (storage: string, input: Input, parameters: Parameter[]): Promise<Output> {
|
|
31
31
|
this.storage ??= await this.discovery
|
|
32
32
|
|
|
33
33
|
const entry = await this.storage.invoke<Maybe<Entry>>('get',
|
|
34
|
-
{
|
|
34
|
+
{
|
|
35
|
+
input: {
|
|
36
|
+
storage,
|
|
37
|
+
path: input.request.url
|
|
38
|
+
}
|
|
39
|
+
})
|
|
35
40
|
|
|
36
41
|
if (entry instanceof Error)
|
|
37
42
|
throw new NotFound()
|
|
@@ -40,31 +45,36 @@ export class Delete implements Directive {
|
|
|
40
45
|
|
|
41
46
|
if (this.workflow !== undefined) {
|
|
42
47
|
output.status = 202
|
|
43
|
-
output.body = Readable.from(this.execute(
|
|
48
|
+
output.body = Readable.from(this.execute(input, storage, entry, parameters))
|
|
44
49
|
} else
|
|
45
|
-
await this.delete(storage,
|
|
50
|
+
await this.delete(storage, input)
|
|
46
51
|
|
|
47
52
|
return output
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
private async delete (storage: string,
|
|
55
|
+
private async delete (storage: string, input: Input): Promise<void> {
|
|
51
56
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
52
57
|
await this.storage!.invoke('delete',
|
|
53
|
-
{
|
|
58
|
+
{
|
|
59
|
+
input: {
|
|
60
|
+
storage,
|
|
61
|
+
path: input.request.url
|
|
62
|
+
}
|
|
63
|
+
})
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
// eslint-disable-next-line max-params
|
|
57
67
|
private async * execute
|
|
58
|
-
(
|
|
68
|
+
(input: Input, storage: string, entry: Entry, parameters: Parameter[]): AsyncGenerator {
|
|
59
69
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
60
|
-
for await (const chunk of this.workflow!.execute(
|
|
70
|
+
for await (const chunk of this.workflow!.execute(input, storage, entry, parameters)) {
|
|
61
71
|
yield chunk
|
|
62
72
|
|
|
63
73
|
if (typeof chunk === 'object' && chunk !== null && 'error' in chunk)
|
|
64
74
|
return
|
|
65
75
|
}
|
|
66
76
|
|
|
67
|
-
await this.delete(storage,
|
|
77
|
+
await this.delete(storage, input)
|
|
68
78
|
}
|
|
69
79
|
}
|
|
70
80
|
|
|
@@ -12,7 +12,11 @@ import type { Directive, Input } from './types'
|
|
|
12
12
|
export class Fetch implements Directive {
|
|
13
13
|
public readonly targeted = true
|
|
14
14
|
|
|
15
|
-
private readonly permissions: Required<Permissions> = {
|
|
15
|
+
private readonly permissions: Required<Permissions> = {
|
|
16
|
+
blob: true,
|
|
17
|
+
meta: false
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
private readonly discovery: Promise<Component>
|
|
17
21
|
private storage: Component = null as unknown as Component
|
|
18
22
|
|
|
@@ -23,30 +27,34 @@ export class Fetch implements Directive {
|
|
|
23
27
|
this.discovery = discovery
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
public async apply (storage: string,
|
|
30
|
+
public async apply (storage: string, input: Input): Promise<Output> {
|
|
27
31
|
this.storage ??= await this.discovery
|
|
28
32
|
|
|
29
|
-
const variant = posix.basename(request.url).includes('.')
|
|
30
|
-
const metadata =
|
|
33
|
+
const variant = posix.basename(input.request.url).includes('.')
|
|
34
|
+
const metadata = input.subtype === 'octets.entry'
|
|
31
35
|
|
|
32
36
|
if (!variant && metadata)
|
|
33
37
|
if (this.permissions.meta)
|
|
34
|
-
return this.get(storage,
|
|
38
|
+
return this.get(storage, input)
|
|
35
39
|
else
|
|
36
40
|
throw new Forbidden('Metadata is not accessible.')
|
|
37
41
|
|
|
38
42
|
if (!variant && !this.permissions.blob)
|
|
39
43
|
throw new Forbidden('BLOB variant must be specified.')
|
|
40
44
|
|
|
41
|
-
return await this.fetch(storage,
|
|
45
|
+
return await this.fetch(storage, input)
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
private async fetch (storage: string,
|
|
45
|
-
if ('if-none-match' in request.headers)
|
|
48
|
+
private async fetch (storage: string, input: Input): Promise<Output> {
|
|
49
|
+
if ('if-none-match' in input.request.headers)
|
|
46
50
|
return { status: 304 }
|
|
47
51
|
|
|
48
|
-
const
|
|
49
|
-
|
|
52
|
+
const result = await this.storage.invoke<Maybe<FetchResult>>('fetch', {
|
|
53
|
+
input: {
|
|
54
|
+
storage,
|
|
55
|
+
path: input.request.url
|
|
56
|
+
}
|
|
57
|
+
})
|
|
50
58
|
|
|
51
59
|
if (result instanceof Error)
|
|
52
60
|
throw new NotFound()
|
|
@@ -57,12 +65,19 @@ export class Fetch implements Directive {
|
|
|
57
65
|
etag: result.checksum
|
|
58
66
|
})
|
|
59
67
|
|
|
60
|
-
return {
|
|
68
|
+
return {
|
|
69
|
+
headers,
|
|
70
|
+
body: result.stream
|
|
71
|
+
}
|
|
61
72
|
}
|
|
62
73
|
|
|
63
|
-
private async get (storage: string,
|
|
64
|
-
const
|
|
65
|
-
|
|
74
|
+
private async get (storage: string, input: Input): Promise<Output> {
|
|
75
|
+
const entry = await this.storage.invoke<Maybe<Entry>>('get', {
|
|
76
|
+
input: {
|
|
77
|
+
storage,
|
|
78
|
+
path: input.request.url
|
|
79
|
+
}
|
|
80
|
+
})
|
|
66
81
|
|
|
67
82
|
if (entry instanceof Error)
|
|
68
83
|
throw new NotFound()
|
|
@@ -22,22 +22,26 @@ export class List implements Directive {
|
|
|
22
22
|
this.discovery = discovery
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
public async apply (storage: string,
|
|
25
|
+
public async apply (storage: string, input: Input): Promise<Output> {
|
|
26
26
|
this.storage ??= await this.discovery
|
|
27
27
|
|
|
28
|
-
const metadata =
|
|
28
|
+
const metadata = input.subtype === 'octets.entries'
|
|
29
29
|
|
|
30
30
|
if (metadata && !this.permissions.meta)
|
|
31
31
|
throw new Forbidden('Metadata is not accessible.')
|
|
32
32
|
|
|
33
|
-
const
|
|
34
|
-
|
|
33
|
+
const list = await this.storage.invoke<Maybe<string[]>>('list', {
|
|
34
|
+
input: {
|
|
35
|
+
storage,
|
|
36
|
+
path: input.request.url
|
|
37
|
+
}
|
|
38
|
+
})
|
|
35
39
|
|
|
36
40
|
if (list instanceof Error)
|
|
37
41
|
throw new NotFound()
|
|
38
42
|
|
|
39
43
|
const body = metadata
|
|
40
|
-
? await this.expand(storage, request.url, list)
|
|
44
|
+
? await this.expand(storage, input.request.url, list)
|
|
41
45
|
: list
|
|
42
46
|
|
|
43
47
|
return { body }
|
|
@@ -47,7 +51,11 @@ export class List implements Directive {
|
|
|
47
51
|
Promise<Array<Maybe<Entry>>> {
|
|
48
52
|
const promises = list.map(async (id) => {
|
|
49
53
|
const path = posix.join(prefix, id)
|
|
50
|
-
|
|
54
|
+
|
|
55
|
+
const input = {
|
|
56
|
+
storage,
|
|
57
|
+
path
|
|
58
|
+
}
|
|
51
59
|
|
|
52
60
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- ensured in `apply`
|
|
53
61
|
return this.storage!.invoke<Maybe<Entry>>('get', { input })
|
|
@@ -46,15 +46,17 @@ export class Octets implements Family<Directive> {
|
|
|
46
46
|
if (action === null)
|
|
47
47
|
return null
|
|
48
48
|
|
|
49
|
+
// noinspection PointlessBooleanExpressionJS
|
|
49
50
|
if (context === null)
|
|
50
51
|
throw new Error('Octets context is not defined.')
|
|
51
52
|
|
|
52
|
-
const targeted = input.
|
|
53
|
+
const targeted = input.request.url[input.request.url.length - 1] !== '/'
|
|
53
54
|
|
|
54
55
|
if (targeted !== action.targeted)
|
|
55
56
|
throw new NotFound(`Trailing slash is ${action.targeted ? 'redundant' : 'required'}.`)
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
// noinspection JSObjectNullOrUndefined
|
|
59
|
+
return action.apply(context.storage, input, parameters)
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -18,16 +18,22 @@ export class Permute implements Directive {
|
|
|
18
18
|
this.discovery = discovery
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
public async apply (storage: string,
|
|
21
|
+
public async apply (storage: string, input: Input): Promise<Output> {
|
|
22
22
|
this.storage ??= await this.discovery
|
|
23
23
|
|
|
24
|
-
if (
|
|
24
|
+
if (input.encoder === null)
|
|
25
25
|
throw new NotAcceptable()
|
|
26
26
|
|
|
27
|
-
const path = request.url
|
|
28
|
-
const list = await
|
|
29
|
-
|
|
30
|
-
const error = await this.storage.invoke<Maybe<unknown>>('permute', {
|
|
27
|
+
const path = input.request.url
|
|
28
|
+
const list = await input.body()
|
|
29
|
+
|
|
30
|
+
const error = await this.storage.invoke<Maybe<unknown>>('permute', {
|
|
31
|
+
input: {
|
|
32
|
+
storage,
|
|
33
|
+
path,
|
|
34
|
+
list
|
|
35
|
+
}
|
|
36
|
+
})
|
|
31
37
|
|
|
32
38
|
if (error instanceof Error)
|
|
33
39
|
throw new NotFound()
|
|
@@ -39,42 +39,42 @@ export class Store implements Directive {
|
|
|
39
39
|
cors.allowHeader('content-meta')
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
public async apply (storage: string,
|
|
42
|
+
public async apply (storage: string, input: Input, parameters: Parameter[]): Promise<Output> {
|
|
43
43
|
this.storage ??= await this.discovery.storage
|
|
44
44
|
|
|
45
|
-
const
|
|
46
|
-
const meta = request.headers['content-meta']
|
|
45
|
+
const request: StoreRequest = { input: { storage, request: input.request } }
|
|
46
|
+
const meta = input.request.headers['content-meta']
|
|
47
47
|
|
|
48
48
|
if (this.accept !== undefined)
|
|
49
|
-
input.accept = this.accept
|
|
49
|
+
request.input.accept = this.accept
|
|
50
50
|
|
|
51
51
|
if (meta !== undefined)
|
|
52
|
-
input.meta = this.parseMeta(meta)
|
|
52
|
+
request.input.meta = this.parseMeta(meta)
|
|
53
53
|
|
|
54
|
-
const entry = await this.storage.invoke<Entry>('store',
|
|
54
|
+
const entry = await this.storage.invoke<Entry>('store', request)
|
|
55
55
|
|
|
56
56
|
return match<Output>(entry,
|
|
57
57
|
Error, (error: ErrorType) => this.throw(error),
|
|
58
|
-
() => this.reply(
|
|
58
|
+
() => this.reply(input, storage, entry, parameters))
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// eslint-disable-next-line max-params
|
|
62
|
-
private reply (
|
|
62
|
+
private reply (input: Input, storage: string, entry: Entry, parameters: Parameter[]): Output {
|
|
63
63
|
const body = this.workflow === undefined
|
|
64
64
|
? entry
|
|
65
|
-
: this.execute(
|
|
65
|
+
: this.execute(input, storage, entry, parameters)
|
|
66
66
|
|
|
67
67
|
return { body }
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// eslint-disable-next-line max-params
|
|
71
71
|
private execute
|
|
72
|
-
(
|
|
72
|
+
(input: Input, storage: string, entry: Entry, parameters: Parameter[]): Readable {
|
|
73
73
|
const stream = new PassThrough({ objectMode: true })
|
|
74
74
|
|
|
75
75
|
stream.push(entry)
|
|
76
76
|
|
|
77
|
-
this.workflow!.execute(
|
|
77
|
+
this.workflow!.execute(input, storage, entry, parameters).pipe(stream)
|
|
78
78
|
|
|
79
79
|
return stream
|
|
80
80
|
}
|
|
@@ -108,9 +108,11 @@ export interface Options {
|
|
|
108
108
|
workflow?: Unit[] | Unit
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
interface
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
interface StoreRequest {
|
|
112
|
+
input: {
|
|
113
|
+
storage: string
|
|
114
|
+
request: Input['request']
|
|
115
|
+
accept?: string
|
|
116
|
+
meta?: Record<string, string>
|
|
117
|
+
}
|
|
116
118
|
}
|
|
@@ -24,18 +24,18 @@ export class WorkflowDirective implements Directive {
|
|
|
24
24
|
this.discovery = discovery
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
public async apply (storage: string,
|
|
27
|
+
public async apply (storage: string, input: Input, parameters: Parameter[]): Promise<Output> {
|
|
28
28
|
this.storage ??= await this.discovery
|
|
29
29
|
|
|
30
30
|
const entry = await this.storage.invoke<Maybe<Entry>>('get',
|
|
31
|
-
{ input: { storage, path: request.url } })
|
|
31
|
+
{ input: { storage, path: input.request.url } })
|
|
32
32
|
|
|
33
33
|
if (entry instanceof Error)
|
|
34
34
|
throw new NotFound()
|
|
35
35
|
|
|
36
36
|
return {
|
|
37
37
|
status: 202,
|
|
38
|
-
body: this.workflow.execute(
|
|
38
|
+
body: this.workflow.execute(input, storage, entry, parameters)
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -21,8 +21,8 @@ export class Workflow {
|
|
|
21
21
|
|
|
22
22
|
// eslint-disable-next-line max-params
|
|
23
23
|
public execute
|
|
24
|
-
(
|
|
25
|
-
const path = posix.join(request.
|
|
24
|
+
(input: Input, storage: string, entry: Entry, params: Parameter[]): Execution {
|
|
25
|
+
const path = posix.join(input.request.url, entry.id)
|
|
26
26
|
const parameters: Record<string, string> = {}
|
|
27
27
|
|
|
28
28
|
for (const { name, value } of params)
|
|
@@ -21,7 +21,7 @@ export class Vary implements Family {
|
|
|
21
21
|
|
|
22
22
|
public preflight (instances: Array<Directive | Property>, request: Input): Output {
|
|
23
23
|
/*
|
|
24
|
-
To stop
|
|
24
|
+
To stop constructing `properties` object on each request, Directive Families must be refactored
|
|
25
25
|
from singleton factories to per-Node instances on the Tree.
|
|
26
26
|
*/
|
|
27
27
|
const properties: Properties = {}
|
|
@@ -17,7 +17,7 @@ export class Language implements Embedding {
|
|
|
17
17
|
assert.ok(properties.languages.length > 0,
|
|
18
18
|
'List of supported languages is empty.')
|
|
19
19
|
|
|
20
|
-
const negotiator = new Negotiator(input)
|
|
20
|
+
const negotiator = new Negotiator(input.request)
|
|
21
21
|
const language = negotiator.language(properties.languages) ?? properties.languages[0]
|
|
22
22
|
|
|
23
23
|
input.pipelines.response.push((response) => {
|
package/source/io.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Context, OutgoingMessage } from './HTTP';
|
|
2
2
|
import type { Remotes } from './Remotes';
|
|
3
3
|
import type { Output } from './io';
|
|
4
4
|
import type * as RTD from './RTD';
|
|
5
5
|
export declare class Directives implements RTD.Directives<Directives> {
|
|
6
6
|
private readonly sets;
|
|
7
7
|
constructor(sets: DirectiveSet[]);
|
|
8
|
-
preflight(
|
|
9
|
-
settle(
|
|
8
|
+
preflight(context: Context, parameters: RTD.Parameter[]): Promise<Output>;
|
|
9
|
+
settle(context: Context, response: OutgoingMessage): Promise<void>;
|
|
10
10
|
merge(directives: Directives): void;
|
|
11
11
|
}
|
|
12
12
|
export declare class DirectivesFactory implements RTD.DirectivesFactory<Directives> {
|
|
13
|
-
private readonly
|
|
13
|
+
private readonly remotes;
|
|
14
14
|
private readonly families;
|
|
15
15
|
private readonly mandatory;
|
|
16
16
|
constructor(families: Family[], remotes: Remotes);
|
|
@@ -21,8 +21,8 @@ export interface Family<TDirective = any, TExtension = any> {
|
|
|
21
21
|
readonly name: string;
|
|
22
22
|
readonly mandatory: boolean;
|
|
23
23
|
create: (name: string, value: any, remotes: Remotes) => TDirective;
|
|
24
|
-
preflight?: (directives: TDirective[], request:
|
|
25
|
-
settle?: (directives: TDirective[], request:
|
|
24
|
+
preflight?: (directives: TDirective[], request: Context & TExtension, parameters: RTD.Parameter[]) => Output | Promise<Output>;
|
|
25
|
+
settle?: (directives: TDirective[], request: Context & TExtension, response: OutgoingMessage) => void | Promise<void>;
|
|
26
26
|
}
|
|
27
27
|
interface DirectiveSet {
|
|
28
28
|
family: Family;
|
package/transpiled/Directive.js
CHANGED
|
@@ -6,22 +6,22 @@ class Directives {
|
|
|
6
6
|
constructor(sets) {
|
|
7
7
|
this.sets = sets;
|
|
8
8
|
}
|
|
9
|
-
async preflight(
|
|
9
|
+
async preflight(context, parameters) {
|
|
10
10
|
for (const set of this.sets) {
|
|
11
11
|
if (set.family.preflight === undefined)
|
|
12
12
|
continue;
|
|
13
|
-
const output = await set.family.preflight(set.directives,
|
|
13
|
+
const output = await set.family.preflight(set.directives, context, parameters);
|
|
14
14
|
if (output !== null) {
|
|
15
|
-
await this.settle(
|
|
15
|
+
await this.settle(context, output);
|
|
16
16
|
return output;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
|
-
async settle(
|
|
21
|
+
async settle(context, response) {
|
|
22
22
|
for (const set of this.sets)
|
|
23
23
|
if (set.family.settle !== undefined)
|
|
24
|
-
await set.family.settle(set.directives,
|
|
24
|
+
await set.family.settle(set.directives, context, response);
|
|
25
25
|
}
|
|
26
26
|
merge(directives) {
|
|
27
27
|
this.sets.push(...directives.sets);
|
|
@@ -29,7 +29,7 @@ class Directives {
|
|
|
29
29
|
}
|
|
30
30
|
exports.Directives = Directives;
|
|
31
31
|
class DirectivesFactory {
|
|
32
|
-
|
|
32
|
+
remotes;
|
|
33
33
|
families = {};
|
|
34
34
|
mandatory = [];
|
|
35
35
|
constructor(families, remotes) {
|
|
@@ -38,7 +38,7 @@ class DirectivesFactory {
|
|
|
38
38
|
if (family.mandatory)
|
|
39
39
|
this.mandatory.push(family.name);
|
|
40
40
|
}
|
|
41
|
-
this.
|
|
41
|
+
this.remotes = remotes;
|
|
42
42
|
}
|
|
43
43
|
create(declarations) {
|
|
44
44
|
const groups = {};
|
|
@@ -48,7 +48,7 @@ class DirectivesFactory {
|
|
|
48
48
|
const family = this.families[declaration.family];
|
|
49
49
|
if (family === undefined)
|
|
50
50
|
throw new Error(`Directive family '${declaration.family}' is not found.`);
|
|
51
|
-
const directive = family.create(declaration.name, declaration.value, this.
|
|
51
|
+
const directive = family.create(declaration.name, declaration.value, this.remotes);
|
|
52
52
|
groups[family.name] ??= [];
|
|
53
53
|
groups[family.name].push(directive);
|
|
54
54
|
mandatory.delete(family.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Directive.js","sourceRoot":"","sources":["../source/Directive.ts"],"names":[],"mappings":";;;AAKA,MAAa,UAAU;IACJ,IAAI,CAAgB;IAErC,YAAoB,IAAoB;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,SAAS,CAAE,
|
|
1
|
+
{"version":3,"file":"Directive.js","sourceRoot":"","sources":["../source/Directive.ts"],"names":[],"mappings":";;;AAKA,MAAa,UAAU;IACJ,IAAI,CAAgB;IAErC,YAAoB,IAAoB;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,SAAS,CAAE,OAAgB,EAAE,UAA2B;QACnE,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS;gBACpC,SAAQ;YAEV,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAA;YAE9E,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAElC,OAAO,MAAM,CAAA;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,KAAK,CAAC,MAAM,CAAE,OAAgB,EAAE,QAAyB;QAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI;YACzB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;gBACjC,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IAChE,CAAC;IAEM,KAAK,CAAE,UAAsB;QAClC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;CACF;AAjCD,gCAiCC;AAED,MAAa,iBAAiB;IACX,OAAO,CAAS;IAChB,QAAQ,GAA2B,EAAE,CAAA;IACrC,SAAS,GAAa,EAAE,CAAA;IAEzC,YAAoB,QAAkB,EAAE,OAAgB;QACtD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA;YAEnC,IAAI,MAAM,CAAC,SAAS;gBAClB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpC,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAEM,MAAM,CAAE,YAAoC;QACjD,MAAM,MAAM,GAAwB,EAAE,CAAA;QACtC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAEzC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACzB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAExE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YAEhD,IAAI,MAAM,KAAK,SAAS;gBACtB,MAAM,IAAI,KAAK,CAAC,qBAAqB,WAAW,CAAC,MAAM,iBAAiB,CAAC,CAAA;YAE3E,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YAElF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;YAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACnC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,MAAM,IAAI,GAAmB,EAAE,CAAA;QAE/B,KAAK,MAAM,MAAM,IAAI,SAAS;YAC5B,IAAI,CAAC,IAAI,CAAC;gBACR,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC7B,UAAU,EAAE,EAAE;aACf,CAAC,CAAA;QAEJ,KAAK,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC;gBACR,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC7B,UAAU;aACX,CAAC,CAAA;QAEJ,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;CACF;AApDD,8CAoDC;AAEY,QAAA,SAAS,GAAyB,IAAI,GAAG,CAAC;IACrD,CAAC,WAAW,EAAE,gBAAgB,CAAC;IAC/B,CAAC,IAAI,EAAE,SAAS,CAAC;IACjB,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,QAAQ,EAAE,aAAa,CAAC;CAC1B,CAAC,CAAA"}
|
package/transpiled/Endpoint.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { type Component
|
|
1
|
+
import { type Component } from '@toa.io/core';
|
|
2
2
|
import { type Remotes } from './Remotes';
|
|
3
3
|
import { Mapping } from './Mapping';
|
|
4
4
|
import { type Context } from './Context';
|
|
5
|
+
import * as http from './HTTP';
|
|
5
6
|
import type * as RTD from './RTD';
|
|
6
|
-
import type * as http from './HTTP';
|
|
7
7
|
export declare class Endpoint implements RTD.Endpoint<Endpoint> {
|
|
8
8
|
private readonly endpoint;
|
|
9
9
|
private readonly mapping;
|
|
10
10
|
private readonly discovery;
|
|
11
11
|
private remote;
|
|
12
12
|
constructor(endpoint: string, mapping: Mapping, discovery: Promise<Component>);
|
|
13
|
-
call(body: any, query: http.Query, parameters: RTD.Parameter[]): Promise<
|
|
13
|
+
call(body: any, query: http.Query, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage>;
|
|
14
14
|
close(): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
export declare class EndpointsFactory implements RTD.EndpointsFactory<Endpoint> {
|