@phpsandbox/sdk 0.3.3 → 0.3.5

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/dist/composer.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ProcessReadable, } from './shell.js';
1
+ import { ProcessReadable } from './shell.js';
2
2
  import { nanoid } from 'nanoid';
3
3
  class ComposerCredentials {
4
4
  constructor(client, notebookId) {
@@ -11,8 +11,9 @@ class ComposerCredentials {
11
11
  }
12
12
  async remove(type, url) {
13
13
  const params = new URLSearchParams({ type });
14
- if (url)
14
+ if (url) {
15
15
  params.set('url', url);
16
+ }
16
17
  await this.client.delete(`/notebook/${this.notebookId}/composer/credentials?${params.toString()}`);
17
18
  }
18
19
  }
@@ -52,10 +53,13 @@ export class ComposerProcess {
52
53
  stdout.fail(error);
53
54
  stderr.fail(error);
54
55
  };
55
- this.completion = this.okra.invoke('composer.invoke', { id, command, args, options }).then((result) => {
56
+ this.completion = this.okra
57
+ .invoke('composer.invoke', { id, command, args, options })
58
+ .then((result) => {
56
59
  finish();
57
60
  return result;
58
- }).catch((error) => {
61
+ })
62
+ .catch((error) => {
59
63
  fail(error);
60
64
  throw error;
61
65
  });
@@ -1,6 +1,6 @@
1
- export type RemoteErrorSource = 'core' | 'runtime';
1
+ export type RemoteErrorSource = 'core' | 'platform' | 'runtime';
2
2
  declare const remoteErrorCodes: readonly ["ActionNotFound", "AuthenticationRequired", "BadGateway", "BadRequest", "Conflict", "FileAlreadyExists", "FileIsDirectory", "FileNotDirectory", "FileNotFound", "FilesystemUnavailable", "InternalError", "InvalidArgument", "InvalidConfiguration", "InvalidRequest", "InvalidResponse", "InvalidServiceCommand", "MethodNotAllowed", "NotebookInitializationFailed", "NotebookUnavailable", "NotFound", "PayloadTooLarge", "PermissionDenied", "RateLimited", "RequestFailed", "RuntimeOperationFailed", "ServiceNotFound", "ServiceUnavailable", "UnprocessableEntity", "ValidationFailed", "WorkspaceUnavailable"];
3
- export type RemoteErrorCode = typeof remoteErrorCodes[number];
3
+ export type RemoteErrorCode = (typeof remoteErrorCodes)[number];
4
4
  export type TransportErrorCode = 'ConnectionFailed' | 'ConnectionTimeout' | 'InvalidResponse' | 'SendTimeout';
5
5
  export interface ValidationErrorDetails {
6
6
  errors: Record<string, string[]>;
@@ -94,9 +94,7 @@ function nonEmptyString(value) {
94
94
  return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
95
95
  }
96
96
  function record(value) {
97
- return value !== null && typeof value === 'object' && !Array.isArray(value)
98
- ? value
99
- : undefined;
97
+ return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
100
98
  }
101
99
  function stringArrayRecord(value) {
102
100
  const candidate = record(value);
package/dist/feedback.js CHANGED
@@ -18,8 +18,9 @@ export class Feedback {
18
18
  async list(options = {}) {
19
19
  const query = new URLSearchParams();
20
20
  for (const [name, value] of Object.entries(options)) {
21
- if (value !== undefined)
21
+ if (value !== undefined) {
22
22
  query.set(name, String(value));
23
+ }
23
24
  }
24
25
  return this.client.get(`${this.path()}${query.size === 0 ? '' : `?${query.toString()}`}`);
25
26
  }
@@ -80,11 +80,13 @@ export class Filesystem {
80
80
  const source = typeof contents === 'string' ? new TextEncoder().encode(contents) : contents;
81
81
  if (this.okra.runtimeTransport === 'rest') {
82
82
  const bytes = source instanceof Uint8Array ? source : await collectBytes(source);
83
- await this.okra.invoke('fs.writeFile', {
83
+ await this.okra
84
+ .invoke('fs.writeFile', {
84
85
  path,
85
86
  contents: bytes,
86
87
  options: resolvedOptions,
87
- }).catch((error) => this.handleError(error));
88
+ })
89
+ .catch((error) => this.handleError(error));
88
90
  return;
89
91
  }
90
92
  const id = nanoid();
@@ -166,13 +168,16 @@ export class Filesystem {
166
168
  disposable = this.okra.listen(`fs.read.${id}`, (event) => {
167
169
  controller.enqueue(event.data);
168
170
  });
169
- void this.okra.invoke('fs.readStream', { id, path }).then(() => {
171
+ void this.okra
172
+ .invoke('fs.readStream', { id, path })
173
+ .then(() => {
170
174
  if (!closed) {
171
175
  closed = true;
172
176
  disposable?.dispose();
173
177
  controller.close();
174
178
  }
175
- }).catch((error) => {
179
+ })
180
+ .catch((error) => {
176
181
  if (!closed) {
177
182
  closed = true;
178
183
  disposable?.dispose();
@@ -235,7 +240,9 @@ export class Filesystem {
235
240
  options.signal.addEventListener('abort', abort, { once: true });
236
241
  }
237
242
  started = true;
238
- void this.okra.invoke('fs.follow', { id, path, lines: options.lines ?? 10 }).then(() => {
243
+ void this.okra
244
+ .invoke('fs.follow', { id, path, lines: options.lines ?? 10 })
245
+ .then(() => {
239
246
  if (!closed) {
240
247
  closed = true;
241
248
  disposable?.dispose();
@@ -245,7 +252,8 @@ export class Filesystem {
245
252
  abort = null;
246
253
  controller.close();
247
254
  }
248
- }).catch((error) => {
255
+ })
256
+ .catch((error) => {
249
257
  if (!closed) {
250
258
  closed = true;
251
259
  disposable?.dispose();
@@ -340,7 +348,8 @@ export class Filesystem {
340
348
  .finally(() => disposable.dispose());
341
349
  }
342
350
  tail(path, options = {}) {
343
- return this.okra.invoke('fs.tail', { path, lines: options.lines ?? 10 })
351
+ return this.okra
352
+ .invoke('fs.tail', { path, lines: options.lines ?? 10 })
344
353
  .then(({ content }) => content)
345
354
  .catch((e) => this.handleError(e));
346
355
  }
@@ -348,31 +357,39 @@ export class Filesystem {
348
357
  return this.okra.invoke('fs.stat', { path }).catch((e) => this.handleError(e));
349
358
  }
350
359
  move(from, to, options = {}) {
351
- return this.okra.invoke('fs.rename', {
360
+ return this.okra
361
+ .invoke('fs.rename', {
352
362
  from,
353
363
  to,
354
364
  options: { overwrite: false, ...options },
355
- }).catch((e) => this.handleError(e));
365
+ })
366
+ .catch((e) => this.handleError(e));
356
367
  }
357
368
  remove(path, options = {}) {
358
- return this.okra.invoke('fs.delete', {
369
+ return this.okra
370
+ .invoke('fs.delete', {
359
371
  path,
360
372
  options: { recursive: false, useTrash: false, atomic: false, ...options },
361
- }).catch((e) => this.handleError(e));
373
+ })
374
+ .catch((e) => this.handleError(e));
362
375
  }
363
376
  copy(source, destination, options = {}) {
364
- return this.okra.invoke('fs.copy', {
377
+ return this.okra
378
+ .invoke('fs.copy', {
365
379
  source,
366
380
  destination,
367
381
  options: { overwrite: false, ...options },
368
- }).catch((e) => this.handleError(e));
382
+ })
383
+ .catch((e) => this.handleError(e));
369
384
  }
370
385
  list(path, options = {}) {
371
- return this.okra.invoke('fs.readDirectory', {
386
+ return this.okra
387
+ .invoke('fs.readDirectory', {
372
388
  path,
373
389
  include: options.include ?? [],
374
390
  exclude: options.exclude ?? [],
375
- }).catch((e) => this.handleError(e));
391
+ })
392
+ .catch((e) => this.handleError(e));
376
393
  }
377
394
  createDirectory(path) {
378
395
  return this.okra.invoke('fs.createDirectory', { path }).catch((e) => this.handleError(e));
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ export declare const identitySchema: z.ZodObject<{
3
+ user: z.ZodNullable<z.ZodObject<{
4
+ id: z.ZodString;
5
+ name: z.ZodString;
6
+ }, z.core.$strip>>;
7
+ organization: z.ZodObject<{
8
+ id: z.ZodString;
9
+ name: z.ZodString;
10
+ }, z.core.$strip>;
11
+ permissions: z.ZodArray<z.ZodString>;
12
+ }, z.core.$strip>;
13
+ export type Identity = z.infer<typeof identitySchema>;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export const identitySchema = z.object({
3
+ user: z.object({ id: z.string(), name: z.string() }).nullable(),
4
+ organization: z.object({ id: z.string(), name: z.string() }),
5
+ permissions: z.array(z.string()),
6
+ });
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import { type Identity } from './identity.js';
2
+ export type { Identity } from './identity.js';
1
3
  import { NotebookPublication } from './publication/index.js';
2
4
  import { Filesystem, FilesystemActions, FilesystemEvents } from './filesystem.js';
3
5
  import Terminals, { TerminalEvents, TerminalActions, type SpawnOptions } from './terminal.js';
4
- import Auth, { AuthActions } from './auth.js';
5
6
  import Lsp, { LspActions, LspEvents } from './lsp.js';
6
7
  import Composer, { ComposerActions, ComposerEvents } from './composer.js';
7
8
  import { LogEvents } from './log.js';
@@ -34,7 +35,7 @@ export type { ConfigPortMapping, ProjectConfig } from './config.js';
34
35
  export { PHPSandboxError, RemoteError, TransportError } from './errors/index.js';
35
36
  export type { HttpResponseDiagnostics, RemoteErrorCode, RemoteErrorSource, TransportErrorCode, ValidationErrorDetails, } from './errors/index.js';
36
37
  export * from './publication/index.js';
37
- export type { CreateServerInput, ServerData, ServerInstance, ServerListOptions, ServerMemberData, ServerSshOptions } from './servers.js';
38
+ export type { CreateServerInput, ServerData, ServerInstance, ServerListOptions, ServerMemberData, ServerInvitationData, ServerInvitationTarget, ServerOrganizationTarget, ShareServerInput, ServerSshOptions, } from './servers.js';
38
39
  export type { ConfigureFeedbackInput, FeedbackData, FeedbackListOptions, FeedbackSource, FeedbackStatus, FeedbackType, FeedbackWidgetConfig, FeedbackWidgetTarget, SubmitFeedbackInput, UpdateFeedbackInput, } from './feedback.js';
39
40
  export type { Integration, IntegrationAuthorization, IntegrationAuthorizationType, IntegrationData, IntegrationProvider, IntegrationReference, LinkIntegrationInput, UpdateIntegrationInput, AttachSandboxIntegrationInput, SandboxIntegration, SandboxIntegrationData, SandboxIntegrationEffect, SandboxIntegrationReference, UpdateSandboxIntegrationInput, } from './integrations/index.js';
40
41
  interface Result<TType extends 'success' | 'error' | 'running', TData extends object> {
@@ -108,7 +109,7 @@ export interface Action<Args = object, Response = void> {
108
109
  response: Response;
109
110
  }
110
111
  export type Events = TerminalEvents & RuntimeEvents & LspEvents & ComposerEvents & LogEvents & ServiceEvents & NotebookEvents & ReplEvents & ShellEvents & FilesystemEvents;
111
- export type Invokable = TerminalActions & RuntimeActions & FilesystemActions & AuthActions & LspActions & ComposerActions & ServiceActions & ConfigActions & ReplActions & ShellActions & GitActions;
112
+ export type Invokable = TerminalActions & RuntimeActions & FilesystemActions & LspActions & ComposerActions & ServiceActions & ConfigActions & ReplActions & ShellActions & GitActions;
112
113
  export interface CreateNotebookImportAuthInput {
113
114
  accessToken: string;
114
115
  }
@@ -364,6 +365,7 @@ export declare class PHPSandbox {
364
365
  readonly servers: ServerApi;
365
366
  readonly integrations: IntegrationApi;
366
367
  private constructor();
368
+ whoami(): Promise<Identity>;
367
369
  get runtimeTransport(): RuntimeTransport;
368
370
  static realtime(token: string, url?: string, options?: PHPSandboxClientOptions): PHPSandbox;
369
371
  static rest(token: string, url?: string, options?: PHPSandboxClientOptions): PHPSandbox;
@@ -387,7 +389,6 @@ export declare class NotebookInstance {
387
389
  protected client: Client;
388
390
  readonly files: Filesystem;
389
391
  readonly terminals: Terminals;
390
- readonly auth: Auth;
391
392
  readonly lsp: Lsp;
392
393
  readonly composer: Composer;
393
394
  readonly runtime: Runtime;
package/dist/index.js CHANGED
@@ -10,10 +10,10 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
12
  var _NotebookInstance_instances, _NotebookInstance_initPromise, _NotebookInstance_init;
13
+ import { identitySchema } from './identity.js';
13
14
  import { NotebookPublication } from './publication/index.js';
14
15
  import { Filesystem } from './filesystem.js';
15
16
  import Terminals from './terminal.js';
16
- import Auth from './auth.js';
17
17
  import Lsp from './lsp.js';
18
18
  import Composer from './composer.js';
19
19
  import Runtime from './runtime.js';
@@ -157,7 +157,7 @@ class ClientImplementation {
157
157
  headers: this.headers,
158
158
  }));
159
159
  if (!response.ok) {
160
- throw await responseError(response);
160
+ throw await responseError(response, path.startsWith('/platform/') ? 'platform' : 'core');
161
161
  }
162
162
  if (response.status === 204) {
163
163
  return { data: undefined };
@@ -195,10 +195,10 @@ class ClientImplementation {
195
195
  }
196
196
  }
197
197
  }
198
- async function responseError(response) {
198
+ async function responseError(response, source = 'core') {
199
199
  const body = await response.text();
200
200
  try {
201
- return remoteError('core', errorPayload(body === '' ? undefined : JSON.parse(body)), response);
201
+ return remoteError(source, errorPayload(body === '' ? undefined : JSON.parse(body)), response);
202
202
  }
203
203
  catch {
204
204
  return new TransportError(`PHPSandbox API returned an invalid error response (HTTP ${response.status}).`, 'InvalidResponse', response, {
@@ -221,6 +221,14 @@ export class PHPSandbox {
221
221
  this.servers = client.servers;
222
222
  this.integrations = client.integrations;
223
223
  }
224
+ async whoami() {
225
+ const { data } = await this.client.get('/auth/whoami');
226
+ const result = identitySchema.safeParse(data);
227
+ if (!result.success) {
228
+ throw new PHPSandboxError('Invalid identity response.');
229
+ }
230
+ return result.data;
231
+ }
224
232
  get runtimeTransport() {
225
233
  return this.client.runtimeTransport;
226
234
  }
@@ -269,7 +277,6 @@ export class NotebookInstance {
269
277
  }
270
278
  this.files = new Filesystem(this, this.socket === null ? null : (handler) => this.onDidConnect(handler));
271
279
  this.terminals = new Terminals(this);
272
- this.auth = new Auth(this);
273
280
  this.lsp = new Lsp(this);
274
281
  this.composer = new Composer(this, client);
275
282
  this.runtime = new Runtime(this);
@@ -476,7 +483,7 @@ export class NotebookInstance {
476
483
  // Wait for the socket to reconnect
477
484
  await whenConnected;
478
485
  // Re-initialize the notebook
479
- __classPrivateFieldGet(this, _NotebookInstance_instances, "m", _NotebookInstance_init).call(this);
486
+ __classPrivateFieldSet(this, _NotebookInstance_initPromise, __classPrivateFieldGet(this, _NotebookInstance_instances, "m", _NotebookInstance_init).call(this), "f");
480
487
  // Wait for initialization to complete
481
488
  return this.ready().then(() => this);
482
489
  }
@@ -524,8 +531,9 @@ class NotebookSecrets {
524
531
  }
525
532
  async list(options) {
526
533
  const params = new URLSearchParams();
527
- if (options?.environment)
534
+ if (options?.environment) {
528
535
  params.set('environment', options.environment);
536
+ }
529
537
  const query = params.toString();
530
538
  const response = await this.client.get(`/notebook/${this.notebookId}/secrets${query ? `?${query}` : ''}`);
531
539
  return response.data;
@@ -543,8 +551,9 @@ class NotebookSecrets {
543
551
  }
544
552
  async delete(name, options) {
545
553
  const params = new URLSearchParams();
546
- if (options?.environment)
554
+ if (options?.environment) {
547
555
  params.set('environment', options.environment);
556
+ }
548
557
  const query = params.toString();
549
558
  await this.client.delete(`/notebook/${this.notebookId}/secrets/${encodeURIComponent(name)}${query ? `?${query}` : ''}`);
550
559
  }
@@ -1,4 +1,4 @@
1
- import { Integration, integrationId, } from './account.js';
1
+ import { Integration, integrationId } from './account.js';
2
2
  export class SandboxIntegrationApi {
3
3
  constructor(notebookId, client) {
4
4
  this.notebookId = notebookId;
package/dist/lsp.d.ts CHANGED
@@ -47,8 +47,8 @@ export declare class LspConnection {
47
47
  onMessage(cb: (data: string) => void): Disposable;
48
48
  onError(cb: (message: string) => void): Disposable;
49
49
  onClose(cb: (code: number, reason: string) => void): Disposable;
50
- dispose(): void;
51
- start(): void;
50
+ dispose(): Promise<void>;
51
+ start(): Promise<void>;
52
52
  onClientDisconnect(cb: (code: number, message: string) => void): Disposable;
53
53
  whenSocketConnected(): Promise<NotebookInstance>;
54
54
  static create(id: string, lsp: Lsp): LspConnection;
package/dist/lsp.js CHANGED
@@ -51,10 +51,10 @@ export class LspConnection {
51
51
  return this.lsp.onClose(this.id, cb);
52
52
  }
53
53
  dispose() {
54
- this.lsp.close(this.id);
54
+ return this.lsp.close(this.id);
55
55
  }
56
56
  start() {
57
- this.lsp.start(this.id);
57
+ return this.lsp.start(this.id);
58
58
  }
59
59
  onClientDisconnect(cb) {
60
60
  return this.lsp.onClientDisconnect(cb);
@@ -51,6 +51,7 @@ export class PublicationInstance {
51
51
  const intervalMs = options.intervalMs ?? 1000;
52
52
  const timeoutMs = options.timeoutMs ?? 300000;
53
53
  const startedAt = Date.now();
54
+ // eslint-disable-next-line typescript/no-this-alias -- Polling starts with this instance and replaces it after each refresh.
54
55
  let current = this;
55
56
  while (!publicationStatusIsTerminal(current.data.status)) {
56
57
  if (Date.now() - startedAt > timeoutMs) {
@@ -41,8 +41,9 @@ export class NotebookPublication {
41
41
  /** Publish the exact app selection in a server-owned review. */
42
42
  async publish(input) {
43
43
  const application = (await this.client.post(`${this.path}/publication`, input)).data;
44
- if (!('confirmationRequired' in application))
44
+ if (!('confirmationRequired' in application)) {
45
45
  this.startApplicationRuns(application);
46
+ }
46
47
  return application;
47
48
  }
48
49
  async application(applicationId) {
@@ -60,10 +61,12 @@ export class NotebookPublication {
60
61
  }
61
62
  startApplicationRuns(application) {
62
63
  for (const app of application.apps) {
63
- if (!(application.selectedAppIds ?? []).includes(app.appId))
64
+ if (!(application.selectedAppIds ?? []).includes(app.appId)) {
64
65
  continue;
65
- if (!['pending', 'queued', 'building', 'deploying'].includes(app.publication.status))
66
+ }
67
+ if (!['pending', 'queued', 'building', 'deploying'].includes(app.publication.status)) {
66
68
  continue;
69
+ }
67
70
  new PublicationRun(new PublicationInstance(app.publication, this.client, this.notebookId), this.client).start();
68
71
  }
69
72
  }
@@ -72,7 +75,6 @@ export class NotebookPublication {
72
75
  if (serverId !== undefined) {
73
76
  query.set('serverId', serverId);
74
77
  }
75
- return (await this.client.get(`${this.path}/publication/catalog?${query}`))
76
- .data;
78
+ return (await this.client.get(`${this.path}/publication/catalog?${query}`)).data;
77
79
  }
78
80
  }
@@ -4,7 +4,8 @@ export class PublicationResources {
4
4
  this.path = path;
5
5
  }
6
6
  async inspect(id) {
7
- return (await this.client.post(`/publication-resources/${encodeURIComponent(id)}/inspect`, {})).data;
7
+ return (await this.client.post(`/publication-resources/${encodeURIComponent(id)}/inspect`, {}))
8
+ .data;
8
9
  }
9
10
  async list(options = {}) {
10
11
  const query = new URLSearchParams();
@@ -23,8 +23,9 @@ export async function* readPublicationStream(input, options = {}) {
23
23
  const lines = data;
24
24
  eventName = 'message';
25
25
  data = [];
26
- if (!lines.length || !PublishStreamSseEventNameSchema.safeParse(name).success)
26
+ if (!lines.length || !PublishStreamSseEventNameSchema.safeParse(name).success) {
27
27
  return null;
28
+ }
28
29
  const raw = lines.join('\n');
29
30
  let payload;
30
31
  try {
@@ -34,24 +35,30 @@ export async function* readPublicationStream(input, options = {}) {
34
35
  payload = raw;
35
36
  }
36
37
  const event = PublishStreamSseEventSchema.parse({ event: name, data: payload });
37
- if (event.type === 'result')
38
+ if (event.type === 'result') {
38
39
  receivedResult = true;
40
+ }
39
41
  return event;
40
42
  }
41
43
  function line(value) {
42
- if (value === '')
44
+ if (value === '') {
43
45
  return dispatch();
44
- if (value.startsWith(':'))
46
+ }
47
+ if (value.startsWith(':')) {
45
48
  return null;
49
+ }
46
50
  const colon = value.indexOf(':');
47
51
  const field = colon < 0 ? value : value.slice(0, colon);
48
52
  let content = colon < 0 ? '' : value.slice(colon + 1);
49
- if (content.startsWith(' '))
53
+ if (content.startsWith(' ')) {
50
54
  content = content.slice(1);
51
- if (field === 'event')
55
+ }
56
+ if (field === 'event') {
52
57
  eventName = content;
53
- if (field === 'data')
58
+ }
59
+ if (field === 'data') {
54
60
  data.push(content);
61
+ }
55
62
  return null;
56
63
  }
57
64
  try {
@@ -61,24 +68,28 @@ export async function* readPublicationStream(input, options = {}) {
61
68
  // A CR at the end of a chunk may be the first half of CRLF.
62
69
  let match;
63
70
  while ((match = /\r\n|\r|\n/.exec(buffer))) {
64
- if (!done && match[0] === '\r' && match.index === buffer.length - 1)
71
+ if (!done && match[0] === '\r' && match.index === buffer.length - 1) {
65
72
  break;
73
+ }
66
74
  const event = line(buffer.slice(0, match.index));
67
75
  buffer = buffer.slice(match.index + match[0].length);
68
- if (event)
76
+ if (event) {
69
77
  yield event;
78
+ }
70
79
  }
71
80
  if (done) {
72
81
  ended = true;
73
82
  if (buffer) {
74
83
  const event = line(buffer);
75
- if (event)
84
+ if (event) {
76
85
  yield event;
86
+ }
77
87
  }
78
88
  // Preserve the SDK's support for a final event without a trailing blank line.
79
89
  const event = dispatch();
80
- if (event)
90
+ if (event) {
81
91
  yield event;
92
+ }
82
93
  if (options.requireResult !== false && !receivedResult) {
83
94
  throw new PHPSandboxError('Publish stream ended without result');
84
95
  }
@@ -87,8 +98,9 @@ export async function* readPublicationStream(input, options = {}) {
87
98
  }
88
99
  }
89
100
  finally {
90
- if (!ended)
101
+ if (!ended) {
91
102
  await reader.cancel().catch(() => undefined);
103
+ }
92
104
  reader.releaseLock();
93
105
  }
94
106
  }
@@ -103,15 +115,16 @@ export function createPublicationStreamResponse(stream, options = {}) {
103
115
  let cancellation;
104
116
  let abort;
105
117
  async function dispose() {
106
- if (disposed)
118
+ if (disposed) {
107
119
  return;
120
+ }
108
121
  disposed = true;
109
122
  options.signal?.removeEventListener('abort', abort);
110
123
  reader.releaseLock();
111
124
  await options.onDispose?.();
112
125
  }
113
126
  function cancel(reason) {
114
- return cancellation ?? (cancellation = (async () => {
127
+ return (cancellation ?? (cancellation = (async () => {
115
128
  finished = true;
116
129
  try {
117
130
  await reader.cancel(reason);
@@ -119,7 +132,7 @@ export function createPublicationStreamResponse(stream, options = {}) {
119
132
  finally {
120
133
  await dispose();
121
134
  }
122
- })());
135
+ })()));
123
136
  }
124
137
  return new Response(new ReadableStream({
125
138
  start(controller) {
@@ -127,16 +140,19 @@ export function createPublicationStreamResponse(stream, options = {}) {
127
140
  controller.error(options.signal.reason);
128
141
  void cancel(options.signal.reason).catch(() => undefined);
129
142
  };
130
- if (options.signal?.aborted)
143
+ if (options.signal?.aborted) {
131
144
  abort();
132
- else
145
+ }
146
+ else {
133
147
  options.signal?.addEventListener('abort', abort, { once: true });
148
+ }
134
149
  },
135
150
  async pull(controller) {
136
151
  try {
137
152
  const { done, value } = await reader.read();
138
- if (finished)
153
+ if (finished) {
139
154
  return;
155
+ }
140
156
  if (done) {
141
157
  finished = true;
142
158
  await dispose();
@@ -147,8 +163,9 @@ export function createPublicationStreamResponse(stream, options = {}) {
147
163
  }
148
164
  }
149
165
  catch (error) {
150
- if (finished && cancellation)
166
+ if (finished && cancellation) {
151
167
  return;
168
+ }
152
169
  try {
153
170
  await cancel(error);
154
171
  }
@@ -194,7 +194,8 @@ function runtimeActionRequestBody(action, data, url, headers) {
194
194
  throw new TypeError('Runtime file contents must be binary data.');
195
195
  }
196
196
  headers['Content-Type'] = 'application/octet-stream';
197
- return Uint8Array.from(new Uint8Array(payload.contents.buffer, payload.contents.byteOffset, payload.contents.byteLength)).buffer;
197
+ return Uint8Array.from(new Uint8Array(payload.contents.buffer, payload.contents.byteOffset, payload.contents.byteLength))
198
+ .buffer;
198
199
  }
199
200
  headers['Content-Type'] = 'application/json';
200
201
  return JSON.stringify(data);
package/dist/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import Logs from './log.js';
2
2
  import Metrics from './metrics.js';
3
3
  import Ports from './ports.js';
4
- import { RuntimeTelemetry, } from './telemetry.js';
4
+ import { RuntimeTelemetry } from './telemetry.js';
5
5
  export class RuntimeMetrics {
6
6
  constructor(metrics) {
7
7
  this.metrics = metrics;