@watasu/sdk 0.1.40 → 0.1.50
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 +10 -4
- package/dist/codeInterpreter.d.ts +124 -25
- package/dist/codeInterpreter.js +62 -24
- package/dist/commands.d.ts +11 -2
- package/dist/commands.js +11 -10
- package/dist/connectionConfig.d.ts +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +54 -4
- package/dist/filesystem.d.ts +13 -1
- package/dist/filesystem.js +51 -8
- package/dist/git.d.ts +5 -2
- package/dist/index.d.ts +22 -10
- package/dist/index.js +7 -5
- package/dist/process.js +8 -4
- package/dist/processSocket.d.ts +15 -3
- package/dist/processSocket.js +108 -6
- package/dist/pty.js +1 -1
- package/dist/sandbox.d.ts +34 -5
- package/dist/sandbox.js +48 -14
- package/dist/template.d.ts +36 -7
- package/dist/template.js +104 -29
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +5 -1
- package/dist/volume.d.ts +15 -4
- package/dist/volume.js +8 -0
- package/package.json +2 -2
package/dist/sandbox.js
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { Commands } from './commands.js';
|
|
2
3
|
import { ConnectionConfig, SESSION_OPERATION_REQUEST_TIMEOUT_MS } from './connectionConfig.js';
|
|
3
4
|
import { DataPlaneClient, ControlClient, withQuery } from './transport.js';
|
|
4
|
-
import { ConflictError, FileNotFoundError, NotFoundError, SandboxError
|
|
5
|
+
import { ConflictError, FileNotFoundError, NotFoundError, SandboxError } from './errors.js';
|
|
5
6
|
import { Filesystem } from './filesystem.js';
|
|
6
7
|
import { Git } from './git.js';
|
|
7
8
|
import { Pty } from './pty.js';
|
|
8
9
|
import { ProcessManager } from './process.js';
|
|
9
10
|
import { TerminalManager } from './terminal.js';
|
|
11
|
+
export const ALL_TRAFFIC = '0.0.0.0/0';
|
|
12
|
+
export async function getSignature({ path, operation, user, expirationInSeconds, envdAccessToken, }) {
|
|
13
|
+
if (!envdAccessToken)
|
|
14
|
+
throw new Error('Access token is not set and signature cannot be generated');
|
|
15
|
+
const expiration = expirationInSeconds ? Math.floor(Date.now() / 1000) + expirationInSeconds : null;
|
|
16
|
+
const signatureRaw = expiration === null
|
|
17
|
+
? `${path}:${operation}:${user ?? ''}:${envdAccessToken}`
|
|
18
|
+
: `${path}:${operation}:${user ?? ''}:${envdAccessToken}:${expiration}`;
|
|
19
|
+
const hashBase64 = await sha256(signatureRaw);
|
|
20
|
+
return { signature: `v1_${hashBase64.replace(/=+$/, '')}`, expiration };
|
|
21
|
+
}
|
|
10
22
|
/** Paginator for listing sandbox snapshots. */
|
|
11
23
|
export class SnapshotPaginator {
|
|
12
24
|
opts;
|
|
@@ -111,7 +123,7 @@ export class Sandbox {
|
|
|
111
123
|
this.terminal = new TerminalManager(this.pty);
|
|
112
124
|
this.git = new Git(dataPlane);
|
|
113
125
|
}
|
|
114
|
-
/**
|
|
126
|
+
/** Unique sandbox identifier. */
|
|
115
127
|
get id() {
|
|
116
128
|
return this.sandboxId;
|
|
117
129
|
}
|
|
@@ -331,6 +343,10 @@ export class Sandbox {
|
|
|
331
343
|
});
|
|
332
344
|
return sandboxInfo(record(payload.sandbox ?? payload));
|
|
333
345
|
}
|
|
346
|
+
/** Fetch full control-plane metadata for a sandbox by id. */
|
|
347
|
+
static async getFullInfo(sandboxId, opts = {}) {
|
|
348
|
+
return this.getInfo(sandboxId, opts);
|
|
349
|
+
}
|
|
334
350
|
/** Fetch the latest control-plane metadata for this sandbox. */
|
|
335
351
|
async getInfo(opts = {}) {
|
|
336
352
|
const payload = await this.control.get(`/sandboxes/${this.sandboxId}`, {
|
|
@@ -351,10 +367,6 @@ export class Sandbox {
|
|
|
351
367
|
async deleteSnapshot(snapshotId, opts = {}) {
|
|
352
368
|
return Sandbox.deleteSnapshot(snapshotId, { ...this.configOptions(), ...opts });
|
|
353
369
|
}
|
|
354
|
-
/** Watasu-native alias for `createSnapshot`. */
|
|
355
|
-
async checkpoint(opts = {}) {
|
|
356
|
-
return this.createSnapshot(opts);
|
|
357
|
-
}
|
|
358
370
|
/** List checkpoints for this sandbox using snapshot naming. */
|
|
359
371
|
listSnapshots(opts = {}) {
|
|
360
372
|
return Sandbox.listSnapshots({ ...this.configOptions(), ...opts, sandboxId: this.sandboxId });
|
|
@@ -688,23 +700,37 @@ function putIfPresent(target, key, value) {
|
|
|
688
700
|
function networkUpdatePayload(network) {
|
|
689
701
|
if (network === undefined)
|
|
690
702
|
return {};
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
unsupported('network rules');
|
|
695
|
-
if (network.maskRequestHost !== undefined)
|
|
696
|
-
unsupported('network request host masking');
|
|
703
|
+
const rules = network.rules instanceof Map
|
|
704
|
+
? network.rules
|
|
705
|
+
: new Map(Object.entries(network.rules ?? {}));
|
|
697
706
|
return compactRecord({
|
|
698
|
-
allow_out: network.allowOut,
|
|
699
|
-
deny_out: network.denyOut,
|
|
707
|
+
allow_out: resolveNetworkSelector(network.allowOut, rules),
|
|
708
|
+
deny_out: resolveNetworkSelector(network.denyOut, rules),
|
|
700
709
|
allow_internet_access: network.allowInternetAccess,
|
|
701
710
|
allow_package_registry_access: network.allowPackageRegistryAccess,
|
|
702
711
|
allow_public_traffic: network.allowPublicTraffic,
|
|
703
712
|
egress_profile: network.egressProfile,
|
|
704
713
|
egress_profiles: network.egressProfiles,
|
|
705
714
|
network_class: network.networkClass,
|
|
715
|
+
rules: network.rules === undefined ? undefined : resolveNetworkRules(rules),
|
|
716
|
+
mask_request_host: network.maskRequestHost,
|
|
706
717
|
});
|
|
707
718
|
}
|
|
719
|
+
function resolveNetworkSelector(selector, rules) {
|
|
720
|
+
if (selector === undefined)
|
|
721
|
+
return undefined;
|
|
722
|
+
if (typeof selector === 'function')
|
|
723
|
+
return selector({ allTraffic: ALL_TRAFFIC, rules }).map(String);
|
|
724
|
+
if (typeof selector === 'string')
|
|
725
|
+
return [selector];
|
|
726
|
+
return selector.map(String);
|
|
727
|
+
}
|
|
728
|
+
function resolveNetworkRules(rules) {
|
|
729
|
+
return Object.fromEntries(Array.from(rules.entries()).map(([host, hostRules]) => [
|
|
730
|
+
host,
|
|
731
|
+
hostRules.map((rule) => rule.transform === undefined ? {} : { transform: rule.transform }),
|
|
732
|
+
]));
|
|
733
|
+
}
|
|
708
734
|
function record(value) {
|
|
709
735
|
return value && typeof value === 'object' ? value : {};
|
|
710
736
|
}
|
|
@@ -726,3 +752,11 @@ function routeTokenFromDataPlaneUrl(value, dataPlaneDomain) {
|
|
|
726
752
|
const token = host.slice(0, -suffix.length);
|
|
727
753
|
return token || undefined;
|
|
728
754
|
}
|
|
755
|
+
async function sha256(data) {
|
|
756
|
+
if (globalThis.crypto?.subtle) {
|
|
757
|
+
const bytes = new TextEncoder().encode(data);
|
|
758
|
+
const hash = await globalThis.crypto.subtle.digest('SHA-256', bytes);
|
|
759
|
+
return Buffer.from(hash).toString('base64');
|
|
760
|
+
}
|
|
761
|
+
return createHash('sha256').update(data, 'utf8').digest('base64');
|
|
762
|
+
}
|
package/dist/template.d.ts
CHANGED
|
@@ -12,10 +12,20 @@ export interface BuildInfo {
|
|
|
12
12
|
/** Build identifier. */
|
|
13
13
|
buildId: string;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
export type LogEntryLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
16
|
+
export type Logger = (logEntry: LogEntry) => void;
|
|
17
|
+
export declare class LogEntry {
|
|
18
|
+
readonly timestamp: Date;
|
|
19
|
+
readonly level: LogEntryLevel;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
constructor(timestamp?: Date, level?: LogEntryLevel, message?: string);
|
|
22
|
+
toString(): string;
|
|
23
|
+
}
|
|
24
|
+
export declare class LogEntryStart extends LogEntry {
|
|
25
|
+
constructor(timestamp?: Date, message?: string);
|
|
26
|
+
}
|
|
27
|
+
export declare class LogEntryEnd extends LogEntry {
|
|
28
|
+
constructor(timestamp?: Date, message?: string);
|
|
19
29
|
}
|
|
20
30
|
export interface BuildStatusReason {
|
|
21
31
|
message: string;
|
|
@@ -75,6 +85,9 @@ export type TemplateBuilder = TemplateBase;
|
|
|
75
85
|
export type TemplateFinal = TemplateBase;
|
|
76
86
|
export type TemplateFromImage = TemplateBase;
|
|
77
87
|
export type ReadyCommand = string | ReadyCmd;
|
|
88
|
+
export declare function defaultBuildLogger(options?: {
|
|
89
|
+
minLevel?: LogEntryLevel;
|
|
90
|
+
}): Logger;
|
|
78
91
|
interface TemplateFileSpec {
|
|
79
92
|
path: string;
|
|
80
93
|
content_b64: string;
|
|
@@ -84,6 +97,10 @@ interface TemplateFileSpec {
|
|
|
84
97
|
}
|
|
85
98
|
interface BuildSpec {
|
|
86
99
|
base?: string;
|
|
100
|
+
from_template?: string;
|
|
101
|
+
from_image?: string;
|
|
102
|
+
from_image_registry?: Record<string, unknown>;
|
|
103
|
+
requested_from_image?: string;
|
|
87
104
|
packages?: Record<string, string[]>;
|
|
88
105
|
files?: TemplateFileSpec[];
|
|
89
106
|
setup?: string[];
|
|
@@ -111,6 +128,8 @@ export declare function waitForTimeout(timeout: number): ReadyCmd;
|
|
|
111
128
|
/** Chainable template builder for Watasu package-spec template builds. */
|
|
112
129
|
export declare class TemplateBase {
|
|
113
130
|
private base;
|
|
131
|
+
private fromImageReference;
|
|
132
|
+
private fromImageRegistry;
|
|
114
133
|
private packages;
|
|
115
134
|
private files;
|
|
116
135
|
private setup;
|
|
@@ -135,24 +154,34 @@ export declare class TemplateBase {
|
|
|
135
154
|
static getTags(templateId: string, options?: ConnectionOpts): Promise<TemplateTag[]>;
|
|
136
155
|
static toJSON(template: TemplateClass): Promise<string>;
|
|
137
156
|
static toDockerfile(template: TemplateClass): string;
|
|
157
|
+
/** Request a Debian public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
138
158
|
fromDebianImage(_variant?: string): TemplateBuilder;
|
|
159
|
+
/** Request an Ubuntu public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
139
160
|
fromUbuntuImage(_variant?: string): TemplateBuilder;
|
|
161
|
+
/** Request a Python public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
140
162
|
fromPythonImage(_version?: string): TemplateBuilder;
|
|
163
|
+
/** Request a Node.js public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
141
164
|
fromNodeImage(_variant?: string): TemplateBuilder;
|
|
165
|
+
/** Request a Bun public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
142
166
|
fromBunImage(_variant?: string): TemplateBuilder;
|
|
167
|
+
/** Start from the Watasu platform base template. */
|
|
143
168
|
fromBaseImage(): TemplateBuilder;
|
|
144
|
-
|
|
169
|
+
/** Request a public container image base. The Watasu API fails closed until OCI image import is enabled. */
|
|
170
|
+
fromImage(baseImage: string, credentials?: {
|
|
145
171
|
username: string;
|
|
146
172
|
password: string;
|
|
147
173
|
}): TemplateBuilder;
|
|
148
|
-
|
|
174
|
+
/** Request an AWS registry image base. The Watasu API fails closed until registry image import is enabled. */
|
|
175
|
+
fromAWSRegistry(image: string, credentials: {
|
|
149
176
|
accessKeyId: string;
|
|
150
177
|
secretAccessKey: string;
|
|
151
178
|
region: string;
|
|
152
179
|
}): TemplateBuilder;
|
|
153
|
-
|
|
180
|
+
/** Request a GCP registry image base. The Watasu API fails closed until registry image import is enabled. */
|
|
181
|
+
fromGCPRegistry(image: string, credentials: {
|
|
154
182
|
serviceAccountJSON: object | string;
|
|
155
183
|
}): TemplateBuilder;
|
|
184
|
+
/** Start from a ready Watasu template slug, tag, or version id. */
|
|
156
185
|
fromTemplate(template: string): TemplateBuilder;
|
|
157
186
|
fromDockerfile(dockerfileContentOrPath: string): TemplateBuilder;
|
|
158
187
|
copy(src: string | string[], dest: string, options?: CopyOptions): TemplateBuilder;
|
package/dist/template.js
CHANGED
|
@@ -1,8 +1,45 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { ConnectionConfig } from './connectionConfig.js';
|
|
4
|
-
import { InvalidArgumentError, NotFoundError, SandboxError,
|
|
4
|
+
import { InvalidArgumentError, NotFoundError, SandboxError, TemplateError } from './errors.js';
|
|
5
5
|
import { ControlClient, withQuery } from './transport.js';
|
|
6
|
+
export class LogEntry {
|
|
7
|
+
timestamp;
|
|
8
|
+
level;
|
|
9
|
+
message;
|
|
10
|
+
constructor(timestamp = new Date(), level = 'info', message = '') {
|
|
11
|
+
this.timestamp = timestamp;
|
|
12
|
+
this.level = level;
|
|
13
|
+
this.message = message;
|
|
14
|
+
}
|
|
15
|
+
toString() {
|
|
16
|
+
return `[${this.timestamp.toISOString()}] ${this.level}: ${this.message}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class LogEntryStart extends LogEntry {
|
|
20
|
+
constructor(timestamp = new Date(), message = 'Build started') {
|
|
21
|
+
super(timestamp, 'info', message);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class LogEntryEnd extends LogEntry {
|
|
25
|
+
constructor(timestamp = new Date(), message = 'Build finished') {
|
|
26
|
+
super(timestamp, 'info', message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function defaultBuildLogger(options = {}) {
|
|
30
|
+
const order = { debug: 10, info: 20, warn: 30, error: 40 };
|
|
31
|
+
const minLevel = options.minLevel ?? 'info';
|
|
32
|
+
return (entry) => {
|
|
33
|
+
if (order[entry.level] < order[minLevel])
|
|
34
|
+
return;
|
|
35
|
+
if (entry.level === 'error')
|
|
36
|
+
console.error(entry.toString());
|
|
37
|
+
else if (entry.level === 'warn')
|
|
38
|
+
console.warn(entry.toString());
|
|
39
|
+
else
|
|
40
|
+
console.log(entry.toString());
|
|
41
|
+
};
|
|
42
|
+
}
|
|
6
43
|
/** Ready-check command wrapper accepted by template builders. */
|
|
7
44
|
export class ReadyCmd {
|
|
8
45
|
cmd;
|
|
@@ -38,6 +75,8 @@ export function waitForTimeout(timeout) {
|
|
|
38
75
|
/** Chainable template builder for Watasu package-spec template builds. */
|
|
39
76
|
export class TemplateBase {
|
|
40
77
|
base;
|
|
78
|
+
fromImageReference;
|
|
79
|
+
fromImageRegistry;
|
|
41
80
|
packages = {};
|
|
42
81
|
files = [];
|
|
43
82
|
setup = [];
|
|
@@ -55,10 +94,10 @@ export class TemplateBase {
|
|
|
55
94
|
}
|
|
56
95
|
static async build(template, nameOrOptions, options = {}) {
|
|
57
96
|
const { name, buildOptions } = normalizeBuildArguments(nameOrOptions, options);
|
|
58
|
-
buildOptions.onBuildLogs?.(
|
|
97
|
+
buildOptions.onBuildLogs?.(new LogEntryStart());
|
|
59
98
|
const data = await TemplateBase.buildInBackground(template, name, buildOptions);
|
|
60
99
|
await waitForBuildFinish(data, buildOptions);
|
|
61
|
-
buildOptions.onBuildLogs?.(
|
|
100
|
+
buildOptions.onBuildLogs?.(new LogEntryEnd());
|
|
62
101
|
return data;
|
|
63
102
|
}
|
|
64
103
|
static async buildInBackground(template, nameOrOptions, options = {}) {
|
|
@@ -133,42 +172,73 @@ export class TemplateBase {
|
|
|
133
172
|
static toDockerfile(template) {
|
|
134
173
|
return template.toDockerfile();
|
|
135
174
|
}
|
|
175
|
+
/** Request a Debian public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
136
176
|
fromDebianImage(_variant = 'stable') {
|
|
137
|
-
this.
|
|
138
|
-
return this;
|
|
177
|
+
return this.fromImage(`debian:${_variant}`);
|
|
139
178
|
}
|
|
179
|
+
/** Request an Ubuntu public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
140
180
|
fromUbuntuImage(_variant = 'latest') {
|
|
141
|
-
this.
|
|
142
|
-
return this;
|
|
181
|
+
return this.fromImage(`ubuntu:${_variant}`);
|
|
143
182
|
}
|
|
183
|
+
/** Request a Python public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
144
184
|
fromPythonImage(_version = '3') {
|
|
145
|
-
|
|
146
|
-
return this;
|
|
185
|
+
return this.fromImage(`python:${_version}`);
|
|
147
186
|
}
|
|
187
|
+
/** Request a Node.js public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
148
188
|
fromNodeImage(_variant = 'lts') {
|
|
149
|
-
|
|
150
|
-
return this;
|
|
189
|
+
return this.fromImage(`node:${_variant}`);
|
|
151
190
|
}
|
|
191
|
+
/** Request a Bun public base image. The Watasu API fails closed until OCI image import is enabled. */
|
|
152
192
|
fromBunImage(_variant = 'latest') {
|
|
153
|
-
|
|
154
|
-
return this;
|
|
193
|
+
return this.fromImage(`oven/bun:${_variant}`);
|
|
155
194
|
}
|
|
195
|
+
/** Start from the Watasu platform base template. */
|
|
156
196
|
fromBaseImage() {
|
|
157
|
-
this.
|
|
158
|
-
return this;
|
|
197
|
+
return this.fromTemplate('base');
|
|
159
198
|
}
|
|
160
|
-
|
|
161
|
-
|
|
199
|
+
/** Request a public container image base. The Watasu API fails closed until OCI image import is enabled. */
|
|
200
|
+
fromImage(baseImage, credentials) {
|
|
201
|
+
if (credentials && (!credentials.username || !credentials.password)) {
|
|
202
|
+
throw new InvalidArgumentError('Both username and password are required when providing registry credentials');
|
|
203
|
+
}
|
|
204
|
+
this.fromImageReference = baseImage;
|
|
205
|
+
this.base = undefined;
|
|
206
|
+
this.fromImageRegistry = credentials
|
|
207
|
+
? {
|
|
208
|
+
type: 'registry',
|
|
209
|
+
username: credentials.username,
|
|
210
|
+
password: credentials.password,
|
|
211
|
+
}
|
|
212
|
+
: undefined;
|
|
162
213
|
return this;
|
|
163
214
|
}
|
|
164
|
-
|
|
165
|
-
|
|
215
|
+
/** Request an AWS registry image base. The Watasu API fails closed until registry image import is enabled. */
|
|
216
|
+
fromAWSRegistry(image, credentials) {
|
|
217
|
+
this.fromImageReference = image;
|
|
218
|
+
this.base = undefined;
|
|
219
|
+
this.fromImageRegistry = {
|
|
220
|
+
type: 'aws',
|
|
221
|
+
aws_access_key_id: credentials.accessKeyId,
|
|
222
|
+
aws_secret_access_key: credentials.secretAccessKey,
|
|
223
|
+
aws_region: credentials.region,
|
|
224
|
+
};
|
|
225
|
+
return this;
|
|
166
226
|
}
|
|
167
|
-
|
|
168
|
-
|
|
227
|
+
/** Request a GCP registry image base. The Watasu API fails closed until registry image import is enabled. */
|
|
228
|
+
fromGCPRegistry(image, credentials) {
|
|
229
|
+
this.fromImageReference = image;
|
|
230
|
+
this.base = undefined;
|
|
231
|
+
this.fromImageRegistry = {
|
|
232
|
+
type: 'gcp',
|
|
233
|
+
service_account_json: credentials.serviceAccountJSON,
|
|
234
|
+
};
|
|
235
|
+
return this;
|
|
169
236
|
}
|
|
237
|
+
/** Start from a ready Watasu template slug, tag, or version id. */
|
|
170
238
|
fromTemplate(template) {
|
|
171
239
|
this.base = template;
|
|
240
|
+
this.fromImageReference = undefined;
|
|
241
|
+
this.fromImageRegistry = undefined;
|
|
172
242
|
return this;
|
|
173
243
|
}
|
|
174
244
|
fromDockerfile(dockerfileContentOrPath) {
|
|
@@ -303,7 +373,11 @@ export class TemplateBase {
|
|
|
303
373
|
toBuildSpec() {
|
|
304
374
|
const spec = {};
|
|
305
375
|
if (this.base)
|
|
306
|
-
spec.
|
|
376
|
+
spec.from_template = this.base;
|
|
377
|
+
if (this.fromImageReference)
|
|
378
|
+
spec.from_image = this.fromImageReference;
|
|
379
|
+
if (this.fromImageRegistry)
|
|
380
|
+
spec.from_image_registry = this.fromImageRegistry;
|
|
307
381
|
if (Object.keys(this.packages).length > 0)
|
|
308
382
|
spec.packages = this.packages;
|
|
309
383
|
if (this.files.length > 0)
|
|
@@ -379,7 +453,7 @@ export class TemplateBase {
|
|
|
379
453
|
: commandText;
|
|
380
454
|
}
|
|
381
455
|
toDockerfile() {
|
|
382
|
-
const lines = [
|
|
456
|
+
const lines = [`FROM ${this.fromImageReference ?? this.base ?? 'base'}`];
|
|
383
457
|
for (const packageName of this.packages.apt ?? [])
|
|
384
458
|
lines.push(`RUN apt-get update && apt-get install -y ${packageName}`);
|
|
385
459
|
for (const packageName of this.packages.pip ?? [])
|
|
@@ -553,7 +627,7 @@ async function waitForBuildFinish(data, options) {
|
|
|
553
627
|
if (status === 'ready')
|
|
554
628
|
return;
|
|
555
629
|
if (status === 'error')
|
|
556
|
-
throw new
|
|
630
|
+
throw new TemplateError(buildStatus.reason?.message ?? 'Template build failed');
|
|
557
631
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
558
632
|
}
|
|
559
633
|
}
|
|
@@ -600,11 +674,12 @@ function buildStatusReason(payload) {
|
|
|
600
674
|
}
|
|
601
675
|
function logEntry(payload) {
|
|
602
676
|
const timestamp = stringValue(payload.timestamp);
|
|
603
|
-
return
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
677
|
+
return new LogEntry(timestamp ? new Date(timestamp) : new Date(), logEntryLevel(stringValue(payload.level)), stringValue(payload.message) ?? '');
|
|
678
|
+
}
|
|
679
|
+
function logEntryLevel(value) {
|
|
680
|
+
if (value === 'debug' || value === 'info' || value === 'warn' || value === 'error')
|
|
681
|
+
return value;
|
|
682
|
+
return 'info';
|
|
608
683
|
}
|
|
609
684
|
function templateTag(payload) {
|
|
610
685
|
return {
|
package/dist/terminal.d.ts
CHANGED
package/dist/terminal.js
CHANGED
|
@@ -32,7 +32,10 @@ export class Terminal {
|
|
|
32
32
|
return this.waitPromise;
|
|
33
33
|
}
|
|
34
34
|
async waitOnce() {
|
|
35
|
-
await this.handle.wait().
|
|
35
|
+
await this.handle.wait().then((result) => {
|
|
36
|
+
if (this.output.data.length === 0 && result.stdout)
|
|
37
|
+
this.output.addData(result.stdout);
|
|
38
|
+
}).catch((error) => {
|
|
36
39
|
if (typeof error?.stdout === 'string')
|
|
37
40
|
this.output.addData(error.stdout);
|
|
38
41
|
else
|
|
@@ -62,6 +65,7 @@ export class TerminalManager {
|
|
|
62
65
|
envs: opts.envs,
|
|
63
66
|
size: opts.size,
|
|
64
67
|
timeoutMs: opts.timeoutMs,
|
|
68
|
+
requestTimeoutMs: opts.requestTimeoutMs,
|
|
65
69
|
onData: async (bytes) => {
|
|
66
70
|
const data = new TextDecoder().decode(bytes);
|
|
67
71
|
output.addData(data);
|
package/dist/volume.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Blob } from 'node:buffer';
|
|
2
2
|
import { ConnectionConfig, type ConnectionOpts } from './connectionConfig.js';
|
|
3
3
|
import { ControlClient } from './transport.js';
|
|
4
|
-
export
|
|
4
|
+
export declare enum VolumeFileType {
|
|
5
|
+
UNKNOWN = "unknown",
|
|
6
|
+
FILE = "file",
|
|
7
|
+
DIRECTORY = "directory",
|
|
8
|
+
SYMLINK = "symlink"
|
|
9
|
+
}
|
|
5
10
|
export type VolumeReadFormat = 'text' | 'bytes' | 'blob' | 'stream';
|
|
6
11
|
export type VolumeWriteData = string | Uint8Array | ArrayBuffer | Blob;
|
|
7
12
|
/** Control-plane metadata for a persistent Watasu volume. */
|
|
@@ -23,7 +28,7 @@ export interface VolumeInfo {
|
|
|
23
28
|
export interface VolumeEntryStat {
|
|
24
29
|
path: string;
|
|
25
30
|
name: string;
|
|
26
|
-
type: VolumeFileType;
|
|
31
|
+
type: VolumeFileType | string;
|
|
27
32
|
size?: number;
|
|
28
33
|
mode?: number;
|
|
29
34
|
uid?: number;
|
|
@@ -36,8 +41,8 @@ export interface VolumeEntryStat {
|
|
|
36
41
|
export interface VolumeApiParams extends ConnectionOpts {
|
|
37
42
|
team?: string;
|
|
38
43
|
}
|
|
39
|
-
export
|
|
40
|
-
|
|
44
|
+
export type VolumeConnectionConfig = ConnectionOpts;
|
|
45
|
+
export declare const VolumeConnectionConfig: typeof ConnectionConfig;
|
|
41
46
|
export interface VolumeListOpts extends ConnectionOpts {
|
|
42
47
|
team?: string;
|
|
43
48
|
}
|
|
@@ -58,6 +63,12 @@ export interface VolumeMetadataOpts extends ConnectionOpts {
|
|
|
58
63
|
gid?: number;
|
|
59
64
|
mode?: number | string;
|
|
60
65
|
}
|
|
66
|
+
export type VolumeAndToken = VolumeInfo & {
|
|
67
|
+
token: string;
|
|
68
|
+
};
|
|
69
|
+
export type VolumeApiOpts = ConnectionOpts;
|
|
70
|
+
export type VolumeMetadataOptions = Omit<VolumeMetadataOpts, keyof ConnectionOpts>;
|
|
71
|
+
export type VolumeWriteOptions = Omit<VolumeWriteFileOpts, keyof ConnectionOpts>;
|
|
61
72
|
/** Persistent volume that can be mounted into sandboxes and edited while detached. */
|
|
62
73
|
export declare class Volume {
|
|
63
74
|
readonly volumeId: string;
|
package/dist/volume.js
CHANGED
|
@@ -3,6 +3,14 @@ import { ConnectionConfig } from './connectionConfig.js';
|
|
|
3
3
|
import { NotFoundError, SandboxError } from './errors.js';
|
|
4
4
|
import { base64DecodeBytes, base64DecodeText, base64Encode } from './processSocket.js';
|
|
5
5
|
import { ControlClient, withQuery } from './transport.js';
|
|
6
|
+
export var VolumeFileType;
|
|
7
|
+
(function (VolumeFileType) {
|
|
8
|
+
VolumeFileType["UNKNOWN"] = "unknown";
|
|
9
|
+
VolumeFileType["FILE"] = "file";
|
|
10
|
+
VolumeFileType["DIRECTORY"] = "directory";
|
|
11
|
+
VolumeFileType["SYMLINK"] = "symlink";
|
|
12
|
+
})(VolumeFileType || (VolumeFileType = {}));
|
|
13
|
+
export const VolumeConnectionConfig = ConnectionConfig;
|
|
6
14
|
/** Persistent volume that can be mounted into sandboxes and edited while detached. */
|
|
7
15
|
export class Volume {
|
|
8
16
|
volumeId;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@watasu/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT OR Apache-2.0",
|
|
6
6
|
"description": "TypeScript SDK for Watasu",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc -p tsconfig.json",
|
|
26
|
-
"test": "npm run build && node --test test/*.mjs"
|
|
26
|
+
"test": "npm run build && tsc -p tsconfig.test.json && node --test test/*.mjs"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"ws": "^8.18.3"
|