@phpsandbox/sdk 0.1.2 → 0.1.6
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 +31 -6
- package/dist/browser/phpsandbox-sdk.esm.js +327 -54
- package/dist/browser/phpsandbox-sdk.esm.min.js +24 -24
- package/dist/browser/phpsandbox-sdk.iife.js +327 -54
- package/dist/browser/phpsandbox-sdk.iife.min.js +24 -24
- package/dist/feedback.d.ts +73 -0
- package/dist/feedback.js +38 -0
- package/dist/filesystem.d.ts +19 -24
- package/dist/filesystem.js +75 -1
- package/dist/git.d.ts +28 -11
- package/dist/git.js +41 -10
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/integrations.d.ts +43 -0
- package/dist/integrations.js +48 -0
- package/dist/publications.d.ts +5 -21
- package/dist/publications.js +1 -8
- package/dist/runtime/rest.js +0 -5
- package/dist/sandbox-integrations.d.ts +44 -0
- package/dist/sandbox-integrations.js +63 -0
- package/dist/schemas/publications.d.ts +11 -1
- package/dist/schemas/publications.js +3 -1
- package/dist/terminal.d.ts +0 -7
- package/docs/api-summary.md +33 -3
- package/examples/README.md +1 -1
- package/examples/publish-cloudflare-container.ts +15 -0
- package/examples/publish-laravel-cloud.ts +33 -22
- package/package.json +12 -2
package/dist/publications.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Client
|
|
1
|
+
import { type Client } from './index.js';
|
|
2
2
|
import type { PublicationBuildStatus, PublicationDomainDnsRecordType, PublicationEventData, PublicationJurisdiction, PublicationLogChunkData, PublicationProtectionMode, PublicationRegion, PublicationReleaseStatus, PublicationSize, PublicationStatus, PublishStreamEvent, PublishStreamResult } from './schemas/publications.js';
|
|
3
3
|
export * from './schemas/publications.js';
|
|
4
4
|
export interface PublicationPlacement {
|
|
@@ -13,10 +13,6 @@ export interface PublicationProtectionData {
|
|
|
13
13
|
expiresAt?: string;
|
|
14
14
|
url?: string;
|
|
15
15
|
}
|
|
16
|
-
export interface PublicationFeedbackData {
|
|
17
|
-
enabled: boolean;
|
|
18
|
-
config: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
16
|
export type PublicationProtectionInput = {
|
|
21
17
|
mode: 'none';
|
|
22
18
|
password?: never;
|
|
@@ -24,11 +20,8 @@ export type PublicationProtectionInput = {
|
|
|
24
20
|
mode: 'password';
|
|
25
21
|
password: string;
|
|
26
22
|
};
|
|
27
|
-
export interface PublicationFeedbackInput {
|
|
28
|
-
enabled: boolean;
|
|
29
|
-
config?: Record<string, unknown>;
|
|
30
|
-
}
|
|
31
23
|
export interface CloudflareContainersProviderOptions {
|
|
24
|
+
accountId: string;
|
|
32
25
|
size?: PublicationSize;
|
|
33
26
|
sleepAfter?: string;
|
|
34
27
|
placement?: PublicationPlacement;
|
|
@@ -42,11 +35,9 @@ export interface LaravelCloudProviderData {
|
|
|
42
35
|
repository?: string;
|
|
43
36
|
branch?: string;
|
|
44
37
|
sourceControlProviderType?: 'github' | 'gitlab' | 'bitbucket';
|
|
45
|
-
apiKeyConfigured?: boolean;
|
|
46
38
|
}
|
|
47
39
|
export interface LaravelCloudProviderInput {
|
|
48
|
-
|
|
49
|
-
region?: LaravelCloudRegion;
|
|
40
|
+
region: LaravelCloudRegion;
|
|
50
41
|
}
|
|
51
42
|
export interface PublicationProviderInputs {
|
|
52
43
|
'cloudflare-containers': CloudflareContainersProviderOptions;
|
|
@@ -73,9 +64,9 @@ export interface PublishInput<TName extends PublicationProviderName = Publicatio
|
|
|
73
64
|
slug: string;
|
|
74
65
|
provider: PublicationProviderInput<TName>;
|
|
75
66
|
protection?: PublicationProtectionInput;
|
|
76
|
-
feedback?: PublicationFeedbackInput;
|
|
77
67
|
metadata?: Record<string, unknown>;
|
|
78
68
|
}
|
|
69
|
+
export type PublicationRunResult = PublishStreamResult;
|
|
79
70
|
export interface PublicationBuildData<TProvider extends PublicationProviderName = PublicationProviderName> {
|
|
80
71
|
id: string;
|
|
81
72
|
status: PublicationBuildStatus;
|
|
@@ -124,7 +115,6 @@ export interface PublicationData<TProvider extends PublicationProviderName = Pub
|
|
|
124
115
|
strategy: string;
|
|
125
116
|
provider: PublicationProvider<TProvider>;
|
|
126
117
|
protection: PublicationProtectionData;
|
|
127
|
-
feedback: PublicationFeedbackData;
|
|
128
118
|
eventStreamUrl: string | null;
|
|
129
119
|
originUrl: string | null;
|
|
130
120
|
currentRelease?: PublicationReleaseData | null;
|
|
@@ -144,10 +134,6 @@ export interface PublicationProtectionSessionData {
|
|
|
144
134
|
expiresAt: string;
|
|
145
135
|
url: string;
|
|
146
136
|
}
|
|
147
|
-
export interface UpdatePublicationFeedbackInput {
|
|
148
|
-
enabled: boolean;
|
|
149
|
-
config?: Record<string, unknown>;
|
|
150
|
-
}
|
|
151
137
|
export declare class NotebookPublicationApi {
|
|
152
138
|
private readonly client;
|
|
153
139
|
constructor(client: Client);
|
|
@@ -163,7 +149,6 @@ export declare class PublicationApi {
|
|
|
163
149
|
protection(id: string): Promise<PublicationProtectionData>;
|
|
164
150
|
createProtectionSession(id: string): Promise<PublicationProtectionSessionData>;
|
|
165
151
|
disableProtection<TProvider extends PublicationProviderName = PublicationProviderName>(id: string): Promise<PublicationInstance<TProvider>>;
|
|
166
|
-
setFeedback<TProvider extends PublicationProviderName = PublicationProviderName>(id: string, input: UpdatePublicationFeedbackInput): Promise<PublicationInstance<TProvider>>;
|
|
167
152
|
listDomains(id: string): Promise<PublicationDomainData[]>;
|
|
168
153
|
createDomain(id: string, input: CreatePublicationDomainInput): Promise<PublicationDomainData>;
|
|
169
154
|
refreshDomain(id: string, domainId: string): Promise<PublicationDomainData>;
|
|
@@ -186,7 +171,7 @@ export declare class PublicationRun<TProvider extends PublicationProviderName =
|
|
|
186
171
|
private readonly subscribers;
|
|
187
172
|
constructor(initial: PublicationInstance<TProvider>, client: Client);
|
|
188
173
|
events(): AsyncIterable<PublishStreamEvent>;
|
|
189
|
-
result(): Promise<
|
|
174
|
+
result(): Promise<PublicationRunResult>;
|
|
190
175
|
publication(): Promise<PublicationInstance<TProvider>>;
|
|
191
176
|
start(): this;
|
|
192
177
|
private subscribe;
|
|
@@ -214,7 +199,6 @@ export declare class PublicationInstance<TProvider extends PublicationProviderNa
|
|
|
214
199
|
protection(): Promise<PublicationProtectionData>;
|
|
215
200
|
createProtectionSession(): Promise<PublicationProtectionSessionData>;
|
|
216
201
|
disableProtection(): Promise<PublicationInstance<TProvider>>;
|
|
217
|
-
setFeedback(input: UpdatePublicationFeedbackInput): Promise<PublicationInstance<TProvider>>;
|
|
218
202
|
domains(): Promise<PublicationDomainData[]>;
|
|
219
203
|
addDomain(input: CreatePublicationDomainInput): Promise<PublicationDomainData>;
|
|
220
204
|
refreshDomain(domainId: string): Promise<PublicationDomainData>;
|
package/dist/publications.js
CHANGED
|
@@ -51,10 +51,6 @@ export class PublicationApi {
|
|
|
51
51
|
const response = await this.client.delete(`/publications/${id}/protection`);
|
|
52
52
|
return new PublicationInstance(response.data, this.client);
|
|
53
53
|
}
|
|
54
|
-
async setFeedback(id, input) {
|
|
55
|
-
const response = await this.client.put(`/publications/${id}/feedback`, input);
|
|
56
|
-
return new PublicationInstance(response.data, this.client);
|
|
57
|
-
}
|
|
58
54
|
async listDomains(id) {
|
|
59
55
|
const response = await this.client.get(`/publications/${id}/domains`);
|
|
60
56
|
return unwrapPublicationDomainCollection(response.data);
|
|
@@ -156,7 +152,7 @@ export class PublicationRun {
|
|
|
156
152
|
if (event.type === 'result') {
|
|
157
153
|
const { type: _, ...result } = event;
|
|
158
154
|
this.finalResult = result;
|
|
159
|
-
this.resolveResult?.(
|
|
155
|
+
this.resolveResult?.(this.finalResult);
|
|
160
156
|
}
|
|
161
157
|
}
|
|
162
158
|
if (!this.finalResult) {
|
|
@@ -248,9 +244,6 @@ export class PublicationInstance {
|
|
|
248
244
|
disableProtection() {
|
|
249
245
|
return this.client.publications.disableProtection(this.data.id);
|
|
250
246
|
}
|
|
251
|
-
setFeedback(input) {
|
|
252
|
-
return this.client.publications.setFeedback(this.data.id, input);
|
|
253
|
-
}
|
|
254
247
|
domains() {
|
|
255
248
|
return this.client.publications.listDomains(this.data.id);
|
|
256
249
|
}
|
package/dist/runtime/rest.js
CHANGED
|
@@ -15,18 +15,13 @@ const restActionRoutes = {
|
|
|
15
15
|
'container.stats': { method: 'GET', path: '/runtime/container/stats' },
|
|
16
16
|
'terminal.list': { method: 'GET', path: '/runtime/terminals' },
|
|
17
17
|
'shell.exec': { method: 'POST', path: '/runtime/executions' },
|
|
18
|
-
'fs.info': { method: 'POST', path: '/runtime/files/info' },
|
|
19
18
|
'fs.readFile': { method: 'GET', path: '/runtime/files/content' },
|
|
20
19
|
'fs.writeFile': { method: 'PUT', path: '/runtime/files/content' },
|
|
21
|
-
'fs.write': { method: 'PUT', path: '/runtime/files/text' },
|
|
22
|
-
'fs.mkdir': { method: 'POST', path: '/runtime/directories' },
|
|
23
20
|
'fs.createDirectory': { method: 'PUT', path: '/runtime/directories' },
|
|
24
21
|
'fs.readDirectory': { method: 'POST', path: '/runtime/directories/read' },
|
|
25
22
|
'fs.stat': { method: 'POST', path: '/runtime/files/stat' },
|
|
26
|
-
'fs.move': { method: 'POST', path: '/runtime/files/move' },
|
|
27
23
|
'fs.rename': { method: 'POST', path: '/runtime/files/rename' },
|
|
28
24
|
'fs.copy': { method: 'POST', path: '/runtime/files/copy' },
|
|
29
|
-
'fs.remove': { method: 'POST', path: '/runtime/files/remove' },
|
|
30
25
|
'fs.delete': { method: 'DELETE', path: '/runtime/files' },
|
|
31
26
|
'fs.tail': { method: 'POST', path: '/runtime/files/tail' },
|
|
32
27
|
'fs.find': { method: 'POST', path: '/runtime/files/find' },
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Client } from './index.js';
|
|
2
|
+
import { Integration, type IntegrationData, type IntegrationReference } from './integrations.js';
|
|
3
|
+
export type SandboxIntegrationEffect = 'network';
|
|
4
|
+
export interface AttachSandboxIntegrationInput {
|
|
5
|
+
integration: IntegrationReference;
|
|
6
|
+
effects?: SandboxIntegrationEffect[];
|
|
7
|
+
}
|
|
8
|
+
export type UpdateSandboxIntegrationInput = {
|
|
9
|
+
integration: IntegrationReference;
|
|
10
|
+
effects?: SandboxIntegrationEffect[];
|
|
11
|
+
} | {
|
|
12
|
+
integration?: IntegrationReference;
|
|
13
|
+
effects: SandboxIntegrationEffect[];
|
|
14
|
+
};
|
|
15
|
+
export interface SandboxIntegrationData {
|
|
16
|
+
id: string;
|
|
17
|
+
integration: IntegrationData;
|
|
18
|
+
effects: SandboxIntegrationEffect[];
|
|
19
|
+
}
|
|
20
|
+
export type SandboxIntegrationReference = string | SandboxIntegration;
|
|
21
|
+
export declare class SandboxIntegrationApi {
|
|
22
|
+
private readonly notebookId;
|
|
23
|
+
private readonly client;
|
|
24
|
+
constructor(notebookId: string, client: Client);
|
|
25
|
+
attach(input: AttachSandboxIntegrationInput): Promise<SandboxIntegration>;
|
|
26
|
+
list(): Promise<SandboxIntegration[]>;
|
|
27
|
+
get(integration: SandboxIntegrationReference): Promise<SandboxIntegration>;
|
|
28
|
+
update(integration: SandboxIntegrationReference, input: UpdateSandboxIntegrationInput): Promise<SandboxIntegration>;
|
|
29
|
+
detach(integration: SandboxIntegrationReference): Promise<void>;
|
|
30
|
+
private path;
|
|
31
|
+
private bindingPath;
|
|
32
|
+
}
|
|
33
|
+
export declare class SandboxIntegration {
|
|
34
|
+
readonly data: SandboxIntegrationData;
|
|
35
|
+
private readonly notebookId;
|
|
36
|
+
private readonly client;
|
|
37
|
+
constructor(data: SandboxIntegrationData, notebookId: string, client: Client);
|
|
38
|
+
get id(): string;
|
|
39
|
+
get integration(): Integration;
|
|
40
|
+
get effects(): SandboxIntegrationEffect[];
|
|
41
|
+
update(input: UpdateSandboxIntegrationInput): Promise<SandboxIntegration>;
|
|
42
|
+
detach(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export declare function sandboxIntegrationId(integration: SandboxIntegrationReference): string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Integration, integrationId, } from './integrations.js';
|
|
2
|
+
export class SandboxIntegrationApi {
|
|
3
|
+
constructor(notebookId, client) {
|
|
4
|
+
this.notebookId = notebookId;
|
|
5
|
+
this.client = client;
|
|
6
|
+
}
|
|
7
|
+
async attach(input) {
|
|
8
|
+
const response = await this.client.post(this.path(), {
|
|
9
|
+
...input,
|
|
10
|
+
integration: integrationId(input.integration),
|
|
11
|
+
});
|
|
12
|
+
return new SandboxIntegration(response.data, this.notebookId, this.client);
|
|
13
|
+
}
|
|
14
|
+
async list() {
|
|
15
|
+
const response = await this.client.get(this.path());
|
|
16
|
+
return response.data.map((integration) => new SandboxIntegration(integration, this.notebookId, this.client));
|
|
17
|
+
}
|
|
18
|
+
async get(integration) {
|
|
19
|
+
const response = await this.client.get(this.bindingPath(integration));
|
|
20
|
+
return new SandboxIntegration(response.data, this.notebookId, this.client);
|
|
21
|
+
}
|
|
22
|
+
async update(integration, input) {
|
|
23
|
+
const response = await this.client.patch(this.bindingPath(integration), {
|
|
24
|
+
...input,
|
|
25
|
+
integration: input.integration === undefined ? undefined : integrationId(input.integration),
|
|
26
|
+
});
|
|
27
|
+
return new SandboxIntegration(response.data, this.notebookId, this.client);
|
|
28
|
+
}
|
|
29
|
+
async detach(integration) {
|
|
30
|
+
await this.client.delete(this.bindingPath(integration));
|
|
31
|
+
}
|
|
32
|
+
path() {
|
|
33
|
+
return `/notebook/${this.notebookId}/integrations`;
|
|
34
|
+
}
|
|
35
|
+
bindingPath(integration) {
|
|
36
|
+
return `${this.path()}/${encodeURIComponent(sandboxIntegrationId(integration))}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class SandboxIntegration {
|
|
40
|
+
constructor(data, notebookId, client) {
|
|
41
|
+
this.data = data;
|
|
42
|
+
this.notebookId = notebookId;
|
|
43
|
+
this.client = client;
|
|
44
|
+
}
|
|
45
|
+
get id() {
|
|
46
|
+
return this.data.id;
|
|
47
|
+
}
|
|
48
|
+
get integration() {
|
|
49
|
+
return new Integration(this.data.integration, this.client);
|
|
50
|
+
}
|
|
51
|
+
get effects() {
|
|
52
|
+
return this.data.effects;
|
|
53
|
+
}
|
|
54
|
+
update(input) {
|
|
55
|
+
return new SandboxIntegrationApi(this.notebookId, this.client).update(this, input);
|
|
56
|
+
}
|
|
57
|
+
detach() {
|
|
58
|
+
return new SandboxIntegrationApi(this.notebookId, this.client).detach(this);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function sandboxIntegrationId(integration) {
|
|
62
|
+
return typeof integration === 'string' ? integration : integration.id;
|
|
63
|
+
}
|
|
@@ -76,7 +76,7 @@ export declare const PublicationEventDataSchema: z.ZodObject<{
|
|
|
76
76
|
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
|
|
77
77
|
sequence: z.ZodNumber;
|
|
78
78
|
type: z.ZodString;
|
|
79
|
-
payload: z.ZodRecord<z.ZodString, z.ZodUnknown
|
|
79
|
+
payload: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
80
80
|
createdAt: z.ZodNullable<z.ZodString>;
|
|
81
81
|
}, z.core.$loose>;
|
|
82
82
|
export declare const PublicationLogChunkDataSchema: z.ZodObject<{
|
|
@@ -108,6 +108,7 @@ export declare const PublishStreamLogSchema: z.ZodObject<{
|
|
|
108
108
|
export declare const PublishStreamResultSchema: z.ZodObject<{
|
|
109
109
|
success: z.ZodBoolean;
|
|
110
110
|
publicationId: z.ZodString;
|
|
111
|
+
url: z.ZodString;
|
|
111
112
|
buildId: z.ZodString;
|
|
112
113
|
releaseId: z.ZodString;
|
|
113
114
|
status: z.ZodEnum<{
|
|
@@ -145,6 +146,7 @@ export declare const PublishStreamLogEventSchema: z.ZodObject<{
|
|
|
145
146
|
export declare const PublishStreamResultEventSchema: z.ZodObject<{
|
|
146
147
|
success: z.ZodBoolean;
|
|
147
148
|
publicationId: z.ZodString;
|
|
149
|
+
url: z.ZodString;
|
|
148
150
|
buildId: z.ZodString;
|
|
149
151
|
releaseId: z.ZodString;
|
|
150
152
|
status: z.ZodEnum<{
|
|
@@ -181,6 +183,7 @@ export declare const PublishStreamEventSchema: z.ZodDiscriminatedUnion<[z.ZodObj
|
|
|
181
183
|
}, z.core.$strict>, z.ZodObject<{
|
|
182
184
|
success: z.ZodBoolean;
|
|
183
185
|
publicationId: z.ZodString;
|
|
186
|
+
url: z.ZodString;
|
|
184
187
|
buildId: z.ZodString;
|
|
185
188
|
releaseId: z.ZodString;
|
|
186
189
|
status: z.ZodEnum<{
|
|
@@ -235,6 +238,7 @@ export declare const PublishStreamSseDoneEventSchema: z.ZodObject<{
|
|
|
235
238
|
data: z.ZodObject<{
|
|
236
239
|
success: z.ZodBoolean;
|
|
237
240
|
publicationId: z.ZodString;
|
|
241
|
+
url: z.ZodString;
|
|
238
242
|
buildId: z.ZodString;
|
|
239
243
|
releaseId: z.ZodString;
|
|
240
244
|
status: z.ZodEnum<{
|
|
@@ -256,6 +260,7 @@ export declare const PublishStreamSseResultEventSchema: z.ZodObject<{
|
|
|
256
260
|
data: z.ZodObject<{
|
|
257
261
|
success: z.ZodBoolean;
|
|
258
262
|
publicationId: z.ZodString;
|
|
263
|
+
url: z.ZodString;
|
|
259
264
|
buildId: z.ZodString;
|
|
260
265
|
releaseId: z.ZodString;
|
|
261
266
|
status: z.ZodEnum<{
|
|
@@ -304,6 +309,7 @@ export declare const PublishStreamSseEventSchema: z.ZodPipe<z.ZodDiscriminatedUn
|
|
|
304
309
|
data: z.ZodObject<{
|
|
305
310
|
success: z.ZodBoolean;
|
|
306
311
|
publicationId: z.ZodString;
|
|
312
|
+
url: z.ZodString;
|
|
307
313
|
buildId: z.ZodString;
|
|
308
314
|
releaseId: z.ZodString;
|
|
309
315
|
status: z.ZodEnum<{
|
|
@@ -324,6 +330,7 @@ export declare const PublishStreamSseEventSchema: z.ZodPipe<z.ZodDiscriminatedUn
|
|
|
324
330
|
data: z.ZodObject<{
|
|
325
331
|
success: z.ZodBoolean;
|
|
326
332
|
publicationId: z.ZodString;
|
|
333
|
+
url: z.ZodString;
|
|
327
334
|
buildId: z.ZodString;
|
|
328
335
|
releaseId: z.ZodString;
|
|
329
336
|
status: z.ZodEnum<{
|
|
@@ -356,6 +363,7 @@ export declare const PublishStreamSseEventSchema: z.ZodPipe<z.ZodDiscriminatedUn
|
|
|
356
363
|
} | {
|
|
357
364
|
success: boolean;
|
|
358
365
|
publicationId: string;
|
|
366
|
+
url: string;
|
|
359
367
|
buildId: string;
|
|
360
368
|
releaseId: string;
|
|
361
369
|
status: "stopped" | "deleted" | "pending" | "queued" | "building" | "deploying" | "healthy" | "failed" | "deleting" | "delete_failed";
|
|
@@ -378,6 +386,7 @@ export declare const PublishStreamSseEventSchema: z.ZodPipe<z.ZodDiscriminatedUn
|
|
|
378
386
|
data: {
|
|
379
387
|
success: boolean;
|
|
380
388
|
publicationId: string;
|
|
389
|
+
url: string;
|
|
381
390
|
buildId: string;
|
|
382
391
|
releaseId: string;
|
|
383
392
|
status: "stopped" | "deleted" | "pending" | "queued" | "building" | "deploying" | "healthy" | "failed" | "deleting" | "delete_failed";
|
|
@@ -387,6 +396,7 @@ export declare const PublishStreamSseEventSchema: z.ZodPipe<z.ZodDiscriminatedUn
|
|
|
387
396
|
data: {
|
|
388
397
|
success: boolean;
|
|
389
398
|
publicationId: string;
|
|
399
|
+
url: string;
|
|
390
400
|
buildId: string;
|
|
391
401
|
releaseId: string;
|
|
392
402
|
status: "stopped" | "deleted" | "pending" | "queued" | "building" | "deploying" | "healthy" | "failed" | "deleting" | "delete_failed";
|
|
@@ -51,11 +51,12 @@ export const PublicationDomainDnsRecordTypeSchema = z.enum(['CNAME', 'ALIAS', 'A
|
|
|
51
51
|
export const PublicationProtectionModeSchema = z.enum(['none', 'password']);
|
|
52
52
|
export const PublicationLogStreamSchema = z.enum(['build', 'runtime']);
|
|
53
53
|
export const PublishStreamLogStreamSchema = z.enum(['build', 'publish', 'runtime']);
|
|
54
|
+
const PublicationEventPayloadSchema = z.preprocess((payload) => Array.isArray(payload) && payload.length === 0 ? {} : payload, z.record(z.string(), z.unknown()));
|
|
54
55
|
export const PublicationEventDataSchema = z.object({
|
|
55
56
|
id: z.union([z.number(), z.string()]).optional(),
|
|
56
57
|
sequence: z.number(),
|
|
57
58
|
type: z.string(),
|
|
58
|
-
payload:
|
|
59
|
+
payload: PublicationEventPayloadSchema,
|
|
59
60
|
createdAt: z.string().nullable(),
|
|
60
61
|
}).passthrough();
|
|
61
62
|
export const PublicationLogChunkDataSchema = z.object({
|
|
@@ -76,6 +77,7 @@ export const PublishStreamLogSchema = z.object({
|
|
|
76
77
|
export const PublishStreamResultSchema = z.object({
|
|
77
78
|
success: z.boolean(),
|
|
78
79
|
publicationId: z.string(),
|
|
80
|
+
url: z.string().url(),
|
|
79
81
|
buildId: z.string(),
|
|
80
82
|
releaseId: z.string(),
|
|
81
83
|
status: PublicationStatusSchema,
|
package/dist/terminal.d.ts
CHANGED
|
@@ -17,12 +17,6 @@ export interface TerminalCreateInput {
|
|
|
17
17
|
env?: Record<string, string | number | boolean>;
|
|
18
18
|
cwd?: string;
|
|
19
19
|
}
|
|
20
|
-
export interface TerminalSpawnInput {
|
|
21
|
-
command: string | string[];
|
|
22
|
-
opts: {
|
|
23
|
-
id: string;
|
|
24
|
-
} & SpawnOptions;
|
|
25
|
-
}
|
|
26
20
|
export interface TerminalEventData {
|
|
27
21
|
'terminal.output': {
|
|
28
22
|
output: string;
|
|
@@ -50,7 +44,6 @@ export interface TerminalActions {
|
|
|
50
44
|
}>;
|
|
51
45
|
'terminal.list': Action<{}, Task[]>;
|
|
52
46
|
'terminal.create': Action<TerminalCreateInput, Task>;
|
|
53
|
-
'terminal.spawn': Action<TerminalSpawnInput, Task>;
|
|
54
47
|
'terminal.attach': Action<{
|
|
55
48
|
id: string;
|
|
56
49
|
replayHistory?: boolean;
|
package/docs/api-summary.md
CHANGED
|
@@ -91,7 +91,8 @@ Connection lifecycle methods, streaming actions, and event subscriptions require
|
|
|
91
91
|
### Git (`notebook.git`)
|
|
92
92
|
|
|
93
93
|
- `checkpoint(author, message, branch = 'main')`
|
|
94
|
-
- `
|
|
94
|
+
- `targets.create({ provider, repository, author, branch?, setDefault? })`
|
|
95
|
+
- `targets.list()`, `targets.get(target)`, and `target.sync({ direction?, author? })`
|
|
95
96
|
- `diff({ url?, token?, ref?, base?, target? })`
|
|
96
97
|
- `merge({ url?, token?, ref?, target?, expectedBaseRef?, author?, message? })`
|
|
97
98
|
- `conflicts()`
|
|
@@ -104,6 +105,16 @@ Connection lifecycle methods, streaming actions, and event subscriptions require
|
|
|
104
105
|
- `log(ref = 'main')`
|
|
105
106
|
- `restore(ref)`
|
|
106
107
|
|
|
108
|
+
### Sandbox integrations (`notebook.integrations`)
|
|
109
|
+
|
|
110
|
+
- `attach({ integration, effects? })`
|
|
111
|
+
- A sandbox has one attached integration per provider. `binding.update({ integration })` replaces that provider selection.
|
|
112
|
+
- Provider-backed operations resolve the attached integration when they run; persistent sandbox behavior remains controlled by explicit effects.
|
|
113
|
+
- `list()`
|
|
114
|
+
- `get(binding)`
|
|
115
|
+
- Binding resources expose `update({ effects })` and `detach()`
|
|
116
|
+
- The currently supported sandbox effect is GitHub `network`; effects are explicit and provider-specific.
|
|
117
|
+
|
|
107
118
|
### Mail (`notebook.mail`)
|
|
108
119
|
|
|
109
120
|
- `status()` returning non-sensitive mail configuration state
|
|
@@ -113,6 +124,16 @@ Connection lifecycle methods, streaming actions, and event subscriptions require
|
|
|
113
124
|
- `get(hash)`
|
|
114
125
|
- `delete(hash)`
|
|
115
126
|
|
|
127
|
+
### Feedback (`sandbox.feedback`)
|
|
128
|
+
|
|
129
|
+
- `configure({ widget })`, where `widget` is `null` or contains `targets`, optional `label`, and optional `types`
|
|
130
|
+
- `submit({ type, message, author?, context?, metadata? })`
|
|
131
|
+
- `list({ type?, status?, source?, page? })`
|
|
132
|
+
- `get(id)`
|
|
133
|
+
- `update(id, { status })`
|
|
134
|
+
|
|
135
|
+
Feedback ingestion is always available through the authenticated API. Configuration controls only the optional widget and can target `preview`, `publication`, or both.
|
|
136
|
+
|
|
116
137
|
### LSP (`notebook.lsp`)
|
|
117
138
|
|
|
118
139
|
- Messaging: `start(id)`, `close(id)`, `message(id, payload)`
|
|
@@ -130,11 +151,20 @@ Connection lifecycle methods, streaming actions, and event subscriptions require
|
|
|
130
151
|
|
|
131
152
|
## Publications
|
|
132
153
|
|
|
133
|
-
- `notebook.publish({ slug, provider, protection?,
|
|
154
|
+
- `notebook.publish({ slug, provider, protection?, metadata? })`
|
|
134
155
|
- `notebook.publication()` returns the current publication or `null`
|
|
135
156
|
- `client.publications.get(id)`, `destroy(id)`, `events(id)`, `logs(id)`, and `buildLogs(id, buildId)`
|
|
136
|
-
- A publish run exposes `events()` as an `AsyncIterable`, `result()
|
|
157
|
+
- A publish run exposes `events()` as an `AsyncIterable`, `result()` with the final status and URL, and `publication()` when refreshed deployment state is needed.
|
|
137
158
|
- Built-in provider names are `cloudflare-containers`, `ssh-server`, and `laravel-cloud`. Provider maps support TypeScript declaration merging.
|
|
159
|
+
- Cloudflare Containers input uses `{ name: 'cloudflare-containers', accountId, size?, sleepAfter?, placement?, instances? }` and resolves the sandbox's attached Cloudflare integration when each operation runs.
|
|
160
|
+
- Laravel Cloud input uses `{ name: 'laravel-cloud', region }` and resolves the sandbox's attached Laravel Cloud integration when each operation runs.
|
|
161
|
+
|
|
162
|
+
## Account integrations
|
|
163
|
+
|
|
164
|
+
- `client.integrations.link({ provider, label?, authorization })`
|
|
165
|
+
- `client.integrations.list()`, `get(integration)`, `update(integration, input)`, and `unlink(integration)`
|
|
166
|
+
- Resource instances expose `update(input)` and `unlink()`.
|
|
167
|
+
- Built-in providers are `cloudflare`, `github`, and `laravel-cloud`; current public authorization uses opaque caller-managed tokens.
|
|
138
168
|
|
|
139
169
|
## Common Errors
|
|
140
170
|
|
package/examples/README.md
CHANGED
|
@@ -32,7 +32,7 @@ PHPSANDBOX_TOKEN=your-token PHPSANDBOX_NOTEBOOK_ID=notebook-id \
|
|
|
32
32
|
npx tsx examples/publish-laravel-cloud.ts
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Publication examples accept `PHPSANDBOX_API_URL` and `PHPSANDBOX_PUBLISH_SLUG`. On the first run they create the notebook's publication; later runs publish it again without changing slug or provider. The SSH example creates a server registration when `PHPSANDBOX_PUBLISH_SERVER_ID` is not set; on local `.test` APIs it also starts local Rook from `PHPSANDBOX_ROOK_DIR` or the sibling `rook` repo. The Laravel Cloud example
|
|
35
|
+
Publication examples accept `PHPSANDBOX_API_URL` and `PHPSANDBOX_PUBLISH_SLUG`. On the first run they create the notebook's publication; later runs publish it again without changing slug or provider. The SSH example creates a server registration when `PHPSANDBOX_PUBLISH_SERVER_ID` is not set; on local `.test` APIs it also starts local Rook from `PHPSANDBOX_ROOK_DIR` or the sibling `rook` repo. The Laravel Cloud example links or refreshes the GitHub and Laravel Cloud integrations, attaches each provider to the sandbox, synchronizes the notebook to `PHPSANDBOX_LARAVEL_CLOUD_REPOSITORY`, and publishes through the attached Laravel Cloud integration.
|
|
36
36
|
|
|
37
37
|
### Running The Laravel Load Test
|
|
38
38
|
|
|
@@ -13,10 +13,24 @@ if (!notebookId) {
|
|
|
13
13
|
|
|
14
14
|
const slug = process.env.PHPSANDBOX_PUBLISH_SLUG ?? `sdk-cloudflare-${Date.now().toString(36)}`;
|
|
15
15
|
const apiUrl = process.env.PHPSANDBOX_API_URL;
|
|
16
|
+
const cloudflareAccountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
17
|
+
const cloudflareApiToken = process.env.CLOUDFLARE_API_TOKEN;
|
|
18
|
+
if (!cloudflareAccountId || !cloudflareApiToken) {
|
|
19
|
+
throw new Error('Missing CLOUDFLARE_ACCOUNT_ID or CLOUDFLARE_API_TOKEN');
|
|
20
|
+
}
|
|
16
21
|
const client = new Client(token, apiUrl);
|
|
17
22
|
const notebook = await client.notebook.get(notebookId);
|
|
18
23
|
|
|
19
24
|
try {
|
|
25
|
+
const existingIntegration = (await client.integrations.list()).find(({ provider }) => provider === 'cloudflare');
|
|
26
|
+
const integration = existingIntegration
|
|
27
|
+
? await existingIntegration.update({ authorization: { type: 'token', token: cloudflareApiToken } })
|
|
28
|
+
: await client.integrations.link({
|
|
29
|
+
provider: 'cloudflare',
|
|
30
|
+
authorization: { type: 'token', token: cloudflareApiToken },
|
|
31
|
+
});
|
|
32
|
+
await notebook.integrations.attach({ integration });
|
|
33
|
+
|
|
20
34
|
const publication = await notebook.publication();
|
|
21
35
|
if (publication && publication.data.provider.name !== 'cloudflare-containers') {
|
|
22
36
|
throw new Error(`Notebook is already published to ${publicationProviderLabel(publication.data.provider.name)}. Destroy that publication before changing providers.`);
|
|
@@ -28,6 +42,7 @@ try {
|
|
|
28
42
|
slug,
|
|
29
43
|
provider: {
|
|
30
44
|
name: 'cloudflare-containers',
|
|
45
|
+
accountId: cloudflareAccountId,
|
|
31
46
|
size: 'small',
|
|
32
47
|
sleepAfter: '30m',
|
|
33
48
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Client, type LaravelCloudRegion } from '../src/index.js';
|
|
1
|
+
import { Client, type Integration, type LaravelCloudRegion } from '../src/index.js';
|
|
2
2
|
import { publicationProviderLabel } from './publication-provider-label.js';
|
|
3
3
|
|
|
4
4
|
const token = process.env.PHPSANDBOX_TOKEN;
|
|
@@ -11,8 +11,6 @@ if (!notebookId) {
|
|
|
11
11
|
throw new Error('Missing PHPSANDBOX_NOTEBOOK_ID');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const apiKeySecret = 'LARAVEL_CLOUD_API_KEY';
|
|
15
|
-
const githubTokenSecret = 'GITHUB_TOKEN';
|
|
16
14
|
const slug = process.env.PHPSANDBOX_PUBLISH_SLUG ?? `sdk-laravel-cloud-${Date.now().toString(36)}`;
|
|
17
15
|
const region: LaravelCloudRegion = 'eu-central-1';
|
|
18
16
|
const apiUrl = process.env.PHPSANDBOX_API_URL ?? 'https://api.phpsandbox.io/v1';
|
|
@@ -74,39 +72,52 @@ async function publishFirstLaravelCloudPublication() {
|
|
|
74
72
|
throw new Error('Missing PHPSANDBOX_LARAVEL_CLOUD_API_KEY');
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
await
|
|
78
|
-
|
|
79
|
-
type: '
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
const existingIntegration = (await client.integrations.list()).find(({ provider }) => provider === 'github');
|
|
76
|
+
const github = existingIntegration
|
|
77
|
+
? await existingIntegration.update({ authorization: { type: 'token', token: githubToken } })
|
|
78
|
+
: await client.integrations.link({
|
|
79
|
+
provider: 'github',
|
|
80
|
+
authorization: { type: 'token', token: githubToken },
|
|
81
|
+
});
|
|
82
|
+
await selectSandboxIntegration(github);
|
|
83
|
+
const target = await notebook.git.targets.create({
|
|
83
84
|
provider: 'github',
|
|
84
85
|
repository,
|
|
85
86
|
author: { name: gitAuthorName, email: gitAuthorEmail },
|
|
86
87
|
branch: 'main',
|
|
87
|
-
credential: {
|
|
88
|
-
secret: githubTokenSecret,
|
|
89
|
-
},
|
|
90
88
|
setDefault: true,
|
|
91
89
|
});
|
|
90
|
+
const source = await target.sync();
|
|
92
91
|
|
|
93
|
-
console.log('source:', source.repository, source.branch, source.lastCommitSha);
|
|
94
|
-
|
|
95
|
-
const secret = await notebook.secrets.set(apiKeySecret, {
|
|
96
|
-
value: apiKey,
|
|
97
|
-
type: 'credential',
|
|
98
|
-
});
|
|
92
|
+
console.log('source:', source.data.repository, source.data.branch, source.data.lastCommitSha);
|
|
99
93
|
|
|
100
|
-
|
|
94
|
+
const existingLaravelCloudIntegration = (await client.integrations.list())
|
|
95
|
+
.find(({ provider }) => provider === 'laravel-cloud');
|
|
96
|
+
const laravelCloud = existingLaravelCloudIntegration
|
|
97
|
+
? await existingLaravelCloudIntegration.update({ authorization: { type: 'token', token: apiKey } })
|
|
98
|
+
: await client.integrations.link({
|
|
99
|
+
provider: 'laravel-cloud',
|
|
100
|
+
authorization: { type: 'token', token: apiKey },
|
|
101
|
+
});
|
|
102
|
+
await selectSandboxIntegration(laravelCloud);
|
|
101
103
|
|
|
102
104
|
return notebook.publish({
|
|
103
105
|
slug,
|
|
104
106
|
provider: {
|
|
105
107
|
name: 'laravel-cloud',
|
|
106
|
-
apiKey: {
|
|
107
|
-
secret: apiKeySecret,
|
|
108
|
-
},
|
|
109
108
|
region,
|
|
110
109
|
},
|
|
111
110
|
});
|
|
112
111
|
}
|
|
112
|
+
|
|
113
|
+
async function selectSandboxIntegration(integration: Integration): Promise<void> {
|
|
114
|
+
const binding = (await notebook.integrations.list())
|
|
115
|
+
.find((candidate) => candidate.integration.provider === integration.provider);
|
|
116
|
+
|
|
117
|
+
if (binding) {
|
|
118
|
+
await binding.update({ integration });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
await notebook.integrations.attach({ integration });
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phpsandbox/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A comprehensive TypeScript SDK for interacting with cloud-based PHP development environments",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -32,7 +32,16 @@
|
|
|
32
32
|
"build:tsc": "tsc",
|
|
33
33
|
"build:browser": "node build.mjs",
|
|
34
34
|
"clean": "rm -rf dist",
|
|
35
|
-
"test": "vitest run",
|
|
35
|
+
"test": "npm run build:tsc && vitest run --config vitest.config.ts",
|
|
36
|
+
"smoke": "npm run smoke:pr",
|
|
37
|
+
"smoke:pr": "npm run build:tsc && vitest run --config tests/smoke/vitest.config.ts tests/smoke/pr",
|
|
38
|
+
"smoke:nightly": "npm run build:tsc && vitest run --config tests/smoke/vitest.config.ts tests/smoke/pr tests/smoke/nightly --exclude tests/smoke/nightly/publication.smoke.ts",
|
|
39
|
+
"smoke:publications": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/nightly/publication.smoke.ts",
|
|
40
|
+
"smoke:composer-credentials": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/integrations/composer-credentials.smoke.ts",
|
|
41
|
+
"smoke:beacon": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/integrations/beacon.smoke.ts",
|
|
42
|
+
"smoke:feedback-widget": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/integrations/feedback-widget.smoke.ts",
|
|
43
|
+
"smoke:reaper": "npm run build:tsc && vitest run --reporter=verbose --config tests/smoke/vitest.config.ts tests/smoke/maintenance/resources.reaper.smoke.ts",
|
|
44
|
+
"smoke:typecheck": "npm run build:tsc && tsc --project tests/smoke/tsconfig.json --noEmit",
|
|
36
45
|
"check:examples": "tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2020 --types node --skipLibCheck --allowSyntheticDefaultImports --esModuleInterop examples/basic.ts examples/publish-cloudflare-container.ts examples/publish-laravel-cloud.ts examples/publish-ssh-agent.ts examples/get.ts examples/git-merge-smoke.ts examples/laravel-load-test.ts examples/notebook-readonly-smoke.ts",
|
|
37
46
|
"prepublishOnly": "npm test && npm run check:examples && npm run clean && npm run build",
|
|
38
47
|
"bumpAndPublish": "npm version patch && npm publish --access public"
|
|
@@ -74,6 +83,7 @@
|
|
|
74
83
|
"@types/ws": "^8.18.1",
|
|
75
84
|
"axios": "^1.17.0",
|
|
76
85
|
"esbuild": "^0.27.1",
|
|
86
|
+
"playwright": "^1.62.1",
|
|
77
87
|
"typescript": "^5.7.2",
|
|
78
88
|
"vitest": "^4.1.8"
|
|
79
89
|
}
|