@phpsandbox/sdk 0.0.57 → 0.0.59

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,18 +1,31 @@
1
+ import { ApiError } from './index.js';
2
+ import { DeploymentEventDataSchema, DeploymentLogChunkDataSchema, DeployStreamSseEventNameSchema, DeployStreamSseEventSchema, } from './schemas/deployments.js';
3
+ export * from './schemas/deployments.js';
1
4
  export class NotebookDeploymentApi {
2
5
  constructor(client) {
3
6
  this.client = client;
4
7
  }
5
- async create(id, input = {}) {
6
- const response = await this.client.post(`/notebook/${id}/deployments`, input);
7
- return new DeploymentInstance(response.data, this.client);
8
+ async current(notebookId) {
9
+ try {
10
+ const response = await this.client.get(`/notebook/${notebookId}/deployment`);
11
+ return new DeploymentInstance(response.data, this.client, notebookId);
12
+ }
13
+ catch (error) {
14
+ if (error instanceof ApiError && error.status === 404) {
15
+ return null;
16
+ }
17
+ throw error;
18
+ }
8
19
  }
9
- async list(id) {
10
- const response = await this.client.get(`/notebook/${id}/deployments`);
11
- return response.data;
20
+ async publish(notebookId, input) {
21
+ const response = await this.client.post(`/notebook/${notebookId}/deployment/publish`, input);
22
+ const run = new DeploymentRun(new DeploymentInstance(response.data, this.client, notebookId), this.client);
23
+ run.start();
24
+ return run;
12
25
  }
13
26
  async slugAvailability(id, slug) {
14
27
  const query = new URLSearchParams({ slug }).toString();
15
- const response = await this.client.get(`/notebook/${id}/deployments/slug-availability?${query}`);
28
+ const response = await this.client.get(`/notebook/${id}/deployment/slug-availability?${query}`);
16
29
  return response.data;
17
30
  }
18
31
  }
@@ -24,10 +37,6 @@ export class DeploymentApi {
24
37
  const response = await this.client.get(`/deployments/${id}`);
25
38
  return new DeploymentInstance(response.data, this.client);
26
39
  }
27
- async redeploy(id, input = {}) {
28
- const response = await this.client.post(`/deployments/${id}/redeploy`, input);
29
- return new DeploymentInstance(response.data, this.client);
30
- }
31
40
  async delete(id) {
32
41
  await this.client.delete(`/deployments/${id}`);
33
42
  }
@@ -67,25 +76,140 @@ export class DeploymentApi {
67
76
  await this.client.delete(`/deployments/${id}/domains/${domainId}`);
68
77
  }
69
78
  async events(id) {
70
- return parseNdjsonStream(await this.client.stream(`/deployments/${id}/events/stream`));
79
+ return parseNdjsonStream(await this.client.stream(`/deployments/${id}/events/stream`), DeploymentEventDataSchema);
71
80
  }
72
81
  async buildLogs(id, buildId) {
73
- return parseNdjsonStream(await this.client.stream(`/deployments/${id}/builds/${buildId}/logs/stream`));
82
+ return parseNdjsonStream(await this.client.stream(`/deployments/${id}/builds/${buildId}/logs/stream`), DeploymentLogChunkDataSchema);
74
83
  }
75
84
  async logs(id) {
76
- return parseNdjsonStream(await this.client.stream(`/deployments/${id}/logs/stream`));
85
+ return parseNdjsonStream(await this.client.stream(`/deployments/${id}/logs/stream`), DeploymentLogChunkDataSchema);
86
+ }
87
+ }
88
+ export class DeploymentRun {
89
+ constructor(initial, client) {
90
+ this.initial = initial;
91
+ this.client = client;
92
+ this.started = false;
93
+ this.completed = false;
94
+ this.finalError = null;
95
+ this.finalResult = null;
96
+ this.resultPromise = null;
97
+ this.resolveResult = null;
98
+ this.rejectResult = null;
99
+ this.bufferedEvents = [];
100
+ this.subscribers = new Set();
101
+ }
102
+ async *events() {
103
+ this.start();
104
+ const queue = this.subscribe();
105
+ try {
106
+ for await (const event of queue) {
107
+ yield event;
108
+ }
109
+ }
110
+ finally {
111
+ this.subscribers.delete(queue);
112
+ queue.close();
113
+ }
114
+ }
115
+ result() {
116
+ this.start();
117
+ return this.resultPromise;
118
+ }
119
+ async deployment() {
120
+ await this.result();
121
+ return this.initial.refresh();
122
+ }
123
+ start() {
124
+ if (this.started) {
125
+ return this;
126
+ }
127
+ if (!this.initial.data.okraUrl) {
128
+ throw new Error(`Deployment ${this.initial.data.id} has no okraUrl for SSE streaming`);
129
+ }
130
+ this.started = true;
131
+ this.resultPromise = new Promise((resolve, reject) => {
132
+ this.resolveResult = resolve;
133
+ this.rejectResult = reject;
134
+ });
135
+ this.resultPromise.catch(() => undefined);
136
+ void this.consumeStream(this.initial.data.okraUrl);
137
+ return this;
138
+ }
139
+ subscribe() {
140
+ const queue = new AsyncDeployEventQueue();
141
+ for (const event of this.bufferedEvents) {
142
+ queue.push(event);
143
+ }
144
+ if (this.finalError) {
145
+ queue.fail(this.finalError);
146
+ }
147
+ else if (this.completed) {
148
+ queue.close();
149
+ }
150
+ else {
151
+ this.subscribers.add(queue);
152
+ }
153
+ return queue;
154
+ }
155
+ async consumeStream(okraUrl) {
156
+ try {
157
+ const stream = await this.client.sse(okraUrl);
158
+ for await (const event of readDeployStreamEvents(stream)) {
159
+ this.publish(event);
160
+ if (event.type === 'result') {
161
+ const { type: _, ...result } = event;
162
+ this.finalResult = result;
163
+ this.resolveResult?.(result);
164
+ }
165
+ }
166
+ if (!this.finalResult) {
167
+ throw new Error('Deploy stream ended without result');
168
+ }
169
+ this.closeSubscribers();
170
+ }
171
+ catch (err) {
172
+ this.fail(err instanceof Error ? err : new Error(String(err)));
173
+ }
174
+ }
175
+ publish(event) {
176
+ this.bufferedEvents.push(event);
177
+ for (const subscriber of this.subscribers) {
178
+ subscriber.push(event);
179
+ }
180
+ }
181
+ closeSubscribers() {
182
+ this.completed = true;
183
+ for (const subscriber of this.subscribers) {
184
+ subscriber.close();
185
+ }
186
+ this.subscribers.clear();
187
+ }
188
+ fail(error) {
189
+ this.finalError = error;
190
+ this.completed = true;
191
+ this.rejectResult?.(error);
192
+ for (const subscriber of this.subscribers) {
193
+ subscriber.fail(error);
194
+ }
195
+ this.subscribers.clear();
77
196
  }
78
197
  }
79
198
  export class DeploymentInstance {
80
- constructor(data, client) {
199
+ constructor(data, client, notebookId) {
81
200
  this.data = data;
82
201
  this.client = client;
202
+ this.notebookId = notebookId;
83
203
  }
84
- refresh() {
85
- return this.client.deployments.get(this.data.id);
204
+ async refresh() {
205
+ const response = await this.client.get(`/deployments/${this.data.id}`);
206
+ return new DeploymentInstance(response.data, this.client, this.notebookId);
86
207
  }
87
- redeploy(input = {}) {
88
- return this.client.deployments.redeploy(this.data.id, input);
208
+ publish() {
209
+ if (!this.notebookId) {
210
+ return Promise.reject(new Error('Deployment publish requires a notebook-scoped deployment instance.'));
211
+ }
212
+ return this.client.notebook.deployment.publish(this.notebookId);
89
213
  }
90
214
  delete() {
91
215
  return this.client.deployments.delete(this.data.id);
@@ -107,7 +231,7 @@ export class DeploymentInstance {
107
231
  events() {
108
232
  return this.client.deployments.events(this.data.id);
109
233
  }
110
- buildLogs(buildId = this.data.latest_build?.id ?? '') {
234
+ buildLogs(buildId = this.data.latestBuild?.id ?? '') {
111
235
  if (buildId === '') {
112
236
  return Promise.reject(new Error('Deployment has no latest build id'));
113
237
  }
@@ -156,7 +280,143 @@ function unwrapDeploymentDomainCollection(input) {
156
280
  }
157
281
  return Array.isArray(input.data) ? input.data : [];
158
282
  }
159
- function parseNdjsonStream(input) {
283
+ class AsyncDeployEventQueue {
284
+ constructor() {
285
+ this.values = [];
286
+ this.pending = [];
287
+ this.closed = false;
288
+ this.error = null;
289
+ }
290
+ push(value) {
291
+ if (this.closed) {
292
+ return;
293
+ }
294
+ const next = this.pending.shift();
295
+ if (next) {
296
+ next.resolve({ done: false, value });
297
+ return;
298
+ }
299
+ this.values.push(value);
300
+ }
301
+ close() {
302
+ if (this.closed) {
303
+ return;
304
+ }
305
+ this.closed = true;
306
+ for (const next of this.pending.splice(0)) {
307
+ next.resolve({ done: true, value: undefined });
308
+ }
309
+ }
310
+ fail(error) {
311
+ if (this.closed) {
312
+ return;
313
+ }
314
+ this.error = error;
315
+ this.closed = true;
316
+ for (const next of this.pending.splice(0)) {
317
+ next.reject(error);
318
+ }
319
+ }
320
+ async *[Symbol.asyncIterator]() {
321
+ while (true) {
322
+ const next = await this.next();
323
+ if (next.done) {
324
+ return;
325
+ }
326
+ yield next.value;
327
+ }
328
+ }
329
+ next() {
330
+ const value = this.values.shift();
331
+ if (value) {
332
+ return Promise.resolve({ done: false, value });
333
+ }
334
+ if (this.error) {
335
+ return Promise.reject(this.error);
336
+ }
337
+ if (this.closed) {
338
+ return Promise.resolve({ done: true, value: undefined });
339
+ }
340
+ return new Promise((resolve, reject) => {
341
+ this.pending.push({ resolve, reject });
342
+ });
343
+ }
344
+ }
345
+ async function* readDeployStreamEvents(stream) {
346
+ const reader = parseSSEStream(stream).getReader();
347
+ try {
348
+ while (true) {
349
+ const { done, value } = await reader.read();
350
+ if (done) {
351
+ return;
352
+ }
353
+ const event = parseDeployStreamEvent(value);
354
+ if (event) {
355
+ yield event;
356
+ }
357
+ }
358
+ }
359
+ finally {
360
+ reader.releaseLock();
361
+ }
362
+ }
363
+ function parseDeployStreamEvent(event) {
364
+ if (!DeployStreamSseEventNameSchema.safeParse(event.event).success) {
365
+ return null;
366
+ }
367
+ return DeployStreamSseEventSchema.parse(event);
368
+ }
369
+ function parseSSEStream(input) {
370
+ const decoder = new TextDecoder();
371
+ let buffer = '';
372
+ return input.pipeThrough(new TransformStream({
373
+ transform(chunk, controller) {
374
+ buffer += decoder.decode(chunk, { stream: true });
375
+ const blocks = buffer.split('\n\n');
376
+ buffer = blocks.pop() ?? '';
377
+ for (const block of blocks) {
378
+ const event = parseSSEBlock(block);
379
+ if (event) {
380
+ controller.enqueue(event);
381
+ }
382
+ }
383
+ },
384
+ flush(controller) {
385
+ buffer += decoder.decode();
386
+ if (buffer.trim() !== '') {
387
+ const event = parseSSEBlock(buffer);
388
+ if (event) {
389
+ controller.enqueue(event);
390
+ }
391
+ }
392
+ },
393
+ }));
394
+ }
395
+ function parseSSEBlock(block) {
396
+ let eventType = 'message';
397
+ let data = '';
398
+ for (const line of block.split('\n')) {
399
+ if (line.startsWith('event: ')) {
400
+ eventType = line.slice(7).trim();
401
+ }
402
+ else if (line.startsWith('data: ')) {
403
+ data += line.slice(6);
404
+ }
405
+ else if (line.startsWith('data:')) {
406
+ data += line.slice(5);
407
+ }
408
+ }
409
+ if (data === '') {
410
+ return null;
411
+ }
412
+ try {
413
+ return { event: eventType, data: JSON.parse(data) };
414
+ }
415
+ catch {
416
+ return { event: eventType, data };
417
+ }
418
+ }
419
+ function parseNdjsonStream(input, schema) {
160
420
  const decoder = new TextDecoder();
161
421
  let buffer = '';
162
422
  return input.pipeThrough(new TransformStream({
@@ -167,7 +427,7 @@ function parseNdjsonStream(input) {
167
427
  for (const line of lines) {
168
428
  const trimmed = line.trim();
169
429
  if (trimmed !== '') {
170
- controller.enqueue(JSON.parse(trimmed));
430
+ controller.enqueue(schema.parse(JSON.parse(trimmed)));
171
431
  }
172
432
  }
173
433
  },
@@ -175,7 +435,7 @@ function parseNdjsonStream(input) {
175
435
  buffer += decoder.decode();
176
436
  const trimmed = buffer.trim();
177
437
  if (trimmed !== '') {
178
- controller.enqueue(JSON.parse(trimmed));
438
+ controller.enqueue(schema.parse(JSON.parse(trimmed)));
179
439
  }
180
440
  },
181
441
  }));
package/dist/git.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Client, SecretRef } from './index.js';
1
2
  import { Action, NotebookInstance } from './index.js';
2
3
  export interface GitLog {
3
4
  hash: string;
@@ -48,6 +49,36 @@ export interface GitCredentials {
48
49
  abilities: string[];
49
50
  expiresAt: string;
50
51
  }
52
+ export type GitProvider = 'github' | (string & {});
53
+ export type GitRepositoryVisibility = 'private' | 'public';
54
+ export type GitSyncDirection = 'pull' | 'push' | 'both';
55
+ export interface GitSyncAuthor {
56
+ name: string;
57
+ email: string;
58
+ }
59
+ export interface GitSyncTargetInput {
60
+ provider: GitProvider;
61
+ repository: string;
62
+ author: GitSyncAuthor;
63
+ branch?: string;
64
+ credential: SecretRef;
65
+ direction?: GitSyncDirection;
66
+ visibility?: GitRepositoryVisibility;
67
+ setDefault?: boolean;
68
+ }
69
+ export interface GitSyncTargetData {
70
+ id: string;
71
+ provider: GitProvider;
72
+ repository: string;
73
+ url: string | null;
74
+ branch: string;
75
+ credentialConfigured: boolean;
76
+ default: boolean;
77
+ lastCommitSha: string | null;
78
+ lastSyncedAt: string | null;
79
+ createdAt: string | null;
80
+ updatedAt: string | null;
81
+ }
51
82
  export interface GitCheckoutResult extends GitRef {
52
83
  branch: string;
53
84
  created: boolean;
@@ -180,10 +211,12 @@ export interface GitActions {
180
211
  }
181
212
  export default class Git {
182
213
  protected okra: NotebookInstance;
183
- constructor(okra: NotebookInstance);
214
+ private readonly client;
215
+ constructor(okra: NotebookInstance, client: Client);
184
216
  checkpoint(author: string, message: string, branch?: string, allowEmpty?: boolean): Promise<GitRef>;
185
217
  checkout(branch: string, create?: boolean): Promise<GitCheckoutResult>;
186
- sync(url: string, author: string, ref?: string, token?: string, direction?: 'pull' | 'push' | 'both', force?: boolean): Promise<GitRef>;
218
+ sync(input: GitSyncTargetInput): Promise<GitSyncTargetData>;
219
+ syncTargets(): Promise<GitSyncTargetData[]>;
187
220
  log(ref?: string): Promise<GitLog[]>;
188
221
  diff(input: GitDiffInput): Promise<GitDiffPreview>;
189
222
  merge(input: GitMergeInput): Promise<GitMergeResult>;
@@ -199,5 +232,6 @@ export default class Git {
199
232
  status(): Promise<GitStatus>;
200
233
  private normalizeRemoteInput;
201
234
  private gitUrlForNotebook;
235
+ private omitUndefined;
202
236
  }
203
237
  export {};
package/dist/git.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export default class Git {
2
- constructor(okra) {
2
+ constructor(okra, client) {
3
3
  this.okra = okra;
4
+ this.client = client;
4
5
  }
5
6
  checkpoint(author, message, branch = 'main', allowEmpty = false) {
6
7
  return this.okra.invoke('git.checkpoint', { author, message, branch, allowEmpty });
@@ -8,8 +9,13 @@ export default class Git {
8
9
  checkout(branch, create = true) {
9
10
  return this.okra.invoke('git.checkout', { branch, create });
10
11
  }
11
- sync(url, author, ref = 'main', token, direction = 'both', force = false) {
12
- return this.okra.invoke('git.sync', { url, author, ref, token, direction, force });
12
+ async sync(input) {
13
+ const response = await this.client.post(`/notebook/${this.okra.data.id}/git/sync-targets`, this.omitUndefined({ ...input }));
14
+ return response.data;
15
+ }
16
+ async syncTargets() {
17
+ const response = await this.client.get(`/notebook/${this.okra.data.id}/git/sync-targets`);
18
+ return response.data;
13
19
  }
14
20
  log(ref = 'main') {
15
21
  return this.okra.invoke('git.log', { ref });
@@ -79,4 +85,7 @@ export default class Git {
79
85
  url.hash = '';
80
86
  return url.toString();
81
87
  }
88
+ omitUndefined(input) {
89
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
90
+ }
82
91
  }
package/dist/index.d.ts CHANGED
@@ -15,7 +15,8 @@ import Git, { GitActions, GitCredentials, GitEvents } from './git.js';
15
15
  import { Disposable } from './types.js';
16
16
  import { Beacon, BeaconOptions } from './beacon/index.js';
17
17
  import { NotebookUnavailableError } from './errors/index.js';
18
- import { DeploymentApi, NotebookDeploymentApi, type DeployInput, type DeploymentInstance } from './deployments.js';
18
+ import { DeploymentApi, NotebookDeploymentApi, type DeploymentInstance, type DeploymentRun, type PublishInput } from './deployments.js';
19
+ import { ServerApi } from './servers.js';
19
20
  export * from './types.js';
20
21
  export { Transport } from './socket/index.js';
21
22
  export * from './lsp.js';
@@ -30,6 +31,7 @@ export * from './utils/promise.js';
30
31
  export * from './beacon/index.js';
31
32
  export * from './errors/index.js';
32
33
  export * from './deployments.js';
34
+ export * from './servers.js';
33
35
  interface Result<TType extends 'success' | 'error' | 'running', TData extends object> {
34
36
  type: TType;
35
37
  message: string;
@@ -125,10 +127,15 @@ export interface NotebookPolicyData {
125
127
  prune_after_at: string | null;
126
128
  }
127
129
  export type SecretEnvironment = 'development' | 'production';
130
+ export type SecretType = 'environment_variable' | 'credential';
131
+ export interface SecretRef {
132
+ secret: string;
133
+ environment?: SecretEnvironment;
134
+ }
128
135
  export interface NotebookSecretData {
129
136
  uuid: string;
130
137
  name: string;
131
- type: 'environment_variable';
138
+ type: SecretType;
132
139
  environment: SecretEnvironment;
133
140
  createdAt: string | null;
134
141
  updatedAt: string | null;
@@ -138,7 +145,7 @@ export interface NotebookSecretListOptions {
138
145
  }
139
146
  export interface UpsertNotebookSecretInput {
140
147
  value: string;
141
- type?: 'environment_variable';
148
+ type?: SecretType;
142
149
  environment?: SecretEnvironment;
143
150
  }
144
151
  export interface UpsertNotebookSecretItemInput extends UpsertNotebookSecretInput {
@@ -223,7 +230,7 @@ export declare class NotebookApi {
223
230
  readonly secrets: NotebookSecretApi;
224
231
  readonly preview: NotebookPreviewApi;
225
232
  readonly mail: NotebookMailApi;
226
- readonly deployments: NotebookDeploymentApi;
233
+ readonly deployment: NotebookDeploymentApi;
227
234
  constructor(client: Client);
228
235
  create(template: string, input?: Partial<CreateNotebookInput>, init?: boolean): Promise<NotebookInstance>;
229
236
  get(id: string): Promise<NotebookInstance>;
@@ -245,6 +252,7 @@ export interface PHPSandboxClientOptions {
245
252
  export declare class Client {
246
253
  readonly notebook: NotebookApi;
247
254
  readonly deployments: DeploymentApi;
255
+ readonly servers: ServerApi;
248
256
  readonly options: PHPSandboxClientOptions;
249
257
  private readonly fetch;
250
258
  private readonly baseUrl;
@@ -263,6 +271,7 @@ export declare class Client {
263
271
  data: T;
264
272
  }>;
265
273
  stream(path: string): Promise<ReadableStream<Uint8Array>>;
274
+ sse(url: string): Promise<ReadableStream<Uint8Array>>;
266
275
  private makeRequest;
267
276
  }
268
277
  export declare class PHPSandbox extends Client {
@@ -331,7 +340,8 @@ export declare class NotebookInstance {
331
340
  constructor(data: NotebookData, client: Client);
332
341
  ready(): Promise<NotebookInitSuccessResult>;
333
342
  fork(input?: Partial<ForkNotebookInput>): Promise<NotebookInstance>;
334
- deploy(input?: DeployInput): Promise<DeploymentInstance>;
343
+ deployment(): Promise<DeploymentInstance | null>;
344
+ publish(input?: PublishInput): Promise<DeploymentRun>;
335
345
  gitCredentials(): Promise<GitCredentials>;
336
346
  delete(): Promise<void>;
337
347
  stop(): Promise<void>;
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ import Git from './git.js';
28
28
  import { createBeacon } from './beacon/index.js';
29
29
  import { NotebookUnavailableError } from './errors/index.js';
30
30
  import { DeploymentApi, NotebookDeploymentApi } from './deployments.js';
31
+ import { ServerApi } from './servers.js';
31
32
  export * from './types.js';
32
33
  export { Transport } from './socket/index.js';
33
34
  export * from './lsp.js';
@@ -42,6 +43,7 @@ export * from './utils/promise.js';
42
43
  export * from './beacon/index.js';
43
44
  export * from './errors/index.js';
44
45
  export * from './deployments.js';
46
+ export * from './servers.js';
45
47
  function normalizeNotebookSecretInputs(input) {
46
48
  if (Array.isArray(input)) {
47
49
  return input;
@@ -97,7 +99,7 @@ export class NotebookApi {
97
99
  this.secrets = new NotebookSecretApi(client);
98
100
  this.preview = new NotebookPreviewApi(client);
99
101
  this.mail = new NotebookMailApi(client);
100
- this.deployments = new NotebookDeploymentApi(client);
102
+ this.deployment = new NotebookDeploymentApi(client);
101
103
  }
102
104
  async create(template, input = {}, init = true) {
103
105
  const response = await this.client.post('/notebook', { template, ...input });
@@ -151,6 +153,7 @@ export class Client {
151
153
  this.fetch = globalThis.fetch;
152
154
  this.deployments = new DeploymentApi(this);
153
155
  this.notebook = new NotebookApi(this);
156
+ this.servers = new ServerApi(this);
154
157
  this.options = Object.assign({ startClosed: true }, options);
155
158
  this.baseUrl = normalizeApiBaseUrl(url);
156
159
  if (options.fetch) {
@@ -187,6 +190,22 @@ export class Client {
187
190
  }
188
191
  return response.body;
189
192
  }
193
+ async sse(url) {
194
+ const response = await this.fetch(new Request(url, {
195
+ method: 'GET',
196
+ headers: {
197
+ ...this.headers,
198
+ 'Accept': 'text/event-stream',
199
+ },
200
+ }));
201
+ if (!response.ok) {
202
+ throw new ApiError(response, await response.text());
203
+ }
204
+ if (!response.body) {
205
+ throw new Error('PHPSandbox API Error: SSE response body is not readable');
206
+ }
207
+ return response.body;
208
+ }
190
209
  async makeRequest(method, path, init) {
191
210
  const response = await this.fetch(new Request(new URL(path.replace(/^\//, ''), this.baseUrl), {
192
211
  method,
@@ -313,7 +332,7 @@ export class NotebookInstance {
313
332
  this.container = new Container(this);
314
333
  this.laravel = new Laravel(this);
315
334
  this.shell = new Shell(this);
316
- this.git = new Git(this);
335
+ this.git = new Git(this, client);
317
336
  this.services = new Services(this);
318
337
  this.config = new Config(this);
319
338
  this.secrets = new NotebookSecrets(client, this.data.id);
@@ -342,8 +361,11 @@ export class NotebookInstance {
342
361
  fork(input = {}) {
343
362
  return this.client.notebook.fork(this.data.id, input);
344
363
  }
345
- deploy(input = {}) {
346
- return this.client.notebook.deployments.create(this.data.id, input);
364
+ deployment() {
365
+ return this.client.notebook.deployment.current(this.data.id);
366
+ }
367
+ publish(input) {
368
+ return this.client.notebook.deployment.publish(this.data.id, input);
347
369
  }
348
370
  gitCredentials() {
349
371
  return this.client.notebook.gitCredentials(this.data.id);