@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/README.md +19 -0
- package/dist/beacon/index.js +4 -2
- package/dist/beacon/navigator.js +0 -1
- package/dist/beacon/types.d.ts +1 -1
- package/dist/browser/phpsandbox-sdk.esm.js +345 -287
- package/dist/browser/phpsandbox-sdk.esm.min.js +9 -9
- package/dist/browser/phpsandbox-sdk.iife.js +345 -287
- package/dist/browser/phpsandbox-sdk.iife.min.js +9 -9
- package/dist/composer.js +8 -4
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.js +1 -3
- package/dist/feedback.js +2 -1
- package/dist/filesystem.js +32 -15
- package/dist/identity.d.ts +13 -0
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +17 -8
- package/dist/integrations/sandbox.js +1 -1
- package/dist/lsp.d.ts +2 -2
- package/dist/lsp.js +2 -2
- package/dist/publication/instance.js +1 -0
- package/dist/publication/notebook.js +7 -5
- package/dist/publication/resources.js +2 -1
- package/dist/publication/stream.js +36 -19
- package/dist/runtime/rest.js +2 -1
- package/dist/runtime.js +1 -1
- package/dist/schemas/publications.js +53 -59
- package/dist/servers.d.ts +31 -1
- package/dist/servers.js +34 -3
- package/dist/shell.js +5 -2
- package/dist/socket/index.js +25 -13
- package/dist/telemetry.js +8 -3
- package/dist/terminal.js +3 -4
- package/dist/utils/promise.js +1 -1
- package/dist/utils/websocket.js +2 -2
- package/package.json +44 -33
- package/dist/auth.d.ts +0 -11
- package/dist/auth.js +0 -12
package/dist/composer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProcessReadable
|
|
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
|
|
56
|
+
this.completion = this.okra
|
|
57
|
+
.invoke('composer.invoke', { id, command, args, options })
|
|
58
|
+
.then((result) => {
|
|
56
59
|
finish();
|
|
57
60
|
return result;
|
|
58
|
-
})
|
|
61
|
+
})
|
|
62
|
+
.catch((error) => {
|
|
59
63
|
fail(error);
|
|
60
64
|
throw error;
|
|
61
65
|
});
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -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[]>;
|
package/dist/errors/index.js
CHANGED
|
@@ -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
|
}
|
package/dist/filesystem.js
CHANGED
|
@@ -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
|
|
83
|
+
await this.okra
|
|
84
|
+
.invoke('fs.writeFile', {
|
|
84
85
|
path,
|
|
85
86
|
contents: bytes,
|
|
86
87
|
options: resolvedOptions,
|
|
87
|
-
})
|
|
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
|
|
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
|
-
})
|
|
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
|
|
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
|
-
})
|
|
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
|
|
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
|
|
360
|
+
return this.okra
|
|
361
|
+
.invoke('fs.rename', {
|
|
352
362
|
from,
|
|
353
363
|
to,
|
|
354
364
|
options: { overwrite: false, ...options },
|
|
355
|
-
})
|
|
365
|
+
})
|
|
366
|
+
.catch((e) => this.handleError(e));
|
|
356
367
|
}
|
|
357
368
|
remove(path, options = {}) {
|
|
358
|
-
return this.okra
|
|
369
|
+
return this.okra
|
|
370
|
+
.invoke('fs.delete', {
|
|
359
371
|
path,
|
|
360
372
|
options: { recursive: false, useTrash: false, atomic: false, ...options },
|
|
361
|
-
})
|
|
373
|
+
})
|
|
374
|
+
.catch((e) => this.handleError(e));
|
|
362
375
|
}
|
|
363
376
|
copy(source, destination, options = {}) {
|
|
364
|
-
return this.okra
|
|
377
|
+
return this.okra
|
|
378
|
+
.invoke('fs.copy', {
|
|
365
379
|
source,
|
|
366
380
|
destination,
|
|
367
381
|
options: { overwrite: false, ...options },
|
|
368
|
-
})
|
|
382
|
+
})
|
|
383
|
+
.catch((e) => this.handleError(e));
|
|
369
384
|
}
|
|
370
385
|
list(path, options = {}) {
|
|
371
|
-
return this.okra
|
|
386
|
+
return this.okra
|
|
387
|
+
.invoke('fs.readDirectory', {
|
|
372
388
|
path,
|
|
373
389
|
include: options.include ?? [],
|
|
374
390
|
exclude: options.exclude ?? [],
|
|
375
|
-
})
|
|
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>;
|
package/dist/identity.js
ADDED
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 &
|
|
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(
|
|
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
|
}
|
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
|
-
|
|
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`, {}))
|
|
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
|
-
|
|
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
|
-
|
|
55
|
+
}
|
|
56
|
+
if (field === 'event') {
|
|
52
57
|
eventName = content;
|
|
53
|
-
|
|
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
|
-
|
|
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
|
}
|
package/dist/runtime/rest.js
CHANGED
|
@@ -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))
|
|
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
|
|
4
|
+
import { RuntimeTelemetry } from './telemetry.js';
|
|
5
5
|
export class RuntimeMetrics {
|
|
6
6
|
constructor(metrics) {
|
|
7
7
|
this.metrics = metrics;
|