@toa.io/extensions.exposition 0.24.0-alpha.21 → 0.24.0-alpha.23

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 (82) hide show
  1. package/components/context.toa.yaml +1 -1
  2. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  3. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  4. package/components/octets.storage/manifest.toa.yaml +1 -0
  5. package/components/octets.storage/operations/store.js +2 -2
  6. package/documentation/octets.md +89 -37
  7. package/features/cors.feature +33 -0
  8. package/features/octets.entries.feature +121 -0
  9. package/features/octets.feature +1 -27
  10. package/features/octets.meta.feature +65 -0
  11. package/features/octets.workflows.feature +105 -4
  12. package/features/routes.feature +37 -0
  13. package/features/steps/Captures.ts +3 -2
  14. package/features/steps/Components.ts +15 -8
  15. package/features/steps/HTTP.ts +1 -1
  16. package/features/steps/Parameters.ts +1 -1
  17. package/features/steps/components/octets.tester/manifest.toa.yaml +1 -0
  18. package/features/steps/components/octets.tester/operations/echo.js +7 -0
  19. package/features/steps/components/users/manifest.toa.yaml +3 -0
  20. package/features/steps/components/users.properties/manifest.toa.yaml +13 -0
  21. package/features/steps/tsconfig.json +1 -1
  22. package/features/vary.feature +1 -1
  23. package/package.json +8 -8
  24. package/schemas/octets/delete.cos.yaml +2 -1
  25. package/schemas/octets/list.cos.yaml +2 -1
  26. package/source/HTTP/Server.ts +32 -23
  27. package/source/HTTP/messages.ts +7 -1
  28. package/source/directives/cors/CORS.ts +25 -23
  29. package/source/directives/index.ts +1 -1
  30. package/source/directives/octets/Delete.ts +45 -6
  31. package/source/directives/octets/Fetch.ts +17 -18
  32. package/source/directives/octets/List.ts +36 -6
  33. package/source/directives/octets/Permute.ts +2 -2
  34. package/source/directives/octets/Store.ts +36 -94
  35. package/source/directives/octets/schemas.ts +11 -6
  36. package/source/directives/octets/workflow/Execution.ts +77 -0
  37. package/source/directives/octets/workflow/Workflow.ts +28 -0
  38. package/source/directives/octets/workflow/index.ts +1 -0
  39. package/source/manifest.test.ts +6 -14
  40. package/source/manifest.ts +9 -6
  41. package/source/schemas.ts +7 -3
  42. package/transpiled/HTTP/Server.d.ts +1 -1
  43. package/transpiled/HTTP/Server.js +22 -21
  44. package/transpiled/HTTP/Server.js.map +1 -1
  45. package/transpiled/HTTP/messages.d.ts +1 -0
  46. package/transpiled/HTTP/messages.js +4 -1
  47. package/transpiled/HTTP/messages.js.map +1 -1
  48. package/transpiled/directives/cors/CORS.d.ts +2 -5
  49. package/transpiled/directives/cors/CORS.js +18 -16
  50. package/transpiled/directives/cors/CORS.js.map +1 -1
  51. package/transpiled/directives/index.js +1 -1
  52. package/transpiled/directives/index.js.map +1 -1
  53. package/transpiled/directives/octets/Delete.d.ts +9 -1
  54. package/transpiled/directives/octets/Delete.js +30 -6
  55. package/transpiled/directives/octets/Delete.js.map +1 -1
  56. package/transpiled/directives/octets/Fetch.d.ts +4 -5
  57. package/transpiled/directives/octets/Fetch.js +11 -12
  58. package/transpiled/directives/octets/Fetch.js.map +1 -1
  59. package/transpiled/directives/octets/List.d.ts +6 -1
  60. package/transpiled/directives/octets/List.js +22 -4
  61. package/transpiled/directives/octets/List.js.map +1 -1
  62. package/transpiled/directives/octets/Permute.js +2 -2
  63. package/transpiled/directives/octets/Permute.js.map +1 -1
  64. package/transpiled/directives/octets/Store.d.ts +7 -19
  65. package/transpiled/directives/octets/Store.js +21 -66
  66. package/transpiled/directives/octets/Store.js.map +1 -1
  67. package/transpiled/directives/octets/schemas.d.ts +11 -6
  68. package/transpiled/directives/octets/schemas.js.map +1 -1
  69. package/transpiled/directives/octets/workflow/Execution.d.ts +24 -0
  70. package/transpiled/directives/octets/workflow/Execution.js +55 -0
  71. package/transpiled/directives/octets/workflow/Execution.js.map +1 -0
  72. package/transpiled/directives/octets/workflow/Workflow.d.ts +11 -0
  73. package/transpiled/directives/octets/workflow/Workflow.js +21 -0
  74. package/transpiled/directives/octets/workflow/Workflow.js.map +1 -0
  75. package/transpiled/directives/octets/workflow/index.d.ts +1 -0
  76. package/transpiled/directives/octets/workflow/index.js +6 -0
  77. package/transpiled/directives/octets/workflow/index.js.map +1 -0
  78. package/transpiled/manifest.js +10 -5
  79. package/transpiled/manifest.js.map +1 -1
  80. package/transpiled/schemas.d.ts +7 -3
  81. package/transpiled/schemas.js.map +1 -1
  82. package/transpiled/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,121 @@
1
+ Feature: Accessing entires
2
+
3
+ Scenario: Entries are not accessible by default
4
+ Given the annotation:
5
+ """yaml
6
+ /:
7
+ auth:anonymous: true
8
+ octets:context: octets
9
+ POST:
10
+ octets:store: ~
11
+ GET:
12
+ octets:list: ~
13
+ /*:
14
+ GET:
15
+ octets:fetch: ~
16
+ """
17
+ When the stream of `lenna.ascii` is received with the following headers:
18
+ """
19
+ POST / HTTP/1.1
20
+ content-type: application/octet-stream
21
+ """
22
+ Then the following reply is sent:
23
+ """
24
+ 201 Created
25
+ """
26
+ When the following request is received:
27
+ """
28
+ GET / HTTP/1.1
29
+ accept: application/vnd.toa.octets.entries+yaml
30
+ """
31
+ Then the following reply is sent:
32
+ """
33
+ 403 Forbidden
34
+
35
+ Metadata is not accessible.
36
+ """
37
+ When the following request is received:
38
+ """
39
+ GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
40
+ accept: text/vnd.toa.octets.entry+plain
41
+ """
42
+ Then the following reply is sent:
43
+ """
44
+ 403 Forbidden
45
+
46
+ Metadata is not accessible.
47
+ """
48
+
49
+ Scenario: Accessing entries
50
+ Given the annotation:
51
+ """yaml
52
+ /:
53
+ auth:anonymous: true
54
+ octets:context: octets
55
+ POST:
56
+ octets:store: ~
57
+ GET:
58
+ octets:list:
59
+ meta: true
60
+ /*:
61
+ GET:
62
+ octets:fetch:
63
+ meta: true
64
+ """
65
+ When the stream of `lenna.ascii` is received with the following headers:
66
+ """
67
+ POST / HTTP/1.1
68
+ accept: application/yaml
69
+ content-type: application/octet-stream
70
+ """
71
+ And the stream of `lenna.png` is received with the following headers:
72
+ """
73
+ POST / HTTP/1.1
74
+ accept: application/yaml
75
+ content-type: application/octet-stream
76
+ """
77
+ When the following request is received:
78
+ """
79
+ GET / HTTP/1.1
80
+ accept: application/yaml
81
+ """
82
+ Then the following reply is sent:
83
+ """
84
+ 200 OK
85
+ content-type: application/yaml
86
+
87
+ - 10cf16b458f759e0d617f2f3d83599ff
88
+ - 814a0034f5549e957ee61360d87457e5
89
+ """
90
+ When the following request is received:
91
+ """
92
+ GET / HTTP/1.1
93
+ accept: application/vnd.toa.octets.entries+yaml
94
+ """
95
+ Then the following reply is sent:
96
+ """
97
+ 200 OK
98
+ content-type: application/yaml
99
+
100
+ - id: 10cf16b458f759e0d617f2f3d83599ff
101
+ size: 8169
102
+ type: application/octet-stream
103
+ - id: 814a0034f5549e957ee61360d87457e5
104
+ size: 473831
105
+ type: image/png
106
+ """
107
+ When the following request is received:
108
+ """
109
+ GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
110
+ accept: application/vnd.toa.octets.entry+yaml
111
+ """
112
+ Then the following reply is sent:
113
+ """
114
+ 200 OK
115
+ content-type: application/yaml
116
+ content-length: 124
117
+
118
+ id: 10cf16b458f759e0d617f2f3d83599ff
119
+ type: application/octet-stream
120
+ size: 8169
121
+ """
@@ -70,17 +70,6 @@ Feature: Octets directive family
70
70
  """
71
71
  304 Not Modified
72
72
  """
73
- When the following request is received:
74
- """
75
- GET /10cf16b458f759e0d617f2f3d83599ff:meta HTTP/1.1
76
- accept: text/plain
77
- """
78
- Then the following reply is sent:
79
- """
80
- 403 Forbidden
81
-
82
- Metadata is not accessible.
83
- """
84
73
  When the following request is received:
85
74
  """
86
75
  GET / HTTP/1.1
@@ -245,7 +234,7 @@ Feature: Octets directive family
245
234
  Trailing slash is redundant.
246
235
  """
247
236
 
248
- Scenario: Accessing an Entry and the original BLOLB
237
+ Scenario: Original BLOLB is not accessible
249
238
  Given the annotation:
250
239
  """yaml
251
240
  /:
@@ -267,21 +256,6 @@ Feature: Octets directive family
267
256
  """
268
257
  201 Created
269
258
  """
270
- When the following request is received:
271
- """
272
- GET /10cf16b458f759e0d617f2f3d83599ff:meta HTTP/1.1
273
- accept: application/yaml
274
- """
275
- Then the following reply is sent:
276
- """
277
- 200 OK
278
- content-type: application/yaml
279
- content-length: 124
280
-
281
- id: 10cf16b458f759e0d617f2f3d83599ff
282
- type: application/octet-stream
283
- size: 8169
284
- """
285
259
  When the following request is received:
286
260
  """
287
261
  GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
@@ -0,0 +1,65 @@
1
+ Feature: Octets `content-meta` header
2
+
3
+ Scenario: Sending `content-meta` header
4
+ Given the `octets.tester` is running
5
+ And the annotation:
6
+ """yaml
7
+ /:
8
+ auth:anonymous: true
9
+ octets:context: octets
10
+ /*:
11
+ POST:
12
+ octets:store: ~
13
+ /*:
14
+ GET:
15
+ octets:fetch:
16
+ meta: true
17
+ """
18
+ When the stream of `lenna.ascii` is received with the following headers:
19
+ """
20
+ POST /meta-header/ HTTP/1.1
21
+ content-type: application/octet-stream
22
+ content-meta: foo, bar=baz=1
23
+ content-meta: baz=1
24
+ """
25
+ Then the following reply is sent:
26
+ """
27
+ 201 Created
28
+ """
29
+ When the following request is received:
30
+ """
31
+ GET /meta-header/10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
32
+ accept: application/vnd.toa.octets.entry+yaml
33
+ """
34
+ Then the following reply is sent:
35
+ """
36
+ 200 OK
37
+
38
+ id: 10cf16b458f759e0d617f2f3d83599ff
39
+ type: application/octet-stream
40
+ size: 8169
41
+ meta:
42
+ foo: 'true'
43
+ bar: baz=1
44
+ baz: '1'
45
+ """
46
+
47
+ Scenario: CORS allows `content-meta` header
48
+ Given the annotation:
49
+ """yaml
50
+ /:
51
+ octets:context: octets
52
+ POST:
53
+ octets:store: ~
54
+ """
55
+ When the following request is received:
56
+ """
57
+ OPTIONS / HTTP/1.1
58
+ origin: http://example.com
59
+ """
60
+ Then the following reply is sent:
61
+ """
62
+ 204 No Content
63
+ access-control-allow-origin: http://example.com
64
+ access-control-allow-headers: accept, authorization, content-type, content-meta
65
+ """
@@ -2,7 +2,7 @@ Feature: Octets storage workflows
2
2
 
3
3
  Scenario: Running a workflow
4
4
  Given the `octets.tester` is running
5
- Given the annotation:
5
+ And the annotation:
6
6
  """yaml
7
7
  /:
8
8
  auth:anonymous: true
@@ -47,8 +47,8 @@ Feature: Octets storage workflows
47
47
  """
48
48
  When the following request is received:
49
49
  """
50
- GET /10cf16b458f759e0d617f2f3d83599ff:meta HTTP/1.1
51
- accept: application/yaml
50
+ GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
51
+ accept: application/vnd.toa.octets.entry+yaml
52
52
  """
53
53
  Then the following reply is sent:
54
54
  """
@@ -74,7 +74,7 @@ Feature: Octets storage workflows
74
74
  content-length: 473831
75
75
  """
76
76
 
77
- Scenario: Getting error when adding metadata to a file
77
+ Scenario: Getting error when running workflow on `store`
78
78
  Given the `octets.tester` is running
79
79
  Given the annotation:
80
80
  """yaml
@@ -112,3 +112,104 @@ Feature: Octets storage workflows
112
112
  message: Something went wrong
113
113
  --cut--
114
114
  """
115
+
116
+ Scenario: Running a workflow on `delete`
117
+ Given the `octets.tester` is running
118
+ And the annotation:
119
+ """yaml
120
+ /:
121
+ auth:anonymous: true
122
+ octets:context: octets
123
+ POST:
124
+ octets:store: ~
125
+ /*:
126
+ GET:
127
+ octets:fetch: ~
128
+ DELETE:
129
+ octets:delete:
130
+ workflow:
131
+ echo: octets.tester.echo
132
+ """
133
+ When the stream of `lenna.ascii` is received with the following headers:
134
+ """
135
+ POST / HTTP/1.1
136
+ content-type: application/octet-stream
137
+ """
138
+ Then the following reply is sent:
139
+ """
140
+ 201 Created
141
+ """
142
+ When the following request is received:
143
+ """
144
+ DELETE /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
145
+ accept: application/yaml
146
+ """
147
+ Then the following reply is sent:
148
+ """
149
+ 202 Accepted
150
+ content-type: multipart/yaml; boundary=cut
151
+
152
+ --cut
153
+ echo: 10cf16b458f759e0d617f2f3d83599ff
154
+ --cut--
155
+ """
156
+ When the following request is received:
157
+ """
158
+ GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
159
+ """
160
+ Then the following reply is sent:
161
+ """
162
+ 404 Not Found
163
+ """
164
+
165
+ Scenario: Error in the workflow on `delete`
166
+ Given the `octets.tester` is running
167
+ And the annotation:
168
+ """yaml
169
+ /:
170
+ auth:anonymous: true
171
+ octets:context: octets
172
+ POST:
173
+ octets:store: ~
174
+ /*:
175
+ GET:
176
+ octets:fetch: ~
177
+ DELETE:
178
+ octets:delete:
179
+ workflow:
180
+ err: octets.tester.err
181
+ """
182
+ When the stream of `lenna.ascii` is received with the following headers:
183
+ """
184
+ POST / HTTP/1.1
185
+ content-type: application/octet-stream
186
+ """
187
+ Then the following reply is sent:
188
+ """
189
+ 201 Created
190
+ """
191
+ When the following request is received:
192
+ """
193
+ DELETE /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
194
+ accept: application/yaml
195
+ """
196
+ Then the following reply is sent:
197
+ """
198
+ 202 Accepted
199
+ content-type: multipart/yaml; boundary=cut
200
+
201
+ --cut
202
+ error:
203
+ step: err
204
+ code: ERROR
205
+ message: Something went wrong
206
+ --cut--
207
+ """
208
+ When the following request is received:
209
+ """
210
+ GET /10cf16b458f759e0d617f2f3d83599ff HTTP/1.1
211
+ """
212
+ Then the following reply is sent:
213
+ """
214
+ 200 OK
215
+ """
@@ -87,3 +87,40 @@ Feature: Routes
87
87
 
88
88
  Hello
89
89
  """
90
+
91
+ Scenario: Routes with naming conflicts
92
+ Given the Gateway is running
93
+ And the `users` is running with the following manifest:
94
+ """yaml
95
+ exposition:
96
+ /:
97
+ POST: create
98
+ """
99
+ And the `users.properties` is running with the following manifest:
100
+ """yaml
101
+ exposition:
102
+ /:id:
103
+ GET: observe
104
+ """
105
+ When the following request is received:
106
+ """
107
+ GET /users/properties/b5534021e30042259badffbd1831e472/ HTTP/1.1
108
+ accept: application/yaml
109
+ """
110
+ Then the following reply is sent:
111
+ """
112
+ 200 OK
113
+
114
+ newbie: false
115
+ """
116
+ When the following request is received:
117
+ """
118
+ POST /users/ HTTP/1.1
119
+ content-type: application/yaml
120
+
121
+ name: Alice
122
+ """
123
+ Then the following reply is sent:
124
+ """
125
+ 201 Created
126
+ """
@@ -1,5 +1,6 @@
1
- import * as http from '@toa.io/http'
1
+ import * as http from '@toa.io/agent'
2
2
  import { binding } from 'cucumber-tsflow'
3
3
 
4
4
  @binding()
5
- export class Captures extends http.Captures {}
5
+ export class Captures extends http.Captures {
6
+ }
@@ -9,7 +9,7 @@ import { Workspace } from './Workspace'
9
9
  @binding([Workspace])
10
10
  export class Components {
11
11
  private readonly workspace: Workspace
12
- private composition: Connector | null = null
12
+ private compositions: Record<string, Connector> = {}
13
13
 
14
14
  public constructor (workspace: Workspace) {
15
15
  this.workspace = workspace
@@ -27,22 +27,29 @@ export class Components {
27
27
  await this.runComponent(name, manifest)
28
28
  }
29
29
 
30
- @after()
31
30
  @given('the `{word}` is stopped')
32
- public async stop (_?: string): Promise<void> {
33
- await this.composition?.disconnect()
31
+ public async stop (name: string): Promise<void> {
32
+ assert.ok(name in this.compositions, `Composition '${name}' is not running`)
33
+
34
+ await this.compositions[name].disconnect()
35
+ delete this.compositions[name]
36
+ }
37
+
38
+ @after()
39
+ public async shutdown (): Promise<void> {
40
+ const promises = Object.values(this.compositions).map((composition) => composition.disconnect())
34
41
 
35
- this.composition = null
42
+ await Promise.all(promises)
36
43
  }
37
44
 
38
45
  private async runComponent (name: string, manifest?: object): Promise<void> {
39
- assert.ok(this.composition === null, 'Composition is already running')
46
+ assert.ok(!(name in this.compositions), `Composition '${name}' is already running`)
40
47
 
41
48
  const path = await this.workspace.addComponent(name, manifest)
42
49
 
43
- this.composition = await boot.composition([path])
50
+ this.compositions[name] = await boot.composition([path])
44
51
 
45
- await this.composition.connect()
52
+ await this.compositions[name].connect()
46
53
  await timeout(50) // discovery
47
54
  }
48
55
  }
@@ -2,7 +2,7 @@ import * as assert from 'node:assert'
2
2
  import * as fs from 'node:fs'
3
3
  import * as path from 'node:path'
4
4
  import { binding, then, when } from 'cucumber-tsflow'
5
- import * as http from '@toa.io/http'
5
+ import * as http from '@toa.io/agent'
6
6
  import * as msgpack from 'msgpackr'
7
7
  import * as YAML from 'js-yaml'
8
8
  import { Captures } from './Captures'
@@ -16,6 +16,6 @@ process.env.TOA_DEV = '1'
16
16
  process.env.TOA_STORAGES = encode({
17
17
  octets: {
18
18
  provider: 'tmp',
19
- prefix: 'test'
19
+ directory: 'exposition'
20
20
  }
21
21
  })
@@ -12,4 +12,5 @@ operations:
12
12
  bar: *operation
13
13
  baz: *operation
14
14
  err: *operation
15
+ echo: *operation
15
16
  diversify: *operation
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ async function baz (input) {
4
+ return input.entry.id
5
+ }
6
+
7
+ exports.computation = baz
@@ -9,3 +9,6 @@ operations:
9
9
  concurrency: retry
10
10
  input:
11
11
  name*: ~
12
+ create:
13
+ query: false
14
+ forward: transit
@@ -0,0 +1,13 @@
1
+ namespace: users
2
+ name: properties
3
+
4
+ entity:
5
+ schema:
6
+ newbie: false
7
+ dependent: true
8
+
9
+ operations:
10
+ transit:
11
+ concurrency: retry
12
+ input:
13
+ newbie*: .
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ESNext",
4
- "outDir": "/dev/null",
4
+ "noEmit": true,
5
5
  "moduleResolution": "node",
6
6
  "experimentalDecorators": true,
7
7
  "emitDecoratorMetadata": true
@@ -146,5 +146,5 @@ Feature: The Vary directive family
146
146
  Then the following reply is sent:
147
147
  """
148
148
  204 No Content
149
- access-control-allow-headers: accept, content-type, accept-language, foo, bar
149
+ access-control-allow-headers: accept, authorization, content-type, accept-language, foo, bar
150
150
  """
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/extensions.exposition",
3
- "version": "0.24.0-alpha.21",
3
+ "version": "0.24.0-alpha.23",
4
4
  "description": "Toa Exposition",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -17,10 +17,10 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "@toa.io/core": "0.24.0-alpha.21",
21
- "@toa.io/generic": "0.24.0-alpha.21",
22
- "@toa.io/schemas": "0.24.0-alpha.21",
23
- "@toa.io/streams": "0.24.0-alpha.21",
20
+ "@toa.io/core": "0.24.0-alpha.23",
21
+ "@toa.io/generic": "0.24.0-alpha.23",
22
+ "@toa.io/schemas": "0.24.0-alpha.23",
23
+ "@toa.io/streams": "0.24.0-alpha.23",
24
24
  "bcryptjs": "2.4.3",
25
25
  "error-value": "0.3.0",
26
26
  "express": "4.18.2",
@@ -45,12 +45,12 @@
45
45
  "features": "cucumber-js"
46
46
  },
47
47
  "devDependencies": {
48
- "@toa.io/extensions.storages": "0.24.0-alpha.21",
49
- "@toa.io/http": "0.24.0-alpha.21",
48
+ "@toa.io/agent": "0.24.0-alpha.23",
49
+ "@toa.io/extensions.storages": "0.24.0-alpha.23",
50
50
  "@types/bcryptjs": "2.4.3",
51
51
  "@types/cors": "2.8.13",
52
52
  "@types/express": "4.17.17",
53
53
  "@types/negotiator": "0.6.1"
54
54
  },
55
- "gitHead": "b30bbcf178be9339914e2e5203c61c0da2c3daf2"
55
+ "gitHead": "df9de3cbb530e8f985a660bca0bf65bd027dbb01"
56
56
  }
@@ -1 +1,2 @@
1
- ~
1
+ workflow+: <string>
2
+ _: true
@@ -1 +1,2 @@
1
- ~
1
+ meta: boolean
2
+ _: true