@toa.io/extensions.exposition 1.0.0-alpha.86 → 1.0.0-alpha.89

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 (80) hide show
  1. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -1
  2. package/components/identity.basic/operations/transit.js +3 -3
  3. package/components/identity.basic/operations/transit.js.map +1 -1
  4. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  5. package/components/identity.basic/source/transit.ts +3 -3
  6. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  7. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  8. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  9. package/components/octets.storage/manifest.toa.yaml +3 -5
  10. package/components/octets.storage/operations/get.js +1 -1
  11. package/components/octets.storage/operations/head.js +7 -0
  12. package/components/octets.storage/operations/{store.js → put.js} +9 -9
  13. package/documentation/octets.md +17 -47
  14. package/features/{octets.meta.feature → octets.attributes.feature} +13 -12
  15. package/features/octets.cloudinary.feature +68 -0
  16. package/features/octets.download.feature +6 -6
  17. package/features/octets.entries.feature +8 -57
  18. package/features/octets.feature +8 -60
  19. package/features/octets.workflows.feature +0 -36
  20. package/features/steps/.env.example +3 -0
  21. package/features/steps/Parameters.ts +40 -0
  22. package/features/steps/components/octets.tester/manifest.toa.yaml +0 -1
  23. package/features/steps/components/octets.tester/operations/bar.js +0 -1
  24. package/features/steps/components/octets.tester/operations/baz.js +0 -1
  25. package/features/steps/components/octets.tester/operations/foo.js +0 -1
  26. package/package.json +3 -3
  27. package/source/Endpoint.ts +3 -3
  28. package/source/HTTP/Server.ts +4 -0
  29. package/source/RTD/syntax/parse.test.ts +1 -1
  30. package/source/directives/auth/Scheme.ts +1 -1
  31. package/source/directives/io/Output.ts +1 -1
  32. package/source/directives/octets/Delete.ts +11 -11
  33. package/source/directives/octets/{Fetch.ts → Get.ts} +17 -34
  34. package/source/directives/octets/Octets.ts +6 -8
  35. package/source/directives/octets/{Store.ts → Put.ts} +9 -14
  36. package/source/directives/octets/Workflow.ts +1 -1
  37. package/source/directives/octets/schemas.ts +4 -6
  38. package/source/directives/octets/workflows/Workflow.ts +2 -3
  39. package/source/directives/vary/embeddings/Language.ts +2 -2
  40. package/transpiled/Endpoint.js +3 -3
  41. package/transpiled/Endpoint.js.map +1 -1
  42. package/transpiled/HTTP/Server.js +2 -0
  43. package/transpiled/HTTP/Server.js.map +1 -1
  44. package/transpiled/directives/auth/Scheme.js +1 -1
  45. package/transpiled/directives/auth/Scheme.js.map +1 -1
  46. package/transpiled/directives/io/Output.js +1 -1
  47. package/transpiled/directives/io/Output.js.map +1 -1
  48. package/transpiled/directives/octets/Delete.js +8 -8
  49. package/transpiled/directives/octets/Delete.js.map +1 -1
  50. package/transpiled/directives/octets/{Fetch.d.ts → Get.d.ts} +2 -3
  51. package/transpiled/directives/octets/{Fetch.js → Get.js} +19 -24
  52. package/transpiled/directives/octets/Get.js.map +1 -0
  53. package/transpiled/directives/octets/Octets.js +6 -8
  54. package/transpiled/directives/octets/Octets.js.map +1 -1
  55. package/transpiled/directives/octets/{Store.d.ts → Put.d.ts} +2 -2
  56. package/transpiled/directives/octets/{Store.js → Put.js} +11 -14
  57. package/transpiled/directives/octets/Put.js.map +1 -0
  58. package/transpiled/directives/octets/Workflow.js +1 -1
  59. package/transpiled/directives/octets/Workflow.js.map +1 -1
  60. package/transpiled/directives/octets/schemas.d.ts +4 -6
  61. package/transpiled/directives/octets/schemas.js +3 -4
  62. package/transpiled/directives/octets/schemas.js.map +1 -1
  63. package/transpiled/directives/octets/workflows/Workflow.d.ts +1 -1
  64. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  65. package/transpiled/directives/vary/embeddings/Language.js +2 -2
  66. package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
  67. package/transpiled/tsconfig.tsbuildinfo +1 -1
  68. package/components/octets.storage/operations/fetch.js +0 -46
  69. package/components/octets.storage/operations/list.js +0 -7
  70. package/features/steps/components/octets.tester/operations/diversify.js +0 -16
  71. package/schemas/octets/fetch.cos.yaml +0 -3
  72. package/schemas/octets/permute.cos.yaml +0 -1
  73. package/source/directives/octets/List.ts +0 -72
  74. package/transpiled/directives/octets/Fetch.js.map +0 -1
  75. package/transpiled/directives/octets/List.d.ts +0 -16
  76. package/transpiled/directives/octets/List.js +0 -74
  77. package/transpiled/directives/octets/List.js.map +0 -1
  78. package/transpiled/directives/octets/Store.js.map +0 -1
  79. /package/schemas/octets/{list.cos.yaml → get.cos.yaml} +0 -0
  80. /package/schemas/octets/{store.cos.yaml → put.cos.yaml} +0 -0
@@ -1,6 +1,6 @@
1
- Feature: Octets `content-meta` header
1
+ Feature: Octets `content-attributes` header
2
2
 
3
- Scenario: Sending `content-meta` header
3
+ Scenario: Sending `content-attributes` header
4
4
  Given the `octets.tester` is running
5
5
  And the annotation:
6
6
  """yaml
@@ -10,19 +10,19 @@ Feature: Octets `content-meta` header
10
10
  octets:context: octets
11
11
  /*:
12
12
  POST:
13
- octets:store: ~
13
+ octets:put: ~
14
14
  /*:
15
15
  GET:
16
- octets:fetch:
16
+ octets:get:
17
17
  meta: true
18
18
  """
19
19
  When the stream of `lenna.ascii` is received with the following headers:
20
20
  """
21
- POST /meta-header/ HTTP/1.1
21
+ POST /attributes-header/ HTTP/1.1
22
22
  host: nex.toa.io
23
23
  content-type: application/octet-stream
24
- content-meta: foo, bar=baz=1
25
- content-meta: baz=1
24
+ content-attributes: foo, bar=baz=1
25
+ content-attributes: baz=1
26
26
  """
27
27
  Then the following reply is sent:
28
28
  """
@@ -30,7 +30,7 @@ Feature: Octets `content-meta` header
30
30
  """
31
31
  When the following request is received:
32
32
  """
33
- GET /meta-header/10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
33
+ GET /attributes-header/10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
34
34
  host: nex.toa.io
35
35
  accept: application/vnd.toa.octets.entry+yaml
36
36
  """
@@ -41,19 +41,20 @@ Feature: Octets `content-meta` header
41
41
  id: 10cf16b458f759e0d617f2f3d83599ff
42
42
  type: application/octet-stream
43
43
  size: 8169
44
- meta:
44
+ checksum: 10cf16b458f759e0d617f2f3d83599ff
45
+ attributes:
45
46
  foo: 'true'
46
47
  bar: baz=1
47
48
  baz: '1'
48
49
  """
49
50
 
50
- Scenario: CORS allows `content-meta` header
51
+ Scenario: CORS allows `content-attributes` header
51
52
  Given the annotation:
52
53
  """yaml
53
54
  /:
54
55
  octets:context: octets
55
56
  POST:
56
- octets:store: ~
57
+ octets:put: ~
57
58
  """
58
59
  When the following request is received:
59
60
  """
@@ -65,5 +66,5 @@ Feature: Octets `content-meta` header
65
66
  """
66
67
  204 No Content
67
68
  access-control-allow-origin: https://example.com
68
- access-control-allow-headers: accept, authorization, content-type, etag, if-match, if-none-match, content-meta
69
+ access-control-allow-headers: accept, authorization, content-type, etag, if-match, if-none-match, content-attributes
69
70
  """
@@ -0,0 +1,68 @@
1
+ Feature: Octets with Cloudinary storage
2
+
3
+ Background:
4
+ Given the annotation:
5
+ """yaml
6
+ /:
7
+ io:output: true
8
+ auth:anonymous: true
9
+ octets:context: cloudinary
10
+ POST:
11
+ octets:put: ~
12
+ /*:
13
+ GET:
14
+ octets:get: ~
15
+ DELETE:
16
+ octets:delete: ~
17
+ """
18
+
19
+ Scenario: Upload an image
20
+ When the stream of `lenna.png` is received with the following headers:
21
+ """
22
+ POST / HTTP/1.1
23
+ host: nex.toa.io
24
+ accept: application/yaml
25
+ content-type: application/octet-stream
26
+ """
27
+ Then the following reply is sent:
28
+ """
29
+ 201 Created
30
+ content-type: application/yaml
31
+
32
+ id: 814a0034f5549e957ee61360d87457e5
33
+ type: image/png
34
+ size: 473831
35
+ """
36
+ When the following request is received:
37
+ """
38
+ GET /814a0034f5549e957ee61360d87457e5 HTTP/1.1
39
+ host: nex.toa.io
40
+ """
41
+ Then the stream equals to `lenna.png` is sent with the following headers:
42
+ """
43
+ 200 OK
44
+ content-type: image/png
45
+ content-length: 473831
46
+ """
47
+
48
+ Scenario: Image transformations
49
+ When the stream of `lenna.png` is received with the following headers:
50
+ """
51
+ POST / HTTP/1.1
52
+ host: nex.toa.io
53
+ content-type: image/png
54
+ """
55
+ Then the following reply is sent:
56
+ """
57
+ 201 Created
58
+ """
59
+ When the following request is received:
60
+ """
61
+ GET /814a0034f5549e957ee61360d87457e5.48x48.jpeg HTTP/1.1
62
+ host: nex.toa.io
63
+ """
64
+ Then the stream equals to `lenna.48x48.jpeg` is sent with the following headers:
65
+ """
66
+ 200 OK
67
+ content-type: image/jpeg
68
+ """
@@ -1,4 +1,4 @@
1
- Feature: Download and store
1
+ Feature: Download external resources
2
2
 
3
3
  Scenario Outline: Download from trusted location defined as <type>
4
4
  Given the annotation:
@@ -8,13 +8,13 @@ Feature: Download and store
8
8
  auth:anonymous: true
9
9
  octets:context: octets
10
10
  POST:
11
- octets:store:
11
+ octets:put:
12
12
  trust:
13
13
  - <location> # <type>
14
14
  - https://github.com
15
15
  /*:
16
16
  GET:
17
- octets:fetch:
17
+ octets:get:
18
18
  meta: true
19
19
  """
20
20
 
@@ -143,7 +143,7 @@ Feature: Download and store
143
143
  auth:anonymous: true
144
144
  octets:context: octets
145
145
  POST:
146
- octets:store:
146
+ octets:put:
147
147
  limit: 1kb
148
148
  trust:
149
149
  - https://avatars.githubusercontent.com
@@ -171,7 +171,7 @@ Feature: Download and store
171
171
  auth:anonymous: true
172
172
  octets:context: octets
173
173
  POST:
174
- octets:store:
174
+ octets:put:
175
175
  limit: 1kb
176
176
  trust:
177
177
  - https://avatars.githubusercontent.com
@@ -185,5 +185,5 @@ Feature: Download and store
185
185
  Then the following reply is sent:
186
186
  """
187
187
  204 No Content
188
- access-control-allow-headers: accept, authorization, content-type, etag, if-match, if-none-match, content-meta, content-location
188
+ access-control-allow-headers: accept, authorization, content-type, etag, if-match, if-none-match, content-attributes, content-location
189
189
  """
@@ -1,6 +1,6 @@
1
- Feature: Accessing entries
1
+ Feature: Accessing metadata
2
2
 
3
- Scenario: Entries are not accessible by default
3
+ Scenario: Metadata is not accessible by default
4
4
  Given the annotation:
5
5
  """yaml
6
6
  /:
@@ -8,12 +8,10 @@ Feature: Accessing entries
8
8
  auth:anonymous: true
9
9
  octets:context: octets
10
10
  POST:
11
- octets:store: ~
12
- GET:
13
- octets:list: ~
11
+ octets:put: ~
14
12
  /*:
15
13
  GET:
16
- octets:fetch: ~
14
+ octets:get: ~
17
15
  """
18
16
  When the stream of `lenna.ascii` is received with the following headers:
19
17
  """
@@ -25,18 +23,6 @@ Feature: Accessing entries
25
23
  """
26
24
  201 Created
27
25
  """
28
- When the following request is received:
29
- """
30
- GET / HTTP/1.1
31
- host: nex.toa.io
32
- accept: application/vnd.toa.octets.entries+yaml
33
- """
34
- Then the following reply is sent:
35
- """
36
- 403 Forbidden
37
-
38
- Metadata is not accessible.
39
- """
40
26
  When the following request is received:
41
27
  """
42
28
  GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
@@ -47,10 +33,10 @@ Feature: Accessing entries
47
33
  """
48
34
  403 Forbidden
49
35
 
50
- Metadata is not accessible.
36
+ Metadata is not accessible
51
37
  """
52
38
 
53
- Scenario: Accessing entries
39
+ Scenario: Accessing metadata
54
40
  Given the annotation:
55
41
  """yaml
56
42
  /:
@@ -58,13 +44,10 @@ Feature: Accessing entries
58
44
  auth:anonymous: true
59
45
  octets:context: octets
60
46
  POST:
61
- octets:store: ~
62
- GET:
63
- octets:list:
64
- meta: true
47
+ octets:put: ~
65
48
  /*:
66
49
  GET:
67
- octets:fetch:
50
+ octets:get:
68
51
  meta: true
69
52
  """
70
53
  When the stream of `lenna.ascii` is received with the following headers:
@@ -81,38 +64,6 @@ Feature: Accessing entries
81
64
  accept: application/yaml
82
65
  content-type: application/octet-stream
83
66
  """
84
- When the following request is received:
85
- """
86
- GET / HTTP/1.1
87
- host: nex.toa.io
88
- accept: application/yaml
89
- """
90
- Then the following reply is sent:
91
- """
92
- 200 OK
93
- content-type: application/yaml
94
-
95
- - 10cf16b458f759e0d617f2f3d83599ff
96
- - 814a0034f5549e957ee61360d87457e5
97
- """
98
- When the following request is received:
99
- """
100
- GET / HTTP/1.1
101
- host: nex.toa.io
102
- accept: application/vnd.toa.octets.entries+yaml
103
- """
104
- Then the following reply is sent:
105
- """
106
- 200 OK
107
- content-type: application/yaml
108
-
109
- - id: 10cf16b458f759e0d617f2f3d83599ff
110
- size: 8169
111
- type: application/octet-stream
112
- - id: 814a0034f5549e957ee61360d87457e5
113
- size: 473831
114
- type: image/png
115
- """
116
67
  When the following request is received:
117
68
  """
118
69
  GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
@@ -8,39 +8,37 @@ Feature: Octets directive family
8
8
  auth:anonymous: true
9
9
  octets:context: octets
10
10
  POST:
11
- octets:store: ~
12
- GET:
13
- octets:list: ~
11
+ octets:put: ~
14
12
  /*:
15
13
  GET:
16
- octets:fetch: ~
14
+ octets:get: ~
17
15
  DELETE:
18
16
  octets:delete: ~
19
17
  /media:
20
18
  /jpeg:
21
19
  POST:
22
- octets:store:
20
+ octets:put:
23
21
  accept: image/jpeg
24
22
  /jpeg-or-png:
25
23
  POST:
26
- octets:store:
24
+ octets:put:
27
25
  accept:
28
26
  - image/jpeg
29
27
  - image/png
30
28
  /images:
31
29
  POST:
32
- octets:store:
30
+ octets:put:
33
31
  accept: image/*
34
32
  /*:
35
33
  GET:
36
- octets:fetch: ~
34
+ octets:get: ~
37
35
  /limit-1kb:
38
36
  POST:
39
- octets:store:
37
+ octets:put:
40
38
  limit: 1kb
41
39
  /limit-100kb:
42
40
  POST:
43
- octets:store:
41
+ octets:put:
44
42
  limit: 100kb
45
43
  """
46
44
 
@@ -83,19 +81,6 @@ Feature: Octets directive family
83
81
  """
84
82
  304 Not Modified
85
83
  """
86
- When the following request is received:
87
- """
88
- GET / HTTP/1.1
89
- host: nex.toa.io
90
- accept: application/yaml
91
- """
92
- Then the following reply is sent:
93
- """
94
- 200 OK
95
- content-type: application/yaml
96
-
97
- - 10cf16b458f759e0d617f2f3d83599ff
98
- """
99
84
  When the following request is received:
100
85
  """
101
86
  GET /10cf16b458f759e0d617f2f3d83599ff?foo=bar HTTP/1.1
@@ -260,40 +245,3 @@ Feature: Octets directive family
260
245
 
261
246
  Trailing slash is redundant.
262
247
  """
263
-
264
- Scenario: Original BLOB is not accessible
265
- Given the annotation:
266
- """yaml
267
- /:
268
- io:output: true
269
- auth:anonymous: true
270
- octets:context: octets
271
- POST:
272
- octets:store: ~
273
- /*:
274
- GET:
275
- octets:fetch:
276
- meta: true
277
- blob: false
278
- """
279
- When the stream of `lenna.ascii` is received with the following headers:
280
- """
281
- POST / HTTP/1.1
282
- host: nex.toa.io
283
- """
284
- Then the following reply is sent:
285
- """
286
- 201 Created
287
- """
288
- When the following request is received:
289
- """
290
- GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
291
- host: nex.toa.io
292
- accept: text/plain
293
- """
294
- Then the following reply is sent:
295
- """
296
- 403 Forbidden
297
-
298
- BLOB variant must be specified.
299
- """
@@ -13,7 +13,6 @@ Feature: Octets storage workflows
13
13
  - add-foo: octets.tester.foo
14
14
  add-bar: octets.tester.bar
15
15
  - add-baz: octets.tester.baz
16
- - diversify: octets.tester.diversify
17
16
  /*:
18
17
  io:output: true
19
18
  GET:
@@ -51,43 +50,8 @@ Feature: Octets storage workflows
51
50
 
52
51
  step: add-baz
53
52
  status: completed
54
- --cut
55
-
56
- step: diversify
57
- output: hello
58
- status: completed
59
53
  --cut--
60
54
  """
61
- When the following request is received:
62
- """
63
- GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
64
- host: nex.toa.io
65
- accept: application/vnd.toa.octets.entry+yaml
66
- """
67
- Then the following reply is sent:
68
- """
69
- 200 OK
70
- content-type: application/yaml
71
-
72
- id: 10cf16b458f759e0d617f2f3d83599ff
73
- type: application/octet-stream
74
- size: 8169
75
- meta:
76
- foo: bar
77
- bar: baz
78
- baz: qux
79
- """
80
- When the following request is received:
81
- """
82
- GET /10cf16b458f759e0d617f2f3d83599ff.hello.png HTTP/1.1
83
- host: nex.toa.io
84
- """
85
- Then the stream equals to `lenna.png` is sent with the following headers:
86
- """
87
- 200 OK
88
- content-type: image/png
89
- content-length: 473831
90
- """
91
55
 
92
56
  Scenario: Getting error when running workflow on `store`
93
57
  Given the `octets.tester` is running
@@ -0,0 +1,3 @@
1
+ CLOUDINARY_ENVIRONMENT=
2
+ TOA_STORAGES_CLOUDINARY_API_KEY=
3
+ TOA_STORAGES_CLOUDINARY_API_SECRET=
@@ -1,7 +1,11 @@
1
+ import { join } from 'node:path'
2
+ import * as dotenv from 'dotenv'
1
3
  import { setDefaultTimeout } from '@cucumber/cucumber'
2
4
  import { encode } from '@toa.io/generic'
3
5
  import { console } from 'openspan'
4
6
 
7
+ dotenv.config({ path: join(__dirname, '.env') })
8
+
5
9
  export class Parameters {
6
10
  public readonly origin: string
7
11
 
@@ -20,5 +24,41 @@ process.env.TOA_STORAGES = encode({
20
24
  octets: {
21
25
  provider: 'tmp',
22
26
  directory: Math.random().toString(36).substring(2)
27
+ },
28
+ cloudinary: {
29
+ provider: 'cloudinary',
30
+ environment: process.env.CLOUDINARY_ENVIRONMENT ?? 'nope',
31
+ type: 'image',
32
+ prefix: 'toa-dev',
33
+ transformations: [
34
+ {
35
+ extension: '(?<width>\\d*)x(?<height>\\d*)(z(?<zoom>\\d*))?',
36
+ transformation: {
37
+ width: '<width>',
38
+ height: '<height>',
39
+ zoom: '<zoom>',
40
+ crop: 'thumb',
41
+ gravity: 'face'
42
+ },
43
+ optional: true
44
+ },
45
+ {
46
+ extension: '\\[(?<width>\\d*)x(?<height>\\d*)\\](z(?<zoom>\\d+))?',
47
+ transformation: {
48
+ width: '<width>',
49
+ height: '<height>',
50
+ zoom: '<zoom>',
51
+ crop: 'fit'
52
+ },
53
+ optional: true
54
+ },
55
+ {
56
+ extension: '(?<format>jpeg|webp)',
57
+ transformation: {
58
+ fetch_format: '<format>'
59
+ },
60
+ optional: true
61
+ }
62
+ ]
23
63
  }
24
64
  })
@@ -17,7 +17,6 @@ operations:
17
17
  err: *operation
18
18
  echo: *operation
19
19
  concat: *operation
20
- diversify: *operation
21
20
  yield: *operation
22
21
  yex: *operation
23
22
  authority: *operation
@@ -4,7 +4,6 @@ import { setTimeout } from 'node:timers/promises'
4
4
 
5
5
  async function bar (input, context) {
6
6
  await setTimeout(10)
7
- await context.storages.octets.annotate(input.path, 'bar', 'baz')
8
7
 
9
8
  return { bar: 'baz' }
10
9
  }
@@ -4,7 +4,6 @@ import { setTimeout } from 'node:timers/promises'
4
4
 
5
5
  async function baz (input, context) {
6
6
  await setTimeout(30)
7
- await context.storages.octets.annotate(input.path, 'baz', 'qux')
8
7
  }
9
8
 
10
9
  exports.effect = baz
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  async function foo (input, context) {
4
- await context.storages.octets.annotate(input.path, 'foo', 'bar')
5
4
  }
6
5
 
7
6
  exports.effect = foo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/extensions.exposition",
3
- "version": "1.0.0-alpha.86",
3
+ "version": "1.0.0-alpha.89",
4
4
  "description": "Toa Exposition",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -52,11 +52,11 @@
52
52
  "@swc/core": "1.6.6",
53
53
  "@swc/helpers": "0.5.11",
54
54
  "@toa.io/agent": "1.0.0-alpha.79",
55
- "@toa.io/extensions.storages": "1.0.0-alpha.86",
55
+ "@toa.io/extensions.storages": "1.0.0-alpha.89",
56
56
  "@types/bcryptjs": "2.4.3",
57
57
  "@types/cors": "2.8.13",
58
58
  "@types/negotiator": "0.6.1",
59
59
  "jest-esbuild": "0.3.0"
60
60
  },
61
- "gitHead": "9379190c388da1327a70f23e0b6f3ae47f0724fb"
61
+ "gitHead": "2234ef78c649dbe51f9c68f11d720d34e666ab08"
62
62
  }
@@ -113,7 +113,7 @@ export class Endpoint implements RTD.Endpoint {
113
113
  const match = etag.match(ETAG)
114
114
 
115
115
  if (match === null)
116
- throw new http.BadRequest('Invalid ETag.')
116
+ throw new http.BadRequest('Invalid ETag')
117
117
 
118
118
  return Number.parseInt(match.groups!.version)
119
119
  }
@@ -128,14 +128,14 @@ export class EndpointsFactory implements RTD.EndpointsFactory {
128
128
 
129
129
  public create (method: RTD.syntax.Method, context: Context): Endpoint {
130
130
  if (method.mapping === undefined)
131
- throw new Error('Cannot create Endpoint without mapping.')
131
+ throw new Error('Cannot create Endpoint without mapping')
132
132
 
133
133
  const mapping = Mapping.create(method.mapping.query)
134
134
  const namespace = method.mapping.namespace ?? context.extension.namespace
135
135
  const component = method.mapping.component ?? context.extension.component
136
136
 
137
137
  if (namespace === undefined || component === undefined)
138
- throw new Error('Annotation endpoints must be fully qualified.')
138
+ throw new Error('Annotation endpoints must be fully qualified')
139
139
 
140
140
  const discovery = this.remotes.discover(namespace, component, context.extension.version)
141
141
 
@@ -25,6 +25,10 @@ export class Server extends Connector {
25
25
  this.authorities = Object.fromEntries(Object.entries(properties.authorities).map(([key, value]) => [value, key]))
26
26
 
27
27
  this.server.on('request', (req, res) => this.listener(req, res))
28
+
29
+ if (this.properties.debug)
30
+ this.server.on('connection', (socket) =>
31
+ console.debug('Connected', { address: socket.remoteAddress }))
28
32
  }
29
33
 
30
34
  public static create (options: Options): Server {
@@ -148,7 +148,7 @@ describe('validation', () => {
148
148
  it('should throw on unknown key', async () => {
149
149
  const declaration = { hello: 'world' }
150
150
 
151
- expect(() => parse(declaration)).toThrow('RTD parse error: unknown key \'hello\'.')
151
+ expect(() => parse(declaration)).toThrow('RTD parse error: unknown key \'hello\'')
152
152
  })
153
153
 
154
154
  it('should throw on invalid mapping', async () => {
@@ -19,7 +19,7 @@ export class Scheme implements Directive {
19
19
 
20
20
  if (scheme !== this.scheme)
21
21
  throw new http.Forbidden(this.Scheme +
22
- ' authentication scheme is required to access this resource.')
22
+ ' authentication scheme is required to access this resource')
23
23
 
24
24
  return false
25
25
  }
@@ -41,7 +41,7 @@ export class Output implements Directive {
41
41
 
42
42
  if (typeof message.body !== 'object' || this.permissions.length === 0) {
43
43
  if (this.omitted)
44
- console.warn('Permissions for \'io:output\' are not specified properly. Response omitted.',
44
+ console.warn('Permissions for \'io:output\' are not specified properly, response omitted',
45
45
  { path: context.url.pathname })
46
46
 
47
47
  delete message.body
@@ -32,20 +32,20 @@ export class Delete extends Directive {
32
32
  public async apply (storage: string, input: Input, parameters: Parameter[]): Promise<Output> {
33
33
  this.storage ??= await this.discovery
34
34
 
35
- const entry = await this.storage.invoke<Maybe<Entry>>('get',
36
- {
37
- input: {
38
- storage,
39
- path: input.request.url
40
- }
41
- })
42
-
43
- if (entry instanceof Error)
44
- throw new NotFound()
45
-
46
35
  const output: Output = {}
47
36
 
48
37
  if (this.workflow !== undefined) {
38
+ const entry = await this.storage.invoke<Maybe<Entry>>('head',
39
+ {
40
+ input: {
41
+ storage,
42
+ path: input.request.url
43
+ }
44
+ })
45
+
46
+ if (entry instanceof Error)
47
+ throw new NotFound()
48
+
49
49
  output.status = 202
50
50
  output.body = Readable.from(this.execute(input, storage, entry, parameters))
51
51
  } else