@phpsandbox/sdk 0.0.61 → 0.0.64

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.
@@ -1,4 +1,4 @@
1
- import { Action, Disposable, NotebookInstance } from './index.js';
1
+ import { Action, Client, ComposerCredentials, Disposable, NotebookInstance } from './index.js';
2
2
  export interface ComposerEvents {
3
3
  'composer.log': string;
4
4
  }
@@ -29,7 +29,8 @@ export type Argument<Name extends string = string, Type extends string | string[
29
29
  export type Options<Name extends string = string, Type extends string | string[] | boolean = string | string[] | boolean> = Record<Name, Type>;
30
30
  export default class Composer {
31
31
  protected okra: NotebookInstance;
32
- constructor(okra: NotebookInstance);
32
+ readonly credentials: ComposerCredentials;
33
+ constructor(okra: NotebookInstance, client: Client);
33
34
  invoke(command: ComposerCommand, args?: Argument, options?: Options): Promise<Result>;
34
35
  dumpAutoload(): Promise<{
35
36
  message: string;
package/dist/composer.js CHANGED
@@ -1,6 +1,8 @@
1
+ import { ComposerCredentials } from './index.js';
1
2
  export default class Composer {
2
- constructor(okra) {
3
+ constructor(okra, client) {
3
4
  this.okra = okra;
5
+ this.credentials = new ComposerCredentials(client, okra.data.id);
4
6
  }
5
7
  invoke(command, args = {}, options = {}) {
6
8
  return this.okra.invoke('composer.invoke', { command, args, options });
package/dist/index.d.ts CHANGED
@@ -58,12 +58,15 @@ export interface NotebookInitProgress {
58
58
  chunk?: string;
59
59
  command?: string;
60
60
  }
61
- export type NotebookInitErrorCode = 'github_import_credential_missing';
61
+ export type NotebookInitErrorCode = 'github_import_credential_missing' | 'notebook_disk_quota_exceeded' | 'notebook_not_found' | 'notebook_setup_json_invalid' | 'notebook_backup_restore_failed';
62
62
  export interface NotebookInitErrorData {
63
63
  errorCode?: NotebookInitErrorCode;
64
64
  details?: string;
65
65
  retryable?: boolean;
66
66
  suggestedAction?: string;
67
+ phase?: string;
68
+ quotaMb?: number;
69
+ usedMb?: number;
67
70
  provider?: string;
68
71
  repository?: string;
69
72
  branch?: string | null;
@@ -118,9 +121,24 @@ export interface CreateNotebookInput extends NotebookLifecycleInput {
118
121
  title: string;
119
122
  visibility: 'public' | 'private' | 'unlisted';
120
123
  import?: CreateNotebookImportInput;
124
+ composerCredentials?: ComposerCredentialInput[];
121
125
  }
122
126
  export type ForkNotebookInput = NotebookLifecycleInput;
123
- export type UpdateNotebookInput = Omit<CreateNotebookInput, 'persistent'>;
127
+ export interface NetworkMatchCondition {
128
+ path?: string;
129
+ method?: string;
130
+ }
131
+ export interface NetworkTransformation {
132
+ match?: NetworkMatchCondition;
133
+ header?: Record<string, string>;
134
+ }
135
+ export type NetworkPolicyAllow = Record<string, NetworkTransformation[]>;
136
+ export type NetworkPolicy = 'allow' | 'deny' | {
137
+ allow: NetworkPolicyAllow;
138
+ };
139
+ export interface UpdateNotebookInput extends Omit<CreateNotebookInput, 'persistent'> {
140
+ network?: NetworkPolicy | null;
141
+ }
124
142
  export interface NotebookPolicyData {
125
143
  auto_delete_when_stale: boolean;
126
144
  stale_after_minutes: number | null;
@@ -155,6 +173,37 @@ export type UpsertNotebookSecretsInput = UpsertNotebookSecretItemInput[] | Recor
155
173
  export interface NotebookSecretDeleteOptions {
156
174
  environment?: SecretEnvironment;
157
175
  }
176
+ export type ComposerCredentialType = 'github-oauth' | 'gitlab-oauth' | 'gitlab-token' | 'bitbucket-oauth' | 'http-basic' | 'bearer';
177
+ export type ComposerCredentialInput = {
178
+ type: 'github-oauth';
179
+ token: string;
180
+ } | {
181
+ type: 'gitlab-oauth';
182
+ url: string;
183
+ token: string;
184
+ } | {
185
+ type: 'gitlab-token';
186
+ url: string;
187
+ token: string;
188
+ } | {
189
+ type: 'bitbucket-oauth';
190
+ consumerKey: string;
191
+ consumerSecret: string;
192
+ } | {
193
+ type: 'http-basic';
194
+ url: string;
195
+ username: string;
196
+ password: string;
197
+ } | {
198
+ type: 'bearer';
199
+ url: string;
200
+ token: string;
201
+ };
202
+ export interface ComposerCredentialInfo {
203
+ type: ComposerCredentialType;
204
+ url: string;
205
+ username?: string;
206
+ }
158
207
  export interface NotebookPreviewDataDisabled {
159
208
  enabled: false;
160
209
  }
@@ -164,6 +213,9 @@ export interface NotebookPreviewDataEnabled {
164
213
  expires_at: string;
165
214
  }
166
215
  export type NotebookPreviewData = NotebookPreviewDataDisabled | NotebookPreviewDataEnabled;
216
+ export type NotebookPreviewDataWithUrl = NotebookPreviewDataDisabled | (NotebookPreviewDataEnabled & {
217
+ url: string;
218
+ });
167
219
  export interface SetNotebookPreviewInput {
168
220
  password: string;
169
221
  }
@@ -171,16 +223,22 @@ export interface NotebookPreviewSessionData {
171
223
  preview_session_id: string;
172
224
  token: string;
173
225
  expires_at: string;
226
+ url: string;
227
+ }
228
+ export interface CreateNotebookPreviewSessionInput {
229
+ url: string;
174
230
  }
175
231
  export interface CreateNotebookPreviewHandoffInput {
176
232
  preview_session_id: string;
177
233
  expires_in_seconds?: number;
234
+ url: string;
178
235
  }
179
236
  export interface NotebookPreviewHandoffData {
180
237
  handoff_id: string;
181
238
  preview_session_id: string;
182
239
  token: string;
183
240
  expires_at: string;
241
+ url: string;
184
242
  }
185
243
  export interface NotebookMailRecipientData {
186
244
  name?: string;
@@ -228,6 +286,7 @@ export declare class ApiError extends Error {
228
286
  export declare class NotebookApi {
229
287
  private readonly client;
230
288
  readonly secrets: NotebookSecretApi;
289
+ readonly composerCredentials: NotebookComposerCredentialApi;
231
290
  readonly preview: NotebookPreviewApi;
232
291
  readonly mail: NotebookMailApi;
233
292
  readonly deployment: NotebookDeploymentApi;
@@ -284,13 +343,20 @@ export declare class NotebookSecretApi {
284
343
  setMany(id: string, input: UpsertNotebookSecretsInput): Promise<NotebookSecretData[]>;
285
344
  delete(id: string, name: string, options?: NotebookSecretDeleteOptions): Promise<void>;
286
345
  }
346
+ export declare class NotebookComposerCredentialApi {
347
+ private readonly client;
348
+ constructor(client: Client);
349
+ set(id: string, input: ComposerCredentialInput): Promise<ComposerCredentialInfo>;
350
+ remove(id: string, type: ComposerCredentialType, url?: string): Promise<void>;
351
+ }
287
352
  export declare class NotebookPreviewApi {
288
353
  private readonly client;
289
354
  constructor(client: Client);
290
355
  get(id: string): Promise<NotebookPreviewData>;
356
+ get(id: string, url: string): Promise<NotebookPreviewDataWithUrl>;
291
357
  setPassword(id: string, input: SetNotebookPreviewInput): Promise<NotebookPreviewData>;
292
358
  disable(id: string): Promise<void>;
293
- createSession(id: string): Promise<NotebookPreviewSessionData>;
359
+ createSession(id: string, input: CreateNotebookPreviewSessionInput): Promise<NotebookPreviewSessionData>;
294
360
  createHandoff(id: string, input: CreateNotebookPreviewHandoffInput): Promise<NotebookPreviewHandoffData>;
295
361
  }
296
362
  export declare class NotebookMailApi {
@@ -359,7 +425,7 @@ export declare class NotebookInstance {
359
425
  onDidConnect(handler: () => void): Disposable;
360
426
  onDidDisconnect(handler: () => void): Disposable;
361
427
  onDidBootError(handler: (error: NotebookUnavailableError) => void): Disposable;
362
- update(): Promise<void>;
428
+ update(input: Partial<UpdateNotebookInput>): Promise<NotebookInstance>;
363
429
  onDidInitialize(handler: (result: NotebookInitResult) => void): Disposable;
364
430
  reconnect(): Promise<NotebookInstance>;
365
431
  beacon(iframe: HTMLIFrameElement, options?: BeaconOptions): Promise<Beacon>;
@@ -373,14 +439,22 @@ export declare class NotebookSecrets {
373
439
  setMany(input: UpsertNotebookSecretsInput): Promise<NotebookSecretData[]>;
374
440
  delete(name: string, options?: NotebookSecretDeleteOptions): Promise<void>;
375
441
  }
442
+ export declare class ComposerCredentials {
443
+ private readonly client;
444
+ private readonly notebookId;
445
+ constructor(client: Client, notebookId: string);
446
+ set(input: ComposerCredentialInput): Promise<ComposerCredentialInfo>;
447
+ remove(type: ComposerCredentialType, url?: string): Promise<void>;
448
+ }
376
449
  export declare class NotebookPreview {
377
450
  private readonly client;
378
451
  private readonly notebookId;
379
452
  constructor(client: Client, notebookId: string);
380
453
  get(): Promise<NotebookPreviewData>;
454
+ get(url: string): Promise<NotebookPreviewDataWithUrl>;
381
455
  setPassword(input: SetNotebookPreviewInput): Promise<NotebookPreviewData>;
382
456
  disable(): Promise<void>;
383
- createSession(): Promise<NotebookPreviewSessionData>;
457
+ createSession(input: CreateNotebookPreviewSessionInput): Promise<NotebookPreviewSessionData>;
384
458
  createHandoff(input: CreateNotebookPreviewHandoffInput): Promise<NotebookPreviewHandoffData>;
385
459
  }
386
460
  export declare class NotebookMail {
package/dist/index.js CHANGED
@@ -97,6 +97,7 @@ export class NotebookApi {
97
97
  constructor(client) {
98
98
  this.client = client;
99
99
  this.secrets = new NotebookSecretApi(client);
100
+ this.composerCredentials = new NotebookComposerCredentialApi(client);
100
101
  this.preview = new NotebookPreviewApi(client);
101
102
  this.mail = new NotebookMailApi(client);
102
103
  this.deployment = new NotebookDeploymentApi(client);
@@ -255,12 +256,28 @@ export class NotebookSecretApi {
255
256
  await this.client.delete(`/notebook/${id}/secrets/${encodeURIComponent(name)}${query ? `?${query}` : ''}`);
256
257
  }
257
258
  }
259
+ export class NotebookComposerCredentialApi {
260
+ constructor(client) {
261
+ this.client = client;
262
+ }
263
+ async set(id, input) {
264
+ const response = await this.client.put(`/notebook/${id}/composer/credentials`, input);
265
+ return response.data;
266
+ }
267
+ async remove(id, type, url) {
268
+ const params = new URLSearchParams({ type });
269
+ if (url)
270
+ params.set('url', url);
271
+ await this.client.delete(`/notebook/${id}/composer/credentials?${params.toString()}`);
272
+ }
273
+ }
258
274
  export class NotebookPreviewApi {
259
275
  constructor(client) {
260
276
  this.client = client;
261
277
  }
262
- async get(id) {
263
- const response = await this.client.get(`/notebook/${id}/preview`);
278
+ async get(id, url) {
279
+ const query = url === undefined ? '' : `?${new URLSearchParams({ url }).toString()}`;
280
+ const response = await this.client.get(`/notebook/${id}/preview${query}`);
264
281
  return response.data;
265
282
  }
266
283
  async setPassword(id, input) {
@@ -270,8 +287,8 @@ export class NotebookPreviewApi {
270
287
  async disable(id) {
271
288
  await this.client.delete(`/notebook/${id}/preview`);
272
289
  }
273
- async createSession(id) {
274
- const response = await this.client.post(`/notebook/${id}/preview/session`);
290
+ async createSession(id, input) {
291
+ const response = await this.client.post(`/notebook/${id}/preview/session`, input);
275
292
  return response.data;
276
293
  }
277
294
  async createHandoff(id, input) {
@@ -326,7 +343,7 @@ export class NotebookInstance {
326
343
  this.terminal = new Terminal(this);
327
344
  this.auth = new Auth(this);
328
345
  this.lsp = new Lsp(this);
329
- this.composer = new Composer(this);
346
+ this.composer = new Composer(this, client);
330
347
  this.log = new Log(this);
331
348
  this.repl = new Repl(this);
332
349
  this.container = new Container(this);
@@ -475,8 +492,8 @@ export class NotebookInstance {
475
492
  this.disposables.push(disposable);
476
493
  return disposable;
477
494
  }
478
- update() {
479
- return this.invoke('notebook.update');
495
+ update(input) {
496
+ return this.client.notebook.update(this.data.id, input);
480
497
  }
481
498
  onDidInitialize(handler) {
482
499
  return this.listen('notebook.initialized', handler);
@@ -544,13 +561,25 @@ export class NotebookSecrets {
544
561
  return this.client.notebook.secrets.delete(this.notebookId, name, options);
545
562
  }
546
563
  }
564
+ export class ComposerCredentials {
565
+ constructor(client, notebookId) {
566
+ this.client = client;
567
+ this.notebookId = notebookId;
568
+ }
569
+ set(input) {
570
+ return this.client.notebook.composerCredentials.set(this.notebookId, input);
571
+ }
572
+ remove(type, url) {
573
+ return this.client.notebook.composerCredentials.remove(this.notebookId, type, url);
574
+ }
575
+ }
547
576
  export class NotebookPreview {
548
577
  constructor(client, notebookId) {
549
578
  this.client = client;
550
579
  this.notebookId = notebookId;
551
580
  }
552
- get() {
553
- return this.client.notebook.preview.get(this.notebookId);
581
+ get(url) {
582
+ return this.client.notebook.preview.get(this.notebookId, url);
554
583
  }
555
584
  setPassword(input) {
556
585
  return this.client.notebook.preview.setPassword(this.notebookId, input);
@@ -558,8 +587,8 @@ export class NotebookPreview {
558
587
  disable() {
559
588
  return this.client.notebook.preview.disable(this.notebookId);
560
589
  }
561
- createSession() {
562
- return this.client.notebook.preview.createSession(this.notebookId);
590
+ createSession(input) {
591
+ return this.client.notebook.preview.createSession(this.notebookId, input);
563
592
  }
564
593
  createHandoff(input) {
565
594
  return this.client.notebook.preview.createHandoff(this.notebookId, input);
@@ -1,4 +1,5 @@
1
1
  import { Client } from '../src/index.js';
2
+ import { deploymentTargetProviderLabel } from './deployment-provider-label.js';
2
3
 
3
4
  const token = process.env.PHPSANDBOX_TOKEN;
4
5
  if (!token) {
@@ -18,7 +19,7 @@ const notebook = await client.notebook.get(notebookId);
18
19
  try {
19
20
  const deployment = await notebook.deployment();
20
21
  if (deployment && deployment.data.targetProvider !== 'okraCloudflareContainer') {
21
- throw new Error(`Notebook is already published to ${deployment.data.targetProvider}. Delete that deployment before changing providers.`);
22
+ throw new Error(`Notebook is already published to ${deploymentTargetProviderLabel(deployment.data.targetProvider)}. Delete that deployment before changing providers.`);
22
23
  }
23
24
 
24
25
  const run = deployment
@@ -1,4 +1,5 @@
1
1
  import { Client, type LaravelCloudRegion } from '../src/index.js';
2
+ import { deploymentTargetProviderLabel } from './deployment-provider-label.js';
2
3
 
3
4
  const token = process.env.PHPSANDBOX_TOKEN;
4
5
  if (!token) {
@@ -26,7 +27,7 @@ const notebook = await client.notebook.get(notebookId);
26
27
  try {
27
28
  const deployment = await notebook.deployment();
28
29
  if (deployment && deployment.data.targetProvider !== 'okraLaravelCloud') {
29
- throw new Error(`Notebook is already published to ${deployment.data.targetProvider}. Delete that deployment before changing providers.`);
30
+ throw new Error(`Notebook is already published to ${deploymentTargetProviderLabel(deployment.data.targetProvider)}. Delete that deployment before changing providers.`);
30
31
  }
31
32
 
32
33
  const run = deployment ? await deployment.publish() : await publishFirstLaravelCloudDeployment();
@@ -4,6 +4,7 @@ import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { Client, type ServerInstance } from '../src/index.js';
7
+ import { deploymentTargetProviderLabel } from './deployment-provider-label.js';
7
8
 
8
9
  const token = process.env.PHPSANDBOX_TOKEN;
9
10
  if (!token) {
@@ -30,7 +31,7 @@ let agent: ChildProcessWithoutNullStreams | null = null;
30
31
  try {
31
32
  const deployment = await notebook.deployment();
32
33
  if (deployment && deployment.data.targetProvider !== 'okraSshAgent') {
33
- throw new Error(`Notebook is already published to ${deployment.data.targetProvider}. Delete that deployment before changing providers.`);
34
+ throw new Error(`Notebook is already published to ${deploymentTargetProviderLabel(deployment.data.targetProvider)}. Delete that deployment before changing providers.`);
34
35
  }
35
36
 
36
37
  const run = deployment
@@ -0,0 +1,11 @@
1
+ import type { DeploymentTargetProvider } from '../src/index.js';
2
+
3
+ const deploymentTargetProviderLabels: Record<DeploymentTargetProvider, string> = {
4
+ okraCloudflareContainer: 'Cloudflare Containers',
5
+ okraSshAgent: 'SSH Agent',
6
+ okraLaravelCloud: 'Laravel Cloud',
7
+ };
8
+
9
+ export function deploymentTargetProviderLabel(provider: DeploymentTargetProvider): string {
10
+ return deploymentTargetProviderLabels[provider] ?? provider;
11
+ }
@@ -2028,7 +2028,7 @@ async function requestPreviewWithSession(
2028
2028
  ): Promise<{ status: number; body: string }> {
2029
2029
  let session: NotebookPreviewSessionData;
2030
2030
  try {
2031
- session = await notebook.preview.createSession();
2031
+ session = await notebook.preview.createSession({ url });
2032
2032
  } catch (error) {
2033
2033
  if (formatError(error).includes('Preview access must be enabled')) {
2034
2034
  return requestPreview(options, url);
@@ -2037,7 +2037,7 @@ async function requestPreviewWithSession(
2037
2037
  throw error;
2038
2038
  }
2039
2039
 
2040
- const bootstrapUrl = previewUrlWithSessionToken(url, session.token);
2040
+ const bootstrapUrl = session.url;
2041
2041
  const bootstrap = await requestPreview(options, bootstrapUrl, { maxRedirects: 0 });
2042
2042
  const cookie = firstSetCookie(bootstrap.headers);
2043
2043
 
@@ -2064,12 +2064,6 @@ async function requestPreviewWithSession(
2064
2064
  };
2065
2065
  }
2066
2066
 
2067
- function previewUrlWithSessionToken(url: string, token: string): string {
2068
- const next = new URL(url);
2069
- next.searchParams.set('__helfer_preview_session', token);
2070
- return next.toString();
2071
- }
2072
-
2073
2067
  function firstSetCookie(headers: Record<string, unknown>): string | undefined {
2074
2068
  const raw = headers['set-cookie'];
2075
2069
  const value = Array.isArray(raw) ? raw[0] : raw;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phpsandbox/sdk",
3
- "version": "0.0.61",
3
+ "version": "0.0.64",
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",