@axiom-lattice/microsandbox-service 0.0.1
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/.turbo/turbo-build.log +29 -0
- package/CHANGELOG.md +7 -0
- package/LICENSE +201 -0
- package/dist/chunk-2W4CTYPX.mjs +464 -0
- package/dist/chunk-2W4CTYPX.mjs.map +1 -0
- package/dist/index.d.mts +208 -0
- package/dist/index.d.ts +208 -0
- package/dist/index.js +496 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.d.mts +9 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +566 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +82 -0
- package/dist/server.mjs.map +1 -0
- package/jest.config.js +17 -0
- package/package.json +46 -0
- package/src/__tests__/MicrosandboxRuntimeService.test.ts +251 -0
- package/src/__tests__/SandboxRegistry.test.ts +101 -0
- package/src/__tests__/app.test.ts +224 -0
- package/src/__tests__/index.test.ts +33 -0
- package/src/__tests__/server-cli.test.ts +26 -0
- package/src/__tests__/server.test.ts +25 -0
- package/src/app.ts +31 -0
- package/src/controllers/sandbox.ts +138 -0
- package/src/index.ts +3 -0
- package/src/lib/errors.ts +44 -0
- package/src/lib/http.ts +11 -0
- package/src/lib/server-cli.ts +59 -0
- package/src/routes/health.ts +6 -0
- package/src/routes/sandbox.ts +28 -0
- package/src/schemas/sandbox.ts +79 -0
- package/src/server.ts +43 -0
- package/src/services/MicrosandboxRuntimeService.ts +247 -0
- package/src/services/SandboxRegistry.ts +69 -0
- package/src/types/runtime-service.ts +23 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
|
|
3
|
+
const bindMountSchema = z.object({
|
|
4
|
+
type: z.literal("bind"),
|
|
5
|
+
source: z.string().min(1),
|
|
6
|
+
readonly: z.boolean().optional(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const namedMountSchema = z.object({
|
|
10
|
+
type: z.literal("named"),
|
|
11
|
+
name: z.string().min(1),
|
|
12
|
+
readonly: z.boolean().optional(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const tmpfsMountSchema = z.object({
|
|
16
|
+
type: z.literal("tmpfs"),
|
|
17
|
+
sizeMib: z.number().int().positive().optional(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const volumeSchema = z.union([
|
|
21
|
+
bindMountSchema,
|
|
22
|
+
namedMountSchema,
|
|
23
|
+
tmpfsMountSchema,
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export const ensureSandboxSchema = z.object({
|
|
27
|
+
image: z.string().optional(),
|
|
28
|
+
cpus: z.number().int().positive().optional(),
|
|
29
|
+
memoryMib: z.number().int().positive().optional(),
|
|
30
|
+
env: z.record(z.string()).optional(),
|
|
31
|
+
volumes: z.record(volumeSchema).optional(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const sandboxAndPathSchema = z.object({
|
|
35
|
+
sandboxName: z.string().min(1),
|
|
36
|
+
path: z.string().min(1),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const readFileSchema = sandboxAndPathSchema;
|
|
40
|
+
|
|
41
|
+
export const writeFileSchema = sandboxAndPathSchema.extend({
|
|
42
|
+
content: z.string(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const listPathSchema = sandboxAndPathSchema.extend({
|
|
46
|
+
recursive: z.boolean().optional(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const findFilesSchema = sandboxAndPathSchema.extend({
|
|
50
|
+
pattern: z.string().min(1),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const searchInFileSchema = sandboxAndPathSchema.extend({
|
|
54
|
+
query: z.string().min(1),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const replaceInFileSchema = sandboxAndPathSchema.extend({
|
|
58
|
+
search: z.string(),
|
|
59
|
+
replace: z.string(),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const uploadFileSchema = sandboxAndPathSchema.and(
|
|
63
|
+
z.union([
|
|
64
|
+
z.object({ contentBase64: z.string() }),
|
|
65
|
+
z.object({ content: z.string().transform((content) => Buffer.from(content).toString("base64")) }),
|
|
66
|
+
])
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
export const downloadFileSchema = sandboxAndPathSchema;
|
|
70
|
+
|
|
71
|
+
export const shellExecSchema = z.object({
|
|
72
|
+
sandboxName: z.string().min(1),
|
|
73
|
+
command: z.string().min(1),
|
|
74
|
+
exec_dir: z.string().optional(),
|
|
75
|
+
timeout: z.number().int().positive().optional(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;
|
|
79
|
+
export type ShellExecInput = z.infer<typeof shellExecSchema>;
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import { buildApp } from "./app";
|
|
3
|
+
import { parseServerArgs, resolveServerConfig } from "./lib/server-cli";
|
|
4
|
+
|
|
5
|
+
export async function startServer({
|
|
6
|
+
argv = process.argv.slice(2),
|
|
7
|
+
env = process.env,
|
|
8
|
+
app = buildApp(),
|
|
9
|
+
}: {
|
|
10
|
+
argv?: string[];
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
app?: Pick<FastifyInstance, "listen" | "close">;
|
|
13
|
+
} = {}): Promise<Pick<FastifyInstance, "listen" | "close">> {
|
|
14
|
+
const config = resolveServerConfig({ args: parseServerArgs(argv), env });
|
|
15
|
+
|
|
16
|
+
const shutdown = async (code: number): Promise<void> => {
|
|
17
|
+
try {
|
|
18
|
+
await app.close();
|
|
19
|
+
process.exit(code);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error("Failed to shutdown microsandbox-service cleanly", error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
process.once("SIGINT", () => {
|
|
27
|
+
void shutdown(0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
process.once("SIGTERM", () => {
|
|
31
|
+
void shutdown(0);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await app.listen({ port: config.port, host: config.host });
|
|
35
|
+
return app;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (require.main === module) {
|
|
39
|
+
void startServer().catch((error) => {
|
|
40
|
+
console.error("Failed to start microsandbox-service", error);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { Mount, Sandbox } from "microsandbox";
|
|
2
|
+
import type { EnsureSandboxInput, ShellExecInput } from "../schemas/sandbox";
|
|
3
|
+
import { SandboxRegistry } from "./SandboxRegistry";
|
|
4
|
+
|
|
5
|
+
type VolumeConfig = NonNullable<EnsureSandboxInput["volumes"]>[string];
|
|
6
|
+
|
|
7
|
+
type RuntimeNative = {
|
|
8
|
+
fs(): {
|
|
9
|
+
readString(path: string): Promise<string>;
|
|
10
|
+
write(path: string, data: Buffer): Promise<void>;
|
|
11
|
+
list(
|
|
12
|
+
path: string,
|
|
13
|
+
options?: { recursive?: boolean }
|
|
14
|
+
): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;
|
|
15
|
+
read(path: string): Promise<Buffer | Uint8Array | string>;
|
|
16
|
+
};
|
|
17
|
+
execWithConfig(config: {
|
|
18
|
+
cmd: string;
|
|
19
|
+
args?: string[];
|
|
20
|
+
cwd?: string;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
stdout(): string;
|
|
24
|
+
stderr?(): string;
|
|
25
|
+
code?: number;
|
|
26
|
+
}>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
kill(): Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export class MicrosandboxRuntimeService {
|
|
32
|
+
constructor(private deps: { registry?: SandboxRegistry } = {}) {}
|
|
33
|
+
|
|
34
|
+
private get registry(): SandboxRegistry {
|
|
35
|
+
return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private buildVolumes(volumes?: EnsureSandboxInput["volumes"]): Record<string, unknown> | undefined {
|
|
39
|
+
if (!volumes) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Object.fromEntries(
|
|
44
|
+
Object.entries(volumes).map(([mountPath, definition]) => [mountPath, this.buildVolume(definition)])
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private buildVolume(definition: VolumeConfig): unknown {
|
|
49
|
+
if (definition.type === "bind") {
|
|
50
|
+
return Mount.bind(definition.source, { readonly: definition.readonly ?? false });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (definition.type === "named") {
|
|
54
|
+
return Mount.named(definition.name, { readonly: definition.readonly ?? false });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return Mount.tmpfs({ sizeMib: definition.sizeMib });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private getNative(name: string): RuntimeNative {
|
|
61
|
+
return this.registry.get(name) as RuntimeNative;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private async getOrEnsureNative(name: string): Promise<RuntimeNative> {
|
|
65
|
+
try {
|
|
66
|
+
return this.getNative(name);
|
|
67
|
+
} catch {
|
|
68
|
+
return (await this.registry.ensure(name)) as RuntimeNative;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async ensureSandbox(name: string, input: EnsureSandboxInput): Promise<{
|
|
73
|
+
name: string;
|
|
74
|
+
status: string;
|
|
75
|
+
}> {
|
|
76
|
+
await this.registry.ensure(name, {
|
|
77
|
+
image: input.image ?? process.env.MICROSANDBOX_IMAGE ?? "python:3.11-slim",
|
|
78
|
+
cpus: input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? "1"),
|
|
79
|
+
memoryMib: input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? "512"),
|
|
80
|
+
env: input.env,
|
|
81
|
+
volumes: this.buildVolumes(input.volumes),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
name,
|
|
86
|
+
status: "running",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async startSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
91
|
+
await Sandbox.start(name);
|
|
92
|
+
this.registry.delete(name);
|
|
93
|
+
await this.registry.ensure(name);
|
|
94
|
+
return { name, status: "running" };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async stopSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
98
|
+
const native = await this.getOrEnsureNative(name);
|
|
99
|
+
await native.stop();
|
|
100
|
+
this.registry.delete(name);
|
|
101
|
+
return { name, status: "stopped" };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async killSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
105
|
+
const native = await this.getOrEnsureNative(name);
|
|
106
|
+
await native.kill();
|
|
107
|
+
this.registry.delete(name);
|
|
108
|
+
return { name, status: "unknown" };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async deleteSandbox(name: string): Promise<{ name: string; status: string }> {
|
|
112
|
+
try {
|
|
113
|
+
await this.getNative(name).kill();
|
|
114
|
+
} catch {
|
|
115
|
+
// Ignore missing cached native handle before remove.
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await Sandbox.remove(name);
|
|
119
|
+
this.registry.delete(name);
|
|
120
|
+
|
|
121
|
+
return { name, status: "unknown" };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async getStatus(name: string): Promise<{ name: string; status: string }> {
|
|
125
|
+
try {
|
|
126
|
+
this.getNative(name);
|
|
127
|
+
return { name, status: "running" };
|
|
128
|
+
} catch {
|
|
129
|
+
return { name, status: "unknown" };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {
|
|
134
|
+
const content = await this.getNative(sandboxName).fs().readString(path);
|
|
135
|
+
return { path, content };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {
|
|
139
|
+
await this.getNative(sandboxName).fs().write(path, Buffer.from(content));
|
|
140
|
+
return { path };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async listPath(
|
|
144
|
+
sandboxName: string,
|
|
145
|
+
path: string,
|
|
146
|
+
recursive?: boolean
|
|
147
|
+
): Promise<{ entries: Array<{ path: string; type: string }> }> {
|
|
148
|
+
const entries = await this.getNative(sandboxName).fs().list(path, { recursive });
|
|
149
|
+
return {
|
|
150
|
+
entries: entries.map((entry) => ({
|
|
151
|
+
path: entry.path,
|
|
152
|
+
type: entry.kind,
|
|
153
|
+
})),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {
|
|
158
|
+
const output = await this.getNative(sandboxName).execWithConfig({
|
|
159
|
+
cmd: "sh",
|
|
160
|
+
args: ["-c", `find "${path}" -name "${pattern}" -type f`],
|
|
161
|
+
});
|
|
162
|
+
return { files: output.stdout().split("\n").filter(Boolean) };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async searchInFile(
|
|
166
|
+
sandboxName: string,
|
|
167
|
+
path: string,
|
|
168
|
+
query: string
|
|
169
|
+
): Promise<{ matches: Array<{ line: number; content: string }> }> {
|
|
170
|
+
let stdout: string;
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const output = await this.getNative(sandboxName).execWithConfig({
|
|
174
|
+
cmd: "grep",
|
|
175
|
+
args: ["-n", "-E", query, path],
|
|
176
|
+
});
|
|
177
|
+
stdout = output.stdout();
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === 1) {
|
|
180
|
+
return { matches: [] };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
matches: stdout
|
|
188
|
+
.split("\n")
|
|
189
|
+
.filter(Boolean)
|
|
190
|
+
.map((line) => {
|
|
191
|
+
const separator = line.indexOf(":");
|
|
192
|
+
return {
|
|
193
|
+
line: Number(line.slice(0, separator)),
|
|
194
|
+
content: line.slice(separator + 1),
|
|
195
|
+
};
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async replaceInFile(
|
|
201
|
+
sandboxName: string,
|
|
202
|
+
input: { path: string; search: string; replace: string }
|
|
203
|
+
): Promise<{ replaced: number }> {
|
|
204
|
+
const fs = this.getNative(sandboxName).fs();
|
|
205
|
+
const original = await fs.readString(input.path);
|
|
206
|
+
|
|
207
|
+
if (!input.search) {
|
|
208
|
+
return { replaced: 0 };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const occurrences = original.split(input.search).length - 1;
|
|
212
|
+
if (occurrences === 0) {
|
|
213
|
+
return { replaced: 0 };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const updated = original.split(input.search).join(input.replace);
|
|
217
|
+
await fs.write(input.path, Buffer.from(updated));
|
|
218
|
+
|
|
219
|
+
return { replaced: occurrences };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {
|
|
223
|
+
await this.getNative(sandboxName).fs().write(path, Buffer.from(contentBase64, "base64"));
|
|
224
|
+
return { path };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {
|
|
228
|
+
const data = await this.getNative(sandboxName).fs().read(path);
|
|
229
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
230
|
+
return { path, contentBase64: buffer.toString("base64") };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {
|
|
234
|
+
const output = await this.getNative(input.sandboxName).execWithConfig({
|
|
235
|
+
cmd: "sh",
|
|
236
|
+
args: ["-c", input.command],
|
|
237
|
+
cwd: input.exec_dir,
|
|
238
|
+
timeoutMs: input.timeout ? input.timeout * 1000 : undefined,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
stdout: output.stdout(),
|
|
243
|
+
stderr: output.stderr ? output.stderr() : "",
|
|
244
|
+
exitCode: output.code ?? 0,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Sandbox } from "microsandbox";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0";
|
|
4
|
+
|
|
5
|
+
export class SandboxRegistry {
|
|
6
|
+
private handles = new Map<string, unknown>();
|
|
7
|
+
private creating = new Map<string, Promise<unknown>>();
|
|
8
|
+
|
|
9
|
+
async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {
|
|
10
|
+
const cached = this.handles.get(name);
|
|
11
|
+
if (cached) {
|
|
12
|
+
return cached;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const inflight = this.creating.get(name);
|
|
16
|
+
if (inflight) {
|
|
17
|
+
return inflight;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const creation = (async () => {
|
|
21
|
+
let native: unknown;
|
|
22
|
+
const createConfig = {
|
|
23
|
+
name,
|
|
24
|
+
image: DEFAULT_IMAGE,
|
|
25
|
+
...(createOptions ?? {}),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const handle = await Sandbox.get(name);
|
|
30
|
+
|
|
31
|
+
if (handle.status === "running") {
|
|
32
|
+
native = await handle.connect();
|
|
33
|
+
} else if (handle.status === "stopped") {
|
|
34
|
+
native = await Sandbox.start(name);
|
|
35
|
+
} else if (handle.status === "crashed" || handle.status === "draining") {
|
|
36
|
+
await Sandbox.remove(name);
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
native = undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!native) {
|
|
43
|
+
native = await Sandbox.createDetached(createConfig);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.handles.set(name, native);
|
|
47
|
+
return native;
|
|
48
|
+
})();
|
|
49
|
+
|
|
50
|
+
this.creating.set(name, creation);
|
|
51
|
+
void creation.finally(() => this.creating.delete(name));
|
|
52
|
+
|
|
53
|
+
return creation;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get(name: string): unknown {
|
|
57
|
+
const handle = this.handles.get(name);
|
|
58
|
+
|
|
59
|
+
if (!handle) {
|
|
60
|
+
throw new Error(`Sandbox ${name} not found`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return handle;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
delete(name: string): void {
|
|
67
|
+
this.handles.delete(name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EnsureSandboxInput } from "../schemas/sandbox";
|
|
2
|
+
import type { ShellExecInput } from "../schemas/sandbox";
|
|
3
|
+
|
|
4
|
+
export interface RuntimeService {
|
|
5
|
+
ensureSandbox(name: string, input: EnsureSandboxInput): Promise<unknown>;
|
|
6
|
+
startSandbox(name: string): Promise<unknown>;
|
|
7
|
+
stopSandbox(name: string): Promise<unknown>;
|
|
8
|
+
killSandbox(name: string): Promise<unknown>;
|
|
9
|
+
deleteSandbox(name: string): Promise<unknown>;
|
|
10
|
+
getStatus(name: string): Promise<unknown>;
|
|
11
|
+
readFile(sandboxName: string, path: string): Promise<unknown>;
|
|
12
|
+
writeFile(sandboxName: string, path: string, content: string): Promise<unknown>;
|
|
13
|
+
listPath(sandboxName: string, path: string, recursive?: boolean): Promise<unknown>;
|
|
14
|
+
findFiles(sandboxName: string, path: string, pattern: string): Promise<unknown>;
|
|
15
|
+
searchInFile(sandboxName: string, path: string, query: string): Promise<unknown>;
|
|
16
|
+
replaceInFile(
|
|
17
|
+
sandboxName: string,
|
|
18
|
+
input: { path: string; search: string; replace: string }
|
|
19
|
+
): Promise<unknown>;
|
|
20
|
+
uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<unknown>;
|
|
21
|
+
downloadFile(sandboxName: string, path: string): Promise<unknown>;
|
|
22
|
+
execCommand(input: ShellExecInput): Promise<unknown>;
|
|
23
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "preserve",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"moduleResolution": "Bundler",
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"declarationMap": true,
|
|
16
|
+
"types": ["node", "jest"],
|
|
17
|
+
"sourceMap": true,
|
|
18
|
+
"isolatedModules": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*.ts"],
|
|
21
|
+
"exclude": ["node_modules", "dist"]
|
|
22
|
+
}
|