@phpsandbox/sdk 0.1.20 → 0.2.0
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/beacon/index.d.ts +2 -2
- package/dist/browser/phpsandbox-sdk.esm.js +16939 -16823
- package/dist/browser/phpsandbox-sdk.esm.min.js +35 -35
- package/dist/browser/phpsandbox-sdk.iife.js +16928 -16811
- package/dist/browser/phpsandbox-sdk.iife.min.js +24 -24
- package/dist/errors/index.d.ts +2 -2
- package/dist/events/index.d.ts +21 -15
- package/dist/events/index.js +9 -5
- package/dist/index.d.ts +9 -8
- package/dist/index.js +31 -34
- package/dist/publication/domains.d.ts +17 -0
- package/dist/publication/domains.js +25 -0
- package/dist/publication/index.d.ts +8 -0
- package/dist/publication/index.js +6 -0
- package/dist/publication/instance.d.ts +42 -0
- package/dist/publication/instance.js +133 -0
- package/dist/publication/notebook.d.ts +20 -0
- package/dist/publication/notebook.js +46 -0
- package/dist/publication/providers/laravel-cloud.d.ts +114 -0
- package/dist/publication/providers/laravel-cloud.js +13 -0
- package/dist/publication/resources.d.ts +9 -0
- package/dist/publication/resources.js +19 -0
- package/dist/publication/run.d.ts +30 -0
- package/dist/{publications.js → publication/run.js} +11 -133
- package/dist/publication/types.d.ts +303 -0
- package/dist/publication/types.js +1 -0
- package/dist/runtime/rest.d.ts +1 -1
- package/dist/schemas/publications.d.ts +33 -33
- package/dist/servers.d.ts +3 -0
- package/dist/servers.js +3 -0
- package/dist/socket/index.d.ts +4 -4
- package/dist/socket/index.js +5 -3
- package/package.json +1 -1
- package/dist/publications.d.ts +0 -192
package/dist/errors/index.d.ts
CHANGED
|
@@ -36,8 +36,8 @@ export interface HttpResponseDiagnostics {
|
|
|
36
36
|
}
|
|
37
37
|
export declare class TransportError<TCode extends TransportErrorCode = TransportErrorCode> extends PHPSandboxError {
|
|
38
38
|
readonly code: TCode;
|
|
39
|
-
readonly response?: HttpResponseDiagnostics;
|
|
40
|
-
constructor(message: string, code: TCode, cause?: unknown, response?: HttpResponseDiagnostics);
|
|
39
|
+
readonly response?: HttpResponseDiagnostics | undefined;
|
|
40
|
+
constructor(message: string, code: TCode, cause?: unknown, response?: HttpResponseDiagnostics | undefined);
|
|
41
41
|
static is(error: unknown): error is TransportError;
|
|
42
42
|
static is<TCode extends TransportErrorCode>(error: unknown, code: TCode): error is TransportError<TCode>;
|
|
43
43
|
is<TExpectedCode extends TransportErrorCode>(code: TExpectedCode): this is this & TransportError<TExpectedCode>;
|
package/dist/events/index.d.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import mitt from 'mitt';
|
|
2
2
|
import type { EventHandlerMap, EventType, Handler } from 'mitt';
|
|
3
3
|
import { Disposable } from '../types.js';
|
|
4
|
-
export interface EventDispatcher {
|
|
5
|
-
listen: (event:
|
|
6
|
-
once: (event:
|
|
7
|
-
emit:
|
|
8
|
-
|
|
4
|
+
export interface EventDispatcher<Events extends Record<EventType, unknown> = Record<EventType, unknown>> {
|
|
5
|
+
listen: <Key extends keyof Events>(event: Key, callback: Handler<Events[Key]>, context?: unknown) => Disposable;
|
|
6
|
+
once: <Key extends keyof Events>(event: Key, callback: Handler<Events[Key]>, context?: unknown) => Disposable;
|
|
7
|
+
emit: {
|
|
8
|
+
<Key extends keyof Events>(event: Key, payload: Events[Key]): void;
|
|
9
|
+
<Key extends keyof Events>(event: undefined extends Events[Key] ? Key : never): void;
|
|
10
|
+
};
|
|
11
|
+
removeListener: <Key extends keyof Events>(event?: Key, callbackSignature?: Handler<Events[Key]>) => void;
|
|
9
12
|
}
|
|
10
|
-
export declare function mittWithOnce<Events extends Record<EventType, unknown>>(all?: EventHandlerMap<Events>):
|
|
11
|
-
once<Key extends keyof Events>(type: Key,
|
|
13
|
+
export declare function mittWithOnce<Events extends Record<EventType, unknown>>(all?: EventHandlerMap<Events>): mitt.Emitter<Events> & {
|
|
14
|
+
once: <Key extends keyof Events>(type: Key, fn: Handler<Events[Key]>) => {
|
|
15
|
+
dispose: () => void;
|
|
16
|
+
};
|
|
12
17
|
};
|
|
13
|
-
export default class EventManager implements EventDispatcher {
|
|
18
|
+
export default class EventManager<Events extends Record<EventType, unknown> = Record<EventType, unknown>> implements EventDispatcher<Events> {
|
|
14
19
|
private readonly emitter;
|
|
15
|
-
listen(event:
|
|
16
|
-
emit(event:
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
listen<Key extends keyof Events>(event: Key, callback: Handler<Events[Key]>): Disposable;
|
|
21
|
+
emit<Key extends keyof Events>(event: Key, payload: Events[Key]): void;
|
|
22
|
+
emit<Key extends keyof Events>(event: undefined extends Events[Key] ? Key : never): void;
|
|
23
|
+
once<Key extends keyof Events>(event: Key, callback: Handler<Events[Key]>): Disposable;
|
|
24
|
+
static make<Events extends Record<EventType, unknown> = Record<EventType, unknown>>(): EventDispatcher<Events>;
|
|
19
25
|
static refresh(): EventDispatcher;
|
|
20
|
-
removeListener(event?:
|
|
26
|
+
removeListener<Key extends keyof Events>(event?: Key, callbackSignature?: Handler<Events[Key]>): void;
|
|
21
27
|
static createInstance(): EventDispatcher;
|
|
22
|
-
inspect(): EventHandlerMap<
|
|
28
|
+
inspect(): EventHandlerMap<Events>;
|
|
23
29
|
}
|
package/dist/events/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
const createMitt =
|
|
1
|
+
import mitt from 'mitt';
|
|
2
|
+
const createMitt = typeof mitt === 'function' ? mitt : mitt.default;
|
|
3
3
|
export function mittWithOnce(all) {
|
|
4
4
|
const inst = createMitt(all);
|
|
5
|
-
|
|
5
|
+
const once = (type, fn) => {
|
|
6
6
|
const onceHandler = (event) => {
|
|
7
7
|
inst.off(type, onceHandler);
|
|
8
8
|
fn(event);
|
|
@@ -14,7 +14,7 @@ export function mittWithOnce(all) {
|
|
|
14
14
|
},
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
|
-
return inst;
|
|
17
|
+
return Object.assign(inst, { once });
|
|
18
18
|
}
|
|
19
19
|
export default class EventManager {
|
|
20
20
|
constructor() {
|
|
@@ -28,7 +28,7 @@ export default class EventManager {
|
|
|
28
28
|
return { dispose };
|
|
29
29
|
}
|
|
30
30
|
emit(event, ...data) {
|
|
31
|
-
this.emitter.emit(event, data
|
|
31
|
+
this.emitter.emit(event, data[0]);
|
|
32
32
|
}
|
|
33
33
|
once(event, callback) {
|
|
34
34
|
return this.emitter.once(event, callback);
|
|
@@ -40,6 +40,10 @@ export default class EventManager {
|
|
|
40
40
|
return new EventManager();
|
|
41
41
|
}
|
|
42
42
|
removeListener(event, callbackSignature) {
|
|
43
|
+
if (event === undefined) {
|
|
44
|
+
this.emitter.all.clear();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
43
47
|
this.emitter.off(event, callbackSignature);
|
|
44
48
|
}
|
|
45
49
|
static createInstance() {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NotebookPublication } from './publication/index.js';
|
|
1
2
|
import { Filesystem, FilesystemActions, FilesystemEvents } from './filesystem.js';
|
|
2
3
|
import Terminals, { TerminalEvents, TerminalActions, type SpawnOptions } from './terminal.js';
|
|
3
4
|
import Auth, { AuthActions } from './auth.js';
|
|
@@ -12,13 +13,13 @@ import Config, { ConfigActions } from './config.js';
|
|
|
12
13
|
import Git, { GitActions, type GitSyncAuthor } from './git.js';
|
|
13
14
|
import { Disposable } from './types.js';
|
|
14
15
|
import { RemoteError } from './errors/index.js';
|
|
15
|
-
import { PublicationApi
|
|
16
|
+
import { PublicationApi } from './publication/index.js';
|
|
16
17
|
import { ServerApi } from './servers.js';
|
|
17
18
|
import { Feedback } from './feedback.js';
|
|
18
19
|
import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
|
|
19
20
|
export type { Disposable } from './types.js';
|
|
20
21
|
export { LspConnection } from './lsp.js';
|
|
21
|
-
export { FileChangeFilter, FileChangeType, FileType
|
|
22
|
+
export { FileChangeFilter, FileChangeType, FileType } from './filesystem.js';
|
|
22
23
|
export type { FileChange, FileContents, FileDeleteOptions, FileDownloadOptions, FileFollowOptions, FileLineRange, FileLineRangeResult, FileListOptions, FileOverwriteOptions, FileResult, FileSearchOptions, FileTailOptions, FileWriteOptions, Filesystem, Stats, TextSearchMatch, TextSearchOptions, TextSearchQuery, TextSearchResult, WatchOptions, } from './filesystem.js';
|
|
23
24
|
export type { PortInfo } from './runtime.js';
|
|
24
25
|
export type { RuntimeLogEntry } from './log.js';
|
|
@@ -30,9 +31,9 @@ export type { GitChangedFile, GitCheckoutResult, GitConflict, GitConflictsResult
|
|
|
30
31
|
export { notebookBuiltinServices, notebookKnownServices } from './services.js';
|
|
31
32
|
export type { NotebookBuiltinServiceName, NotebookKnownServiceName, NotebookServiceCommand, NotebookServiceKind, NotebookServiceName, NotebookServiceSource, NotebookServiceState, NotebookServiceStatus, ServiceLogOptions, ServiceLogStreamOptions, } from './services.js';
|
|
32
33
|
export type { ConfigPortMapping, ProjectConfig } from './config.js';
|
|
33
|
-
export { PHPSandboxError, RemoteError, TransportError
|
|
34
|
+
export { PHPSandboxError, RemoteError, TransportError } from './errors/index.js';
|
|
34
35
|
export type { HttpResponseDiagnostics, RemoteErrorCode, RemoteErrorSource, TransportErrorCode, ValidationErrorDetails, } from './errors/index.js';
|
|
35
|
-
export
|
|
36
|
+
export * from './publication/index.js';
|
|
36
37
|
export type { CreateServerInput, ServerData, ServerInstance, ServerListOptions, ServerSshOptions } from './servers.js';
|
|
37
38
|
export type { ConfigureFeedbackInput, FeedbackData, FeedbackListOptions, FeedbackSource, FeedbackStatus, FeedbackType, FeedbackWidgetConfig, FeedbackWidgetTarget, SubmitFeedbackInput, UpdateFeedbackInput, } from './feedback.js';
|
|
38
39
|
export type { Integration, IntegrationAuthorization, IntegrationAuthorizationType, IntegrationData, IntegrationProvider, IntegrationReference, LinkIntegrationInput, UpdateIntegrationInput, AttachSandboxIntegrationInput, SandboxIntegration, SandboxIntegrationData, SandboxIntegrationEffect, SandboxIntegrationReference, UpdateSandboxIntegrationInput, } from './integrations/index.js';
|
|
@@ -340,8 +341,8 @@ declare class ClientImplementation {
|
|
|
340
341
|
post<T extends unknown>(path: string, body?: unknown): Promise<{
|
|
341
342
|
data: T;
|
|
342
343
|
}>;
|
|
343
|
-
delete<T
|
|
344
|
-
data: T;
|
|
344
|
+
delete<T>(path: string): Promise<{
|
|
345
|
+
data: T | undefined;
|
|
345
346
|
}>;
|
|
346
347
|
put<T extends unknown>(path: string, body?: unknown): Promise<{
|
|
347
348
|
data: T;
|
|
@@ -351,6 +352,7 @@ declare class ClientImplementation {
|
|
|
351
352
|
}>;
|
|
352
353
|
stream(path: string): Promise<ReadableStream<Uint8Array>>;
|
|
353
354
|
sse(url: string, signal?: AbortSignal): Promise<ReadableStream<Uint8Array>>;
|
|
355
|
+
private requireData;
|
|
354
356
|
private makeRequest;
|
|
355
357
|
private fetchResponse;
|
|
356
358
|
}
|
|
@@ -399,6 +401,7 @@ export declare class NotebookInstance {
|
|
|
399
401
|
readonly preview: NotebookPreview;
|
|
400
402
|
readonly mail: NotebookMail;
|
|
401
403
|
readonly feedback: Feedback;
|
|
404
|
+
readonly publication: NotebookPublication;
|
|
402
405
|
private readonly socket;
|
|
403
406
|
private readonly restInvoker;
|
|
404
407
|
private readonly emitter;
|
|
@@ -410,8 +413,6 @@ export declare class NotebookInstance {
|
|
|
410
413
|
/** Update sandbox metadata and Git defaults without restarting it. */
|
|
411
414
|
update(input: UpdateNotebookInput): Promise<NotebookData>;
|
|
412
415
|
fork(input?: Partial<ForkNotebookInput>): Promise<NotebookInstance>;
|
|
413
|
-
publication(): Promise<PublicationInstance | null>;
|
|
414
|
-
publish(input?: PublishInput): Promise<PublicationRun>;
|
|
415
416
|
run(command: string | string[], opts?: SpawnOptions): ShellProcess;
|
|
416
417
|
run(command: string, args: string[], opts?: SpawnOptions): ShellProcess;
|
|
417
418
|
exec(command: string | string[], opts?: SpawnOptions): Promise<ProcessResult>;
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ 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 { NotebookPublication } from './publication/index.js';
|
|
13
14
|
import { Filesystem } from './filesystem.js';
|
|
14
15
|
import Terminals from './terminal.js';
|
|
15
16
|
import Auth from './auth.js';
|
|
@@ -23,17 +24,18 @@ import Config from './config.js';
|
|
|
23
24
|
import { Transport } from './socket/index.js';
|
|
24
25
|
import EventManager from './events/index.js';
|
|
25
26
|
import Git from './git.js';
|
|
26
|
-
import { PHPSandboxError, RemoteError, TransportError, remoteError
|
|
27
|
-
import { PublicationApi
|
|
27
|
+
import { PHPSandboxError, RemoteError, TransportError, remoteError } from './errors/index.js';
|
|
28
|
+
import { PublicationApi } from './publication/index.js';
|
|
28
29
|
import { ServerApi } from './servers.js';
|
|
29
30
|
import { RestRuntimeInvoker } from './runtime/rest.js';
|
|
30
31
|
import { Feedback } from './feedback.js';
|
|
31
32
|
import { IntegrationApi, SandboxIntegrationApi } from './integrations/index.js';
|
|
32
33
|
import { authenticatedRequest } from './http.js';
|
|
33
34
|
export { LspConnection } from './lsp.js';
|
|
34
|
-
export { FileChangeFilter, FileChangeType, FileType
|
|
35
|
+
export { FileChangeFilter, FileChangeType, FileType } from './filesystem.js';
|
|
35
36
|
export { notebookBuiltinServices, notebookKnownServices } from './services.js';
|
|
36
|
-
export { PHPSandboxError, RemoteError, TransportError
|
|
37
|
+
export { PHPSandboxError, RemoteError, TransportError } from './errors/index.js';
|
|
38
|
+
export * from './publication/index.js';
|
|
37
39
|
function normalizeNotebookSecretInputs(input) {
|
|
38
40
|
if (Array.isArray(input)) {
|
|
39
41
|
return input;
|
|
@@ -91,25 +93,25 @@ class ClientImplementation {
|
|
|
91
93
|
this.fetch = options.fetch;
|
|
92
94
|
}
|
|
93
95
|
this.headers = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
Accept: 'application/json',
|
|
97
|
+
Authorization: `Bearer ${token}`,
|
|
96
98
|
'Content-Type': 'application/json',
|
|
97
99
|
};
|
|
98
100
|
}
|
|
99
101
|
get(path) {
|
|
100
|
-
return this.makeRequest('GET', path);
|
|
102
|
+
return this.requireData(this.makeRequest('GET', path));
|
|
101
103
|
}
|
|
102
104
|
post(path, body) {
|
|
103
|
-
return this.makeRequest('POST', path, { body: body === undefined ? undefined : JSON.stringify(body) });
|
|
105
|
+
return this.requireData(this.makeRequest('POST', path, { body: body === undefined ? undefined : JSON.stringify(body) }));
|
|
104
106
|
}
|
|
105
107
|
delete(path) {
|
|
106
108
|
return this.makeRequest('DELETE', path);
|
|
107
109
|
}
|
|
108
110
|
put(path, body) {
|
|
109
|
-
return this.makeRequest('PUT', path, { body: body === undefined ? undefined : JSON.stringify(body) });
|
|
111
|
+
return this.requireData(this.makeRequest('PUT', path, { body: body === undefined ? undefined : JSON.stringify(body) }));
|
|
110
112
|
}
|
|
111
113
|
patch(path, body) {
|
|
112
|
-
return this.makeRequest('PATCH', path, { body: body === undefined ? undefined : JSON.stringify(body) });
|
|
114
|
+
return this.requireData(this.makeRequest('PATCH', path, { body: body === undefined ? undefined : JSON.stringify(body) }));
|
|
113
115
|
}
|
|
114
116
|
async stream(path) {
|
|
115
117
|
const response = await this.fetchResponse(authenticatedRequest(new URL(path.replace(/^\//, ''), this.baseUrl), {
|
|
@@ -129,7 +131,7 @@ class ClientImplementation {
|
|
|
129
131
|
method: 'GET',
|
|
130
132
|
headers: {
|
|
131
133
|
...this.headers,
|
|
132
|
-
|
|
134
|
+
Accept: 'text/event-stream',
|
|
133
135
|
},
|
|
134
136
|
...(signal === undefined ? {} : { signal }),
|
|
135
137
|
}));
|
|
@@ -141,6 +143,13 @@ class ClientImplementation {
|
|
|
141
143
|
}
|
|
142
144
|
return response.body;
|
|
143
145
|
}
|
|
146
|
+
async requireData(request) {
|
|
147
|
+
const response = await request;
|
|
148
|
+
if (response.data === undefined) {
|
|
149
|
+
throw new TransportError('PHPSandbox API returned no data for a data request.', 'InvalidResponse');
|
|
150
|
+
}
|
|
151
|
+
return { ...response, data: response.data };
|
|
152
|
+
}
|
|
144
153
|
async makeRequest(method, path, init) {
|
|
145
154
|
const response = await this.fetchResponse(authenticatedRequest(new URL(path.replace(/^\//, ''), this.baseUrl), {
|
|
146
155
|
method,
|
|
@@ -159,7 +168,10 @@ class ClientImplementation {
|
|
|
159
168
|
}
|
|
160
169
|
try {
|
|
161
170
|
const payload = JSON.parse(body);
|
|
162
|
-
if (payload === null ||
|
|
171
|
+
if (payload === null ||
|
|
172
|
+
typeof payload !== 'object' ||
|
|
173
|
+
Array.isArray(payload) ||
|
|
174
|
+
!Object.prototype.hasOwnProperty.call(payload, 'data')) {
|
|
163
175
|
throw new TransportError('PHPSandbox API returned an invalid success response.', 'InvalidResponse', response);
|
|
164
176
|
}
|
|
165
177
|
return payload;
|
|
@@ -234,9 +246,7 @@ export class NotebookInstance {
|
|
|
234
246
|
this.emitter = EventManager.createInstance();
|
|
235
247
|
if (client.runtimeTransport === 'rest') {
|
|
236
248
|
this.socket = null;
|
|
237
|
-
this.restInvoker = new RestRuntimeInvoker(data, client.options.fetch ?? globalThis.fetch, runtimeUrlProvider === undefined
|
|
238
|
-
? undefined
|
|
239
|
-
: () => runtimeUrlProvider(data.id));
|
|
249
|
+
this.restInvoker = new RestRuntimeInvoker(data, client.options.fetch ?? globalThis.fetch, runtimeUrlProvider === undefined ? undefined : () => runtimeUrlProvider(data.id));
|
|
240
250
|
}
|
|
241
251
|
else {
|
|
242
252
|
this.restInvoker = null;
|
|
@@ -273,6 +283,7 @@ export class NotebookInstance {
|
|
|
273
283
|
this.preview = new NotebookPreview(client, this.data.id);
|
|
274
284
|
this.mail = new NotebookMail(client, this.data.id);
|
|
275
285
|
this.feedback = new Feedback(client, this.data.id);
|
|
286
|
+
this.publication = new NotebookPublication(this.data.id, client);
|
|
276
287
|
}
|
|
277
288
|
async ready() {
|
|
278
289
|
if (this.restInvoker !== null) {
|
|
@@ -307,24 +318,6 @@ export class NotebookInstance {
|
|
|
307
318
|
const response = await this.client.post(`/notebook/${this.data.id}/fork`, input);
|
|
308
319
|
return new NotebookInstance(response.data, this.client);
|
|
309
320
|
}
|
|
310
|
-
async publication() {
|
|
311
|
-
try {
|
|
312
|
-
const response = await this.client.get(`/notebook/${this.data.id}/publication`);
|
|
313
|
-
return new PublicationInstance(response.data, this.client, this.data.id);
|
|
314
|
-
}
|
|
315
|
-
catch (error) {
|
|
316
|
-
if (RemoteError.is(error) && error.status === 404) {
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
throw error;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
async publish(input) {
|
|
323
|
-
const response = await this.client.post(`/notebook/${this.data.id}/publication`, input);
|
|
324
|
-
const run = new PublicationRun(new PublicationInstance(response.data, this.client, this.data.id), this.client);
|
|
325
|
-
run.start();
|
|
326
|
-
return run;
|
|
327
|
-
}
|
|
328
321
|
run(command, argsOrOpts = [], opts) {
|
|
329
322
|
if (Array.isArray(argsOrOpts)) {
|
|
330
323
|
return this.shell.run(command, argsOrOpts, opts);
|
|
@@ -447,7 +440,11 @@ export class NotebookInstance {
|
|
|
447
440
|
return disposable;
|
|
448
441
|
}
|
|
449
442
|
onDidBootError(handler) {
|
|
450
|
-
const disposable = this.realtimeSocket().listen('okra.boot_error',
|
|
443
|
+
const disposable = this.realtimeSocket().listen('okra.boot_error', (error) => {
|
|
444
|
+
if (RemoteError.is(error, 'NotebookUnavailable')) {
|
|
445
|
+
handler(error);
|
|
446
|
+
}
|
|
447
|
+
});
|
|
451
448
|
this.disposables.push(disposable);
|
|
452
449
|
return disposable;
|
|
453
450
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Client } from '../index.js';
|
|
2
|
+
import type { PublicationDomainData } from './types.js';
|
|
3
|
+
export declare class PublicationDomains {
|
|
4
|
+
private readonly client;
|
|
5
|
+
private readonly publicationId;
|
|
6
|
+
constructor(client: Client, publicationId: string);
|
|
7
|
+
list(): Promise<PublicationDomainData[]>;
|
|
8
|
+
create(hostname: string): Promise<PublicationDomainData>;
|
|
9
|
+
refresh(id: string): Promise<PublicationDomainData>;
|
|
10
|
+
/** Sets production APP_URL. Publish again to apply it to the running app. */
|
|
11
|
+
useAsApplicationUrl(id: string): Promise<{
|
|
12
|
+
url: string;
|
|
13
|
+
requiresPublication: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
delete(id: string): Promise<void>;
|
|
16
|
+
private path;
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class PublicationDomains {
|
|
2
|
+
constructor(client, publicationId) {
|
|
3
|
+
this.client = client;
|
|
4
|
+
this.publicationId = publicationId;
|
|
5
|
+
}
|
|
6
|
+
async list() {
|
|
7
|
+
return (await this.client.get(this.path())).data;
|
|
8
|
+
}
|
|
9
|
+
async create(hostname) {
|
|
10
|
+
return (await this.client.post(this.path(), { hostname })).data;
|
|
11
|
+
}
|
|
12
|
+
async refresh(id) {
|
|
13
|
+
return (await this.client.post(`${this.path()}/${encodeURIComponent(id)}/refresh`)).data;
|
|
14
|
+
}
|
|
15
|
+
/** Sets production APP_URL. Publish again to apply it to the running app. */
|
|
16
|
+
async useAsApplicationUrl(id) {
|
|
17
|
+
return (await this.client.post(`${this.path()}/${encodeURIComponent(id)}/application-url`)).data;
|
|
18
|
+
}
|
|
19
|
+
async delete(id) {
|
|
20
|
+
await this.client.delete(`${this.path()}/${encodeURIComponent(id)}`);
|
|
21
|
+
}
|
|
22
|
+
path() {
|
|
23
|
+
return `/publications/${encodeURIComponent(this.publicationId)}/domains`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { NotebookPublication } from './notebook.js';
|
|
2
|
+
export { PublicationApi, PublicationInstance } from './instance.js';
|
|
3
|
+
export { PublicationRun } from './run.js';
|
|
4
|
+
export type * from './types.js';
|
|
5
|
+
export type { BuiltInPublicationProviderName, PublicationStatus, PublicationBuildStatus, PublicationReleaseStatus, PublicationSize, PublicationRegion, PublicationJurisdiction, PublicationProtectionMode, PublicationLogStream, PublicationEventData, PublicationLogChunkData, PublishStreamPhase, PublishStreamLog, PublishStreamResult, PublishStreamEvent, PublishStreamSseEvent, } from '../schemas/publications.js';
|
|
6
|
+
export { laravelCloudSetupForRepublish } from './providers/laravel-cloud.js';
|
|
7
|
+
export { PublicationResources } from './resources.js';
|
|
8
|
+
export { PublicationDomains } from './domains.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { NotebookPublication } from './notebook.js';
|
|
2
|
+
export { PublicationApi, PublicationInstance } from './instance.js';
|
|
3
|
+
export { PublicationRun } from './run.js';
|
|
4
|
+
export { laravelCloudSetupForRepublish } from './providers/laravel-cloud.js';
|
|
5
|
+
export { PublicationResources } from './resources.js';
|
|
6
|
+
export { PublicationDomains } from './domains.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Client } from '../index.js';
|
|
2
|
+
import type { PublicationEventData, PublicationLogChunkData } from '../schemas/publications.js';
|
|
3
|
+
import type { PublicationProtectionData, LaravelCloudSetupInput, PublicationProviderName, PublicationData, UpdatePublicationProtectionInput, PublicationProtectionSessionData, PublicationDestroyOptions } from './types.js';
|
|
4
|
+
import { PublicationRun } from './run.js';
|
|
5
|
+
import { PublicationResources } from './resources.js';
|
|
6
|
+
import { PublicationDomains } from './domains.js';
|
|
7
|
+
export declare class PublicationApi {
|
|
8
|
+
private readonly client;
|
|
9
|
+
readonly resources: PublicationResources;
|
|
10
|
+
constructor(client: Client);
|
|
11
|
+
get<TProvider extends PublicationProviderName = PublicationProviderName>(id: string): Promise<PublicationInstance<TProvider>>;
|
|
12
|
+
}
|
|
13
|
+
export declare class PublicationInstance<TProvider extends PublicationProviderName = PublicationProviderName> {
|
|
14
|
+
readonly data: PublicationData<TProvider>;
|
|
15
|
+
private readonly client;
|
|
16
|
+
private readonly notebookId?;
|
|
17
|
+
readonly domains: PublicationDomains;
|
|
18
|
+
constructor(data: PublicationData<TProvider>, client: Client, notebookId?: string | undefined);
|
|
19
|
+
reconcileLaravelCloudResource(resourceId: string): Promise<PublicationInstance<TProvider>>;
|
|
20
|
+
configureLaravelCloud(setup: LaravelCloudSetupInput): Promise<PublicationInstance<TProvider>>;
|
|
21
|
+
refresh(): Promise<PublicationInstance<TProvider>>;
|
|
22
|
+
/** Start or reattach to the current release stream without queuing another release. */
|
|
23
|
+
follow(): PublicationRun<TProvider>;
|
|
24
|
+
publish(): Promise<PublicationRun<TProvider>>;
|
|
25
|
+
destroy(options?: PublicationDestroyOptions): Promise<void>;
|
|
26
|
+
wait(options?: {
|
|
27
|
+
intervalMs?: number;
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
}): Promise<PublicationInstance<TProvider>>;
|
|
30
|
+
events(): Promise<ReadableStream<PublicationEventData>>;
|
|
31
|
+
buildLogs(buildId?: string): Promise<ReadableStream<PublicationLogChunkData>>;
|
|
32
|
+
logSnapshot(stream: 'build' | 'runtime', limit?: number): Promise<{
|
|
33
|
+
stream: 'build' | 'runtime';
|
|
34
|
+
content: string;
|
|
35
|
+
truncated: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
logs(): Promise<ReadableStream<PublicationLogChunkData>>;
|
|
38
|
+
setProtection(input: UpdatePublicationProtectionInput): Promise<PublicationInstance<TProvider>>;
|
|
39
|
+
protection(): Promise<PublicationProtectionData>;
|
|
40
|
+
createProtectionSession(): Promise<PublicationProtectionSessionData>;
|
|
41
|
+
disableProtection(): Promise<PublicationInstance<TProvider>>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { PublicationEventDataSchema, PublicationLogChunkDataSchema } from '../schemas/publications.js';
|
|
2
|
+
import { PHPSandboxError, TransportError } from '../errors/index.js';
|
|
3
|
+
import { PublicationRun } from './run.js';
|
|
4
|
+
import { PublicationResources } from './resources.js';
|
|
5
|
+
import { PublicationDomains } from './domains.js';
|
|
6
|
+
export class PublicationApi {
|
|
7
|
+
constructor(client) {
|
|
8
|
+
this.client = client;
|
|
9
|
+
this.resources = new PublicationResources(client);
|
|
10
|
+
}
|
|
11
|
+
async get(id) {
|
|
12
|
+
const response = await this.client.get(`/publications/${encodeURIComponent(id)}`);
|
|
13
|
+
return new PublicationInstance(response.data, this.client);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class PublicationInstance {
|
|
17
|
+
constructor(data, client, notebookId) {
|
|
18
|
+
this.data = data;
|
|
19
|
+
this.client = client;
|
|
20
|
+
this.notebookId = notebookId;
|
|
21
|
+
this.domains = new PublicationDomains(client, data.id);
|
|
22
|
+
}
|
|
23
|
+
async reconcileLaravelCloudResource(resourceId) {
|
|
24
|
+
const response = await this.client.post(`/publications/${encodeURIComponent(this.data.id)}/laravel-cloud/reconcile`, { resourceId });
|
|
25
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
26
|
+
}
|
|
27
|
+
async configureLaravelCloud(setup) {
|
|
28
|
+
const response = await this.client.put(`/publications/${encodeURIComponent(this.data.id)}/laravel-cloud/setup`, { setup });
|
|
29
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
30
|
+
}
|
|
31
|
+
async refresh() {
|
|
32
|
+
const response = await this.client.get(`/publications/${encodeURIComponent(this.data.id)}`);
|
|
33
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
34
|
+
}
|
|
35
|
+
/** Start or reattach to the current release stream without queuing another release. */
|
|
36
|
+
follow() {
|
|
37
|
+
return new PublicationRun(this, this.client).start();
|
|
38
|
+
}
|
|
39
|
+
async publish() {
|
|
40
|
+
if (!this.notebookId) {
|
|
41
|
+
throw new PHPSandboxError('Publishing requires a notebook-scoped publication instance.');
|
|
42
|
+
}
|
|
43
|
+
const response = await this.client.post(`/notebook/${encodeURIComponent(this.notebookId)}/publication`);
|
|
44
|
+
const run = new PublicationRun(new PublicationInstance(response.data, this.client, this.notebookId), this.client);
|
|
45
|
+
run.start();
|
|
46
|
+
return run;
|
|
47
|
+
}
|
|
48
|
+
async destroy(options = {}) {
|
|
49
|
+
const query = options.deleteResources ? '?deleteResources=1' : '';
|
|
50
|
+
await this.client.delete(`/publications/${encodeURIComponent(this.data.id)}${query}`);
|
|
51
|
+
}
|
|
52
|
+
async wait(options = {}) {
|
|
53
|
+
const intervalMs = options.intervalMs ?? 1000;
|
|
54
|
+
const timeoutMs = options.timeoutMs ?? 300000;
|
|
55
|
+
const startedAt = Date.now();
|
|
56
|
+
let current = this;
|
|
57
|
+
while (!publicationStatusIsTerminal(current.data.status)) {
|
|
58
|
+
if (Date.now() - startedAt > timeoutMs) {
|
|
59
|
+
throw new PHPSandboxError(`Timed out waiting for publication ${this.data.id}`);
|
|
60
|
+
}
|
|
61
|
+
await delay(intervalMs);
|
|
62
|
+
current = await current.refresh();
|
|
63
|
+
}
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
66
|
+
async events() {
|
|
67
|
+
return parseNdjsonStream(await this.client.stream(`/publications/${encodeURIComponent(this.data.id)}/events/stream`), PublicationEventDataSchema);
|
|
68
|
+
}
|
|
69
|
+
buildLogs(buildId = this.data.latestBuild?.id ?? '') {
|
|
70
|
+
if (buildId === '') {
|
|
71
|
+
return Promise.reject(new PHPSandboxError('Publication has no latest build id'));
|
|
72
|
+
}
|
|
73
|
+
return this.client
|
|
74
|
+
.stream(`/publications/${encodeURIComponent(this.data.id)}/builds/${encodeURIComponent(buildId)}/logs/stream`)
|
|
75
|
+
.then((stream) => parseNdjsonStream(stream, PublicationLogChunkDataSchema));
|
|
76
|
+
}
|
|
77
|
+
async logSnapshot(stream, limit = 50) {
|
|
78
|
+
const query = new URLSearchParams({ stream, limit: String(limit) });
|
|
79
|
+
return (await this.client.get(`/publications/${encodeURIComponent(this.data.id)}/logs?${query}`)).data;
|
|
80
|
+
}
|
|
81
|
+
async logs() {
|
|
82
|
+
return parseNdjsonStream(await this.client.stream(`/publications/${encodeURIComponent(this.data.id)}/logs/stream`), PublicationLogChunkDataSchema);
|
|
83
|
+
}
|
|
84
|
+
async setProtection(input) {
|
|
85
|
+
const response = await this.client.put(`/publications/${encodeURIComponent(this.data.id)}/protection`, input);
|
|
86
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
87
|
+
}
|
|
88
|
+
async protection() {
|
|
89
|
+
const response = await this.client.get(`/publications/${encodeURIComponent(this.data.id)}/protection`);
|
|
90
|
+
return response.data;
|
|
91
|
+
}
|
|
92
|
+
async createProtectionSession() {
|
|
93
|
+
const response = await this.client.post(`/publications/${encodeURIComponent(this.data.id)}/protection/session`);
|
|
94
|
+
return response.data;
|
|
95
|
+
}
|
|
96
|
+
async disableProtection() {
|
|
97
|
+
const response = await this.client.delete(`/publications/${encodeURIComponent(this.data.id)}/protection`);
|
|
98
|
+
if (!response.data) {
|
|
99
|
+
throw new TransportError('Protection response has no publication data.', 'InvalidResponse');
|
|
100
|
+
}
|
|
101
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function publicationStatusIsTerminal(status) {
|
|
105
|
+
return ['healthy', 'failed', 'stopped', 'deleted', 'delete_failed'].includes(status);
|
|
106
|
+
}
|
|
107
|
+
function delay(ms) {
|
|
108
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
109
|
+
}
|
|
110
|
+
function parseNdjsonStream(input, schema) {
|
|
111
|
+
const decoder = new TextDecoder();
|
|
112
|
+
let buffer = '';
|
|
113
|
+
return input.pipeThrough(new TransformStream({
|
|
114
|
+
transform(chunk, controller) {
|
|
115
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
116
|
+
const lines = buffer.split('\n');
|
|
117
|
+
buffer = lines.pop() ?? '';
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
const trimmed = line.trim();
|
|
120
|
+
if (trimmed !== '') {
|
|
121
|
+
controller.enqueue(schema.parse(JSON.parse(trimmed)));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
flush(controller) {
|
|
126
|
+
buffer += decoder.decode();
|
|
127
|
+
const trimmed = buffer.trim();
|
|
128
|
+
if (trimmed !== '') {
|
|
129
|
+
controller.enqueue(schema.parse(JSON.parse(trimmed)));
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Client } from '../index.js';
|
|
2
|
+
import { PublicationInstance } from './instance.js';
|
|
3
|
+
import { PublicationRun } from './run.js';
|
|
4
|
+
import { PublicationResources } from './resources.js';
|
|
5
|
+
import type { PlannedPublishInput, PublicationPlan, PublicationPlanInput, PublicationProviderName, PublicationReadiness, PublicationResourceCatalog } from './types.js';
|
|
6
|
+
export declare class NotebookPublication {
|
|
7
|
+
private readonly notebookId;
|
|
8
|
+
private readonly client;
|
|
9
|
+
readonly resources: PublicationResources;
|
|
10
|
+
constructor(notebookId: string, client: Client);
|
|
11
|
+
private get path();
|
|
12
|
+
current(): Promise<PublicationInstance | null>;
|
|
13
|
+
readiness(): Promise<PublicationReadiness>;
|
|
14
|
+
/** Review a publishing plan without committing changes or creating resources. */
|
|
15
|
+
prepare<TName extends PublicationProviderName>(input: PublicationPlanInput<TName>): Promise<PublicationPlan<TName>>;
|
|
16
|
+
catalog(provider: 'laravel-cloud' | 'cloudflare-containers'): Promise<PublicationResourceCatalog>;
|
|
17
|
+
catalog(provider: 'ssh-server', serverId: string): Promise<PublicationResourceCatalog>;
|
|
18
|
+
/** Core validates the plan, prepares source and executes publishing. */
|
|
19
|
+
publish(input?: PlannedPublishInput): Promise<PublicationRun>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RemoteError } from '../errors/index.js';
|
|
2
|
+
import { PublicationInstance } from './instance.js';
|
|
3
|
+
import { PublicationRun } from './run.js';
|
|
4
|
+
import { PublicationResources } from './resources.js';
|
|
5
|
+
export class NotebookPublication {
|
|
6
|
+
constructor(notebookId, client) {
|
|
7
|
+
this.notebookId = notebookId;
|
|
8
|
+
this.client = client;
|
|
9
|
+
this.resources = new PublicationResources(client, `${this.path}/publication/resources`);
|
|
10
|
+
}
|
|
11
|
+
get path() {
|
|
12
|
+
return `/notebook/${encodeURIComponent(this.notebookId)}`;
|
|
13
|
+
}
|
|
14
|
+
async current() {
|
|
15
|
+
try {
|
|
16
|
+
const response = await this.client.get(`${this.path}/publication`);
|
|
17
|
+
return new PublicationInstance(response.data, this.client, this.notebookId);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (RemoteError.is(error) && error.status === 404) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async readiness() {
|
|
27
|
+
return (await this.client.get(`${this.path}/publication/readiness`)).data;
|
|
28
|
+
}
|
|
29
|
+
/** Review a publishing plan without committing changes or creating resources. */
|
|
30
|
+
async prepare(input) {
|
|
31
|
+
return (await this.client.post(`${this.path}/publication/plan`, input)).data;
|
|
32
|
+
}
|
|
33
|
+
async catalog(provider, serverId) {
|
|
34
|
+
const query = new URLSearchParams({ provider });
|
|
35
|
+
if (serverId !== undefined) {
|
|
36
|
+
query.set('serverId', serverId);
|
|
37
|
+
}
|
|
38
|
+
return (await this.client.get(`${this.path}/publication/catalog?${query}`))
|
|
39
|
+
.data;
|
|
40
|
+
}
|
|
41
|
+
/** Core validates the plan, prepares source and executes publishing. */
|
|
42
|
+
async publish(input) {
|
|
43
|
+
const response = await this.client.post(`${this.path}/publication`, input);
|
|
44
|
+
return new PublicationRun(new PublicationInstance(response.data, this.client, this.notebookId), this.client).start();
|
|
45
|
+
}
|
|
46
|
+
}
|