@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.
Files changed (152) hide show
  1. package/components/identity.bans/manifest.toa.yaml +1 -0
  2. package/components/identity.basic/manifest.toa.yaml +1 -0
  3. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  4. package/components/identity.federation/manifest.toa.yaml +1 -0
  5. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  6. package/components/identity.roles/manifest.toa.yaml +1 -0
  7. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  8. package/components/identity.tokens/manifest.toa.yaml +1 -0
  9. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  10. package/components/octets.storage/manifest.toa.yaml +1 -0
  11. package/components/octets.storage/operations/store.js +1 -1
  12. package/documentation/components.md +5 -5
  13. package/documentation/query.md +45 -2
  14. package/features/body.feature +1 -1
  15. package/features/errors.feature +1 -1
  16. package/features/etag.feature +86 -0
  17. package/features/octets.entries.feature +1 -1
  18. package/features/steps/Gateway.ts +3 -0
  19. package/features/steps/components/echo/manifest.toa.yaml +1 -0
  20. package/features/steps/components/greeter/manifest.toa.yaml +1 -0
  21. package/features/steps/components/octets.tester/manifest.toa.yaml +1 -0
  22. package/features/steps/components/pots/manifest.toa.yaml +10 -3
  23. package/features/steps/components/sequences/manifest.toa.yaml +1 -0
  24. package/features/timing.feature +43 -0
  25. package/package.json +7 -10
  26. package/readme.md +7 -6
  27. package/schemas/annotation.cos.yaml +1 -0
  28. package/schemas/querystring.cos.yaml +1 -0
  29. package/source/Annotation.ts +1 -0
  30. package/source/Directive.test.ts +3 -3
  31. package/source/Directive.ts +11 -11
  32. package/source/Endpoint.ts +18 -4
  33. package/source/Factory.ts +8 -4
  34. package/source/Gateway.ts +55 -42
  35. package/source/HTTP/Context.ts +67 -0
  36. package/source/HTTP/Server.test.ts +1 -1
  37. package/source/HTTP/Server.ts +60 -95
  38. package/source/HTTP/Timing.ts +40 -0
  39. package/source/HTTP/index.ts +1 -0
  40. package/source/HTTP/messages.test.ts +27 -8
  41. package/source/HTTP/messages.ts +32 -48
  42. package/source/Mapping.ts +7 -8
  43. package/source/deployment.ts +6 -0
  44. package/source/directives/auth/Anonymous.ts +3 -2
  45. package/source/directives/auth/Authorization.ts +5 -3
  46. package/source/directives/auth/Incept.ts +11 -6
  47. package/source/directives/auth/Role.ts +5 -3
  48. package/source/directives/auth/Scheme.ts +2 -2
  49. package/source/directives/cache/Cache.ts +2 -2
  50. package/source/directives/cache/Control.ts +5 -5
  51. package/source/directives/cache/types.ts +1 -1
  52. package/source/directives/cors/CORS.ts +5 -3
  53. package/source/directives/octets/Context.ts +1 -1
  54. package/source/directives/octets/Delete.ts +19 -9
  55. package/source/directives/octets/Fetch.ts +29 -14
  56. package/source/directives/octets/List.ts +14 -6
  57. package/source/directives/octets/Octets.ts +4 -2
  58. package/source/directives/octets/Permute.ts +12 -6
  59. package/source/directives/octets/Store.ts +18 -16
  60. package/source/directives/octets/Workflow.ts +3 -3
  61. package/source/directives/octets/workflows/Workflow.ts +2 -2
  62. package/source/directives/vary/Vary.ts +1 -1
  63. package/source/directives/vary/embeddings/Header.ts +1 -1
  64. package/source/directives/vary/embeddings/Language.ts +1 -1
  65. package/source/io.ts +2 -2
  66. package/transpiled/Annotation.d.ts +1 -0
  67. package/transpiled/Directive.d.ts +6 -6
  68. package/transpiled/Directive.js +8 -8
  69. package/transpiled/Directive.js.map +1 -1
  70. package/transpiled/Endpoint.d.ts +3 -3
  71. package/transpiled/Endpoint.js +34 -1
  72. package/transpiled/Endpoint.js.map +1 -1
  73. package/transpiled/Factory.js +4 -2
  74. package/transpiled/Factory.js.map +1 -1
  75. package/transpiled/Gateway.d.ts +5 -6
  76. package/transpiled/Gateway.js +38 -32
  77. package/transpiled/Gateway.js.map +1 -1
  78. package/transpiled/HTTP/Context.d.ts +24 -0
  79. package/transpiled/HTTP/Context.js +47 -0
  80. package/transpiled/HTTP/Context.js.map +1 -0
  81. package/transpiled/HTTP/Server.d.ts +8 -7
  82. package/transpiled/HTTP/Server.js +68 -76
  83. package/transpiled/HTTP/Server.js.map +1 -1
  84. package/transpiled/HTTP/Timing.d.ts +10 -0
  85. package/transpiled/HTTP/Timing.js +29 -0
  86. package/transpiled/HTTP/Timing.js.map +1 -0
  87. package/transpiled/HTTP/index.d.ts +1 -0
  88. package/transpiled/HTTP/index.js +1 -0
  89. package/transpiled/HTTP/index.js.map +1 -1
  90. package/transpiled/HTTP/messages.d.ts +7 -21
  91. package/transpiled/HTTP/messages.js +24 -26
  92. package/transpiled/HTTP/messages.js.map +1 -1
  93. package/transpiled/Mapping.js +7 -7
  94. package/transpiled/Mapping.js.map +1 -1
  95. package/transpiled/deployment.js +5 -0
  96. package/transpiled/deployment.js.map +1 -1
  97. package/transpiled/directives/auth/Anonymous.js +3 -4
  98. package/transpiled/directives/auth/Anonymous.js.map +1 -1
  99. package/transpiled/directives/auth/Authorization.js +1 -1
  100. package/transpiled/directives/auth/Authorization.js.map +1 -1
  101. package/transpiled/directives/auth/Incept.d.ts +1 -1
  102. package/transpiled/directives/auth/Incept.js +11 -6
  103. package/transpiled/directives/auth/Incept.js.map +1 -1
  104. package/transpiled/directives/auth/Role.js +5 -3
  105. package/transpiled/directives/auth/Role.js.map +1 -1
  106. package/transpiled/directives/auth/Scheme.js +2 -2
  107. package/transpiled/directives/auth/Scheme.js.map +1 -1
  108. package/transpiled/directives/cache/Cache.d.ts +1 -1
  109. package/transpiled/directives/cache/Cache.js +2 -2
  110. package/transpiled/directives/cache/Cache.js.map +1 -1
  111. package/transpiled/directives/cache/Control.d.ts +3 -3
  112. package/transpiled/directives/cache/Control.js +3 -3
  113. package/transpiled/directives/cache/Control.js.map +1 -1
  114. package/transpiled/directives/cache/types.d.ts +1 -1
  115. package/transpiled/directives/cors/CORS.js +4 -3
  116. package/transpiled/directives/cors/CORS.js.map +1 -1
  117. package/transpiled/directives/octets/Context.d.ts +1 -1
  118. package/transpiled/directives/octets/Context.js.map +1 -1
  119. package/transpiled/directives/octets/Delete.d.ts +1 -1
  120. package/transpiled/directives/octets/Delete.js +19 -9
  121. package/transpiled/directives/octets/Delete.js.map +1 -1
  122. package/transpiled/directives/octets/Fetch.d.ts +1 -1
  123. package/transpiled/directives/octets/Fetch.js +28 -14
  124. package/transpiled/directives/octets/Fetch.js.map +1 -1
  125. package/transpiled/directives/octets/List.d.ts +1 -1
  126. package/transpiled/directives/octets/List.js +13 -6
  127. package/transpiled/directives/octets/List.js.map +1 -1
  128. package/transpiled/directives/octets/Octets.js +4 -2
  129. package/transpiled/directives/octets/Octets.js.map +1 -1
  130. package/transpiled/directives/octets/Permute.d.ts +1 -1
  131. package/transpiled/directives/octets/Permute.js +11 -6
  132. package/transpiled/directives/octets/Permute.js.map +1 -1
  133. package/transpiled/directives/octets/Store.d.ts +1 -1
  134. package/transpiled/directives/octets/Store.js +11 -11
  135. package/transpiled/directives/octets/Store.js.map +1 -1
  136. package/transpiled/directives/octets/Workflow.d.ts +1 -1
  137. package/transpiled/directives/octets/Workflow.js +3 -3
  138. package/transpiled/directives/octets/Workflow.js.map +1 -1
  139. package/transpiled/directives/octets/workflows/Workflow.d.ts +1 -1
  140. package/transpiled/directives/octets/workflows/Workflow.js +2 -2
  141. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  142. package/transpiled/directives/vary/Vary.js +1 -1
  143. package/transpiled/directives/vary/embeddings/Header.js +1 -1
  144. package/transpiled/directives/vary/embeddings/Header.js.map +1 -1
  145. package/transpiled/directives/vary/embeddings/Language.js +1 -1
  146. package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
  147. package/transpiled/io.d.ts +2 -2
  148. package/transpiled/tsconfig.tsbuildinfo +1 -1
  149. package/source/HTTP/Server.fixtures.ts +0 -40
  150. package/transpiled/HTTP/Server.fixtures.d.ts +0 -10
  151. package/transpiled/HTTP/Server.fixtures.js +0 -31
  152. 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[], request: Input, response: http.OutgoingMessage): Promise<void> {
26
+ (directives: Directive[], input: Input, response: http.OutgoingMessage): Promise<void> {
27
27
  response.headers ??= new Headers()
28
- directives[0]?.set(request, response.headers)
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 { AuthenticatedRequest, Directive } from './types'
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 (request: AuthenticatedRequest, headers: Headers): void {
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(request)
16
+ this.cache ??= this.resolve(context)
17
17
 
18
18
  headers.set('cache-control', this.cache)
19
19
  }
20
20
 
21
- protected resolve (request: AuthenticatedRequest): string {
21
+ protected resolve (request: AuthenticatedContext): string {
22
22
  if (request.identity === null)
23
23
  return this.value
24
24
 
@@ -4,6 +4,6 @@ export interface Directive {
4
4
  set: (input: Input, headers: Headers) => void
5
5
  }
6
6
 
7
- export interface AuthenticatedRequest extends Input {
7
+ export interface AuthenticatedContext extends Input {
8
8
  identity?: unknown | null
9
9
  }
@@ -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
- if (input.method === 'GET' || input.method === 'HEAD' || input.method === 'OPTIONS')
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
 
@@ -6,7 +6,7 @@ export class Context implements Directive {
6
6
  public readonly targeted = false
7
7
  public readonly storage: string
8
8
 
9
- public constructor (value: any) {
9
+ public constructor (value: unknown) {
10
10
  schemas.context.validate(value)
11
11
 
12
12
  this.storage = value
@@ -27,11 +27,16 @@ export class Delete implements Directive {
27
27
  this.discovery = discovery
28
28
  }
29
29
 
30
- public async apply (storage: string, request: Input, parameters: Parameter[]): Promise<Output> {
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
- { input: { storage, path: request.url } })
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(request, storage, entry, parameters))
48
+ output.body = Readable.from(this.execute(input, storage, entry, parameters))
44
49
  } else
45
- await this.delete(storage, request)
50
+ await this.delete(storage, input)
46
51
 
47
52
  return output
48
53
  }
49
54
 
50
- private async delete (storage: string, request: Input): Promise<void> {
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
- { input: { storage, path: request.url } })
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
- (request: Input, storage: string, entry: Entry, parameters: Parameter[]): AsyncGenerator {
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(request, storage, entry, parameters)) {
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, request)
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> = { blob: true, meta: false }
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, request: Input): Promise<Output> {
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 = request.subtype === 'octets.entry'
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, request)
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, request)
45
+ return await this.fetch(storage, input)
42
46
  }
43
47
 
44
- private async fetch (storage: string, request: Input): Promise<Output> {
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 input = { storage, path: request.url }
49
- const result = await this.storage.invoke<Maybe<FetchResult>>('fetch', { input })
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 { headers, body: result.stream }
68
+ return {
69
+ headers,
70
+ body: result.stream
71
+ }
61
72
  }
62
73
 
63
- private async get (storage: string, request: Input): Promise<Output> {
64
- const input = { storage, path: request.url }
65
- const entry = await this.storage.invoke<Maybe<Entry>>('get', { input })
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, request: Input): Promise<Output> {
25
+ public async apply (storage: string, input: Input): Promise<Output> {
26
26
  this.storage ??= await this.discovery
27
27
 
28
- const metadata = request.subtype === 'octets.entries'
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 input = { storage, path: request.url }
34
- const list = await this.storage.invoke<Maybe<string[]>>('list', { input })
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
- const input = { storage, path }
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.path[input.path.length - 1] !== '/'
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
- return await action.apply(context.storage, input, parameters)
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, request: Input): Promise<Output> {
21
+ public async apply (storage: string, input: Input): Promise<Output> {
22
22
  this.storage ??= await this.discovery
23
23
 
24
- if (request.encoder === null)
24
+ if (input.encoder === null)
25
25
  throw new NotAcceptable()
26
26
 
27
- const path = request.url
28
- const list = await request.parse()
29
- const input = { storage, path, list }
30
- const error = await this.storage.invoke<Maybe<unknown>>('permute', { input })
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, request: Input, parameters: Parameter[]): Promise<Output> {
42
+ public async apply (storage: string, input: Input, parameters: Parameter[]): Promise<Output> {
43
43
  this.storage ??= await this.discovery.storage
44
44
 
45
- const input: StoreInput = { storage, request }
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', { input })
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(request, storage, entry, parameters))
58
+ () => this.reply(input, storage, entry, parameters))
59
59
  }
60
60
 
61
61
  // eslint-disable-next-line max-params
62
- private reply (request: Input, storage: string, entry: Entry, parameters: Parameter[]): Output {
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(request, storage, entry, parameters)
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
- (request: Input, storage: string, entry: Entry, parameters: Parameter[]): Readable {
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(request, storage, entry, parameters).pipe(stream)
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 StoreInput {
112
- storage: string
113
- request: Input
114
- accept?: string
115
- meta?: Record<string, string>
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, request: Input, parameters: Parameter[]): Promise<Output> {
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(request, storage, entry, parameters)
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
- (request: Input, storage: string, entry: Entry, params: Parameter[]): Execution {
25
- const path = posix.join(request.path, entry.id)
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 consructing `properties` object on each request, Directive Families must be refactored
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 = {}
@@ -12,7 +12,7 @@ export class Header implements Embedding {
12
12
  }
13
13
 
14
14
  public resolve (input: Input): string | undefined {
15
- const value = input.headers[this.name]
15
+ const value = input.request.headers[this.name]
16
16
 
17
17
  if (value === undefined)
18
18
  return value
@@ -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,4 +1,4 @@
1
- import type { IncomingMessage, OutgoingMessage } from './HTTP'
1
+ import type { Context, OutgoingMessage } from './HTTP'
2
2
 
3
- export type Input = IncomingMessage
3
+ export type Input = Context
4
4
  export type Output = OutgoingMessage | null
@@ -3,5 +3,6 @@ export interface Annotation {
3
3
  class?: string;
4
4
  annotations?: Record<string, string>;
5
5
  debug: boolean;
6
+ trace: boolean;
6
7
  '/'?: object;
7
8
  }
@@ -1,16 +1,16 @@
1
- import type { IncomingMessage, OutgoingMessage } from './HTTP';
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(request: IncomingMessage, parameters: RTD.Parameter[]): Promise<Output>;
9
- settle(request: IncomingMessage, response: OutgoingMessage): Promise<void>;
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 remtoes;
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: IncomingMessage & TExtension, parameters: RTD.Parameter[]) => Output | Promise<Output>;
25
- settle?: (directives: TDirective[], request: IncomingMessage & TExtension, response: OutgoingMessage) => void | Promise<void>;
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;
@@ -6,22 +6,22 @@ class Directives {
6
6
  constructor(sets) {
7
7
  this.sets = sets;
8
8
  }
9
- async preflight(request, parameters) {
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, request, parameters);
13
+ const output = await set.family.preflight(set.directives, context, parameters);
14
14
  if (output !== null) {
15
- await this.settle(request, output);
15
+ await this.settle(context, output);
16
16
  return output;
17
17
  }
18
18
  }
19
19
  return null;
20
20
  }
21
- async settle(request, response) {
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, request, response);
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
- remtoes;
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.remtoes = remotes;
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.remtoes);
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":"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"}
1
+ {"version":3,"file":"Directive.js","sourceRoot":"","sources":["../source/Directive.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,16 @@
1
- import { type Component, type Reply } from '@toa.io/core';
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<Reply>;
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> {