@adobe/aio-lib-sandbox 0.1.0-alpha.8 → 0.1.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/aio-lib-sandbox",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.0-alpha.9",
4
4
  "description": "JavaScript SDK for Adobe Runtime Sandboxes",
5
5
  "main": "src/index.js",
6
6
  "license": "Apache-2.0",
package/src/Sandbox.js CHANGED
@@ -23,7 +23,7 @@ const {
23
23
  normalizeSize,
24
24
  apiRequest
25
25
  } = require('./utils')
26
- const { SANDBOX_SIZES } = require('./constants')
26
+ const { SANDBOX_SIZES, PROTOCOL_VERSION, API_PREFIX } = require('./constants')
27
27
  const { SandboxSocket } = require('./ws')
28
28
 
29
29
  /**
@@ -44,6 +44,7 @@ class Sandbox {
44
44
  this.region = options.region
45
45
  this.idleTimeout = options.idleTimeout
46
46
  this.maxLifetime = options.maxLifetime
47
+ this.protocolVersion = options.protocolVersion || PROTOCOL_VERSION
47
48
 
48
49
  this.namespace = options.namespace
49
50
  this.apiHost = options.apiHost
@@ -98,7 +99,7 @@ class Sandbox {
98
99
  if (options.policy !== undefined) body.policy = options.policy
99
100
  if (options.ports !== undefined) body.ports = options.ports
100
101
 
101
- const url = `${creds.apiHost}/api/v1/namespaces/${creds.namespace}/sandboxes`
102
+ const url = `${creds.apiHost}${API_PREFIX}/namespaces/${creds.namespace}/sandboxes`
102
103
  const payload = await apiRequest('POST', url, creds.apiKey, body)
103
104
 
104
105
  const sandboxId = payload.sandboxId
@@ -112,6 +113,7 @@ class Sandbox {
112
113
  region: payload.region,
113
114
  idleTimeout: payload.idleTimeout,
114
115
  maxLifetime: payload.maxLifetime,
116
+ protocolVersion: payload.protocolVersion || PROTOCOL_VERSION,
115
117
  previewUrls: parsePreviewUrls(payload.previewUrls),
116
118
  managementEndpoint: payload.managementEndpoint || null,
117
119
  namespace: creds.namespace,
@@ -146,7 +148,7 @@ class Sandbox {
146
148
  console.warn('[aio-lib-sandbox] alpha — APIs may change without notice')
147
149
  const creds = resolveCredentials(options)
148
150
  const base = options.managementEndpoint || creds.apiHost
149
- const url = `${base}/api/v1/namespaces/${creds.namespace}/sandboxes/${sandboxId}`
151
+ const url = `${base}${API_PREFIX}/namespaces/${creds.namespace}/sandboxes/${sandboxId}`
150
152
  const payload = await apiRequest('GET', url, creds.apiKey)
151
153
 
152
154
  return new Sandbox({
@@ -157,6 +159,7 @@ class Sandbox {
157
159
  region: payload.region,
158
160
  idleTimeout: payload.idleTimeout,
159
161
  maxLifetime: payload.maxLifetime,
162
+ protocolVersion: payload.protocolVersion || PROTOCOL_VERSION,
160
163
  managementEndpoint: payload.managementEndpoint || options.managementEndpoint || null,
161
164
  previewUrls: parsePreviewUrls(payload.previewUrls),
162
165
  namespace: creds.namespace,
@@ -175,6 +178,15 @@ class Sandbox {
175
178
  return SANDBOX_SIZES
176
179
  }
177
180
 
181
+ /**
182
+ * Sandbox wire protocol major bundled with this SDK.
183
+ *
184
+ * @type {string}
185
+ */
186
+ static get protocolVersion () {
187
+ return PROTOCOL_VERSION
188
+ }
189
+
178
190
  /**
179
191
  * Exposes `resolveCredentials` as a static helper (useful for testing).
180
192
  *
@@ -507,7 +519,7 @@ class Sandbox {
507
519
  */
508
520
  async destroy () {
509
521
  const base = this.managementEndpoint || this.apiHost
510
- const url = `${base}/api/v1/namespaces/${this.namespace}/sandboxes/${this.id}`
522
+ const url = `${base}${API_PREFIX}/namespaces/${this.namespace}/sandboxes/${this.id}`
511
523
  this.ws?.beginIntentionalClose()
512
524
 
513
525
  let payload
package/src/constants.js CHANGED
@@ -16,4 +16,7 @@ const SANDBOX_SIZES = Object.freeze({
16
16
  XLARGE: { cpu: '8000m', memory: '32Gi', gpu: 1 }
17
17
  })
18
18
 
19
- module.exports = { SANDBOX_SIZES }
19
+ const PROTOCOL_VERSION = '1'
20
+ const API_PREFIX = `/api/v${PROTOCOL_VERSION}`
21
+
22
+ module.exports = { SANDBOX_SIZES, PROTOCOL_VERSION, API_PREFIX }
package/src/errors.js CHANGED
@@ -28,6 +28,8 @@ class SandboxWebSocketError extends SandboxSDKError {}
28
28
  class SandboxCommandNotFoundError extends SandboxSDKError {}
29
29
  class SandboxPortNotProvisionedError extends SandboxSDKError {}
30
30
  class SandboxInvalidPortError extends SandboxClientError {}
31
+ class ProtocolVersionMismatchError extends SandboxClientError {}
32
+ class SandboxMalformedFrameError extends SandboxClientError {}
31
33
 
32
34
  module.exports = {
33
35
  SandboxSDKError,
@@ -39,5 +41,7 @@ module.exports = {
39
41
  SandboxWebSocketError,
40
42
  SandboxCommandNotFoundError,
41
43
  SandboxPortNotProvisionedError,
42
- SandboxInvalidPortError
44
+ SandboxInvalidPortError,
45
+ ProtocolVersionMismatchError,
46
+ SandboxMalformedFrameError
43
47
  }
package/src/index.js CHANGED
@@ -10,6 +10,7 @@ governing permissions and limitations under the License.
10
10
  */
11
11
 
12
12
  const Sandbox = require('./Sandbox')
13
+ const { PROTOCOL_VERSION } = require('./constants')
13
14
  const {
14
15
  SandboxSDKError,
15
16
  SandboxInitializationError,
@@ -20,11 +21,14 @@ const {
20
21
  SandboxWebSocketError,
21
22
  SandboxCommandNotFoundError,
22
23
  SandboxPortNotProvisionedError,
23
- SandboxInvalidPortError
24
+ SandboxInvalidPortError,
25
+ ProtocolVersionMismatchError,
26
+ SandboxMalformedFrameError
24
27
  } = require('./errors')
25
28
 
26
29
  module.exports = {
27
30
  Sandbox,
31
+ SANDBOX_PROTOCOL_VERSION: PROTOCOL_VERSION,
28
32
  SandboxSDKError,
29
33
  SandboxInitializationError,
30
34
  SandboxClientError,
@@ -34,5 +38,7 @@ module.exports = {
34
38
  SandboxWebSocketError,
35
39
  SandboxCommandNotFoundError,
36
40
  SandboxPortNotProvisionedError,
37
- SandboxInvalidPortError
41
+ SandboxInvalidPortError,
42
+ ProtocolVersionMismatchError,
43
+ SandboxMalformedFrameError
38
44
  }
package/src/utils.js CHANGED
@@ -16,7 +16,7 @@ const {
16
16
  SandboxUnauthorizedError,
17
17
  SandboxTimeoutError
18
18
  } = require('./errors')
19
- const { SANDBOX_SIZES } = require('./constants')
19
+ const { SANDBOX_SIZES, API_PREFIX } = require('./constants')
20
20
 
21
21
  /**
22
22
  * Builds a Basic authorization header from a Runtime API key.
@@ -72,7 +72,7 @@ function normalizeApiHost (host) {
72
72
  function buildWebSocketEndpoint (apiHost, namespace, sandboxId) {
73
73
  const url = new URL(apiHost)
74
74
  url.protocol = url.protocol === 'http:' ? 'ws:' : 'wss:'
75
- url.pathname = `/api/v1/namespaces/${namespace}/sandboxes/${sandboxId}/exec`
75
+ url.pathname = `${API_PREFIX}/namespaces/${namespace}/sandboxes/${sandboxId}/exec`
76
76
  url.search = ''
77
77
  return url.toString()
78
78
  }
package/src/ws.js CHANGED
@@ -13,6 +13,8 @@ const WebSocket = require('ws')
13
13
  const {
14
14
  SandboxClientError,
15
15
  SandboxCommandNotFoundError,
16
+ ProtocolVersionMismatchError,
17
+ SandboxMalformedFrameError,
16
18
  SandboxUnauthorizedError,
17
19
  SandboxWebSocketError
18
20
  } = require('./errors')
@@ -355,6 +357,16 @@ class SandboxSocket {
355
357
  `Sandbox '${this.id}' rejected the WebSocket authentication token`
356
358
  )
357
359
  }
360
+ if (code === 4003) {
361
+ return new ProtocolVersionMismatchError(
362
+ `Sandbox '${this.id}' WebSocket protocol version does not match this SDK`
363
+ )
364
+ }
365
+ if (code === 4004) {
366
+ return new SandboxMalformedFrameError(
367
+ `Sandbox '${this.id}' rejected a malformed WebSocket frame`
368
+ )
369
+ }
358
370
  return new SandboxWebSocketError(
359
371
  `Sandbox '${this.id}' WebSocket closed with code ${code}`
360
372
  )
@@ -17,11 +17,13 @@ const {
17
17
  SandboxCommandNotFoundError,
18
18
  SandboxInitializationError,
19
19
  SandboxNotFoundError,
20
+ ProtocolVersionMismatchError,
20
21
  SandboxPortNotProvisionedError,
21
22
  SandboxInvalidPortError,
22
23
  SandboxTimeoutError,
23
24
  SandboxUnauthorizedError,
24
- SandboxWebSocketError
25
+ SandboxWebSocketError,
26
+ SandboxMalformedFrameError
25
27
  } = require('../src/errors')
26
28
 
27
29
  jest.mock('ws')
@@ -199,6 +201,12 @@ describe('Sandbox', () => {
199
201
  })
200
202
  })
201
203
 
204
+ describe('protocolVersion', () => {
205
+ test('exposes the bundled sandbox protocol major', () => {
206
+ expect(Sandbox.protocolVersion).toBe('1')
207
+ })
208
+ })
209
+
202
210
  // -------------------------------------------------------------------------
203
211
  // Static factories
204
212
  // -------------------------------------------------------------------------
@@ -213,6 +221,7 @@ describe('Sandbox', () => {
213
221
  status: 'ready',
214
222
  token: 'tok-new',
215
223
  maxLifetime: 3600,
224
+ protocolVersion: '1',
216
225
  previewUrls: {
217
226
  3000: 'https://sb-new-3000.preview.example.net'
218
227
  }
@@ -236,6 +245,7 @@ describe('Sandbox', () => {
236
245
 
237
246
  expect(sandbox.id).toBe('sb-new')
238
247
  expect(sandbox.status).toBe('ready')
248
+ expect(sandbox.protocolVersion).toBe('1')
239
249
  expect(sandbox.previewUrls).toEqual(new Map([
240
250
  [3000, 'https://sb-new-3000.preview.example.net']
241
251
  ]))
@@ -471,7 +481,8 @@ describe('Sandbox', () => {
471
481
  sandboxId: 'sb-get',
472
482
  status: 'running',
473
483
  cluster: 'cluster-b',
474
- region: 'va6'
484
+ region: 'va6',
485
+ protocolVersion: '1'
475
486
  })
476
487
  })
477
488
 
@@ -484,6 +495,7 @@ describe('Sandbox', () => {
484
495
  expect(sandbox.id).toBe('sb-get')
485
496
  expect(sandbox.status).toBe('running')
486
497
  expect(sandbox.cluster).toBe('cluster-b')
498
+ expect(sandbox.protocolVersion).toBe('1')
487
499
  })
488
500
 
489
501
  test('stores idleTimeout from the get response on the instance', async () => {
@@ -602,6 +614,22 @@ describe('Sandbox', () => {
602
614
  await expect(p).rejects.toThrow(SandboxUnauthorizedError)
603
615
  })
604
616
 
617
+ test('rejects on protocol mismatch close code 4003 with ProtocolVersionMismatchError', async () => {
618
+ const sandbox = new Sandbox(BASE_OPTIONS)
619
+ const p = sandbox.connect()
620
+ sockets[0].open()
621
+ sockets[0].closeWith(4003)
622
+ await expect(p).rejects.toThrow(ProtocolVersionMismatchError)
623
+ })
624
+
625
+ test('rejects on malformed frame close code 4004 with SandboxMalformedFrameError', async () => {
626
+ const sandbox = new Sandbox(BASE_OPTIONS)
627
+ const p = sandbox.connect()
628
+ sockets[0].open()
629
+ sockets[0].closeWith(4004)
630
+ await expect(p).rejects.toThrow(SandboxMalformedFrameError)
631
+ })
632
+
605
633
  test('rejects on unexpected socket close', async () => {
606
634
  const sandbox = new Sandbox(BASE_OPTIONS)
607
635
  const p = sandbox.connect()