@freestyle-sh/with-bun 0.2.0 → 0.2.2

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 CHANGED
@@ -57,6 +57,40 @@ type RunCodeResponse<Result> = {
57
57
  };
58
58
  ```
59
59
 
60
+ ### `vm.js.install(options?)`
61
+
62
+ Installs npm packages using Bun.
63
+
64
+ ```typescript
65
+ // Install from package.json in current directory
66
+ await vm.js.install();
67
+
68
+ // Install from package.json in specific directory
69
+ await vm.js.install({ directory: "/app" });
70
+
71
+ // Install specific packages
72
+ await vm.js.install({ deps: ["lodash", "express"] });
73
+
74
+ // Install with specific versions
75
+ await vm.js.install({ deps: { "lodash": "^4.0.0", "express": "~5.0.0" } });
76
+
77
+ // Install as dev dependencies
78
+ await vm.js.install({ deps: ["typescript"], dev: true });
79
+
80
+ // Install globally
81
+ await vm.js.install({ global: true, deps: ["typescript"] });
82
+ ```
83
+
84
+ **Returns:** `Promise<InstallResult>`
85
+
86
+ ```typescript
87
+ type InstallResult = {
88
+ success: boolean;
89
+ stdout?: string;
90
+ stderr?: string;
91
+ };
92
+ ```
93
+
60
94
  ## Documentation
61
95
 
62
96
  - [Freestyle Documentation](https://docs.freestyle.sh)
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { VmWith, VmWithInstance, CreateVmOptions } from 'freestyle-sandboxes';
2
- import { VmJavaScriptRuntimeInstance, JSONValue, RunCodeResponse, VmJavaScriptRuntime } from '@freestyle-sh/with-type-js';
1
+ import { VmWith, VmWithInstance, VmSpec } from 'freestyle-sandboxes';
2
+ import { VmJavaScriptRuntimeInstance, JSONValue, RunCodeResponse, InstallOptions, InstallResult, VmJavaScriptRuntime } from '@freestyle-sh/with-type-js';
3
3
 
4
4
  type BunJsOptions = {
5
5
  version?: string;
@@ -12,16 +12,20 @@ type BunJsResolvedOptions = {
12
12
  declare class VmBun extends VmWith<VmBunInstance> implements VmJavaScriptRuntime<VmJavaScriptRuntimeInstance> {
13
13
  options: BunJsResolvedOptions;
14
14
  constructor(options?: BunJsOptions);
15
- configure(existingConfig: CreateVmOptions): CreateVmOptions | Promise<CreateVmOptions>;
15
+ configureSnapshotSpec(spec: VmSpec): VmSpec;
16
16
  createInstance(): VmBunInstance;
17
17
  installServiceName(): string;
18
18
  }
19
19
  declare class VmBunInstance extends VmWithInstance implements VmJavaScriptRuntimeInstance {
20
20
  builder: VmBun;
21
21
  constructor(builder: VmBun);
22
- runCode<Result extends JSONValue = any>({ code, }: {
22
+ runCode<Result extends JSONValue = any>(args: string | {
23
23
  code: string;
24
+ argv?: string[];
25
+ env?: Record<string, string>;
26
+ workdir?: string;
24
27
  }): Promise<RunCodeResponse<Result>>;
28
+ install(options?: InstallOptions): Promise<InstallResult>;
25
29
  }
26
30
 
27
31
  export { VmBun };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { VmWith, VmTemplate, VmWithInstance } from 'freestyle-sandboxes';
1
+ import { VmWith, VmSpec, VmWithInstance } from 'freestyle-sandboxes';
2
2
 
3
3
  class VmBun extends VmWith {
4
4
  options;
@@ -9,7 +9,7 @@ class VmBun extends VmWith {
9
9
  workdir: options?.workdir
10
10
  };
11
11
  }
12
- configure(existingConfig) {
12
+ configureSnapshotSpec(spec) {
13
13
  const versionArg = this.options.version ? ` -s "bun-v${this.options.version}"` : "";
14
14
  const installScript = `#!/bin/bash
15
15
  set -e
@@ -20,8 +20,9 @@ $BUN_INSTALL/bin/bun --version
20
20
  const bunInit = `export BUN_INSTALL="/opt/bun"
21
21
  export PATH="$BUN_INSTALL/bin:$PATH"
22
22
  `;
23
- const bunConfig = {
24
- template: new VmTemplate({
23
+ return this.composeSpecs(
24
+ spec,
25
+ new VmSpec({
25
26
  additionalFiles: {
26
27
  "/opt/install-bun.sh": {
27
28
  content: installScript
@@ -42,8 +43,7 @@ export PATH="$BUN_INSTALL/bin:$PATH"
42
43
  ]
43
44
  }
44
45
  })
45
- };
46
- return this.compose(existingConfig, bunConfig);
46
+ );
47
47
  }
48
48
  createInstance() {
49
49
  return new VmBunInstance(this);
@@ -58,17 +58,26 @@ class VmBunInstance extends VmWithInstance {
58
58
  super();
59
59
  this.builder = builder;
60
60
  }
61
- async runCode({
62
- code
63
- }) {
61
+ async runCode(args) {
62
+ const options = typeof args === "string" ? { code: args } : args;
63
+ const { code, argv, env, workdir } = options;
64
+ const shellEscape = (value) => `'${value.replace(/'/g, "'\\''")}'`;
65
+ const argvArgs = argv?.map(shellEscape).join(" ");
66
+ const envPrefix = env ? `${Object.entries(env).map(([key, value]) => `${key}=${shellEscape(value)}`).join(" ")} ` : "";
67
+ const cdPrefix = workdir ? `cd ${shellEscape(workdir)} && ` : "";
68
+ const command = `${cdPrefix}${envPrefix}/opt/bun/bin/bun -e "${code.replace(/"/g, '\\"')}"${argvArgs ? ` -- ${argvArgs}` : ""}`;
64
69
  const result = await this.vm.exec({
65
- command: `/opt/bun/bin/bun -e "${code.replace(/"/g, '\\"')}"`
70
+ command
66
71
  });
67
72
  let parsedResult = void 0;
68
73
  if (result.stdout) {
69
- try {
70
- parsedResult = JSON.parse(result.stdout);
71
- } catch (e) {
74
+ const lines = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
75
+ const lastLine = lines[lines.length - 1];
76
+ if (lastLine) {
77
+ try {
78
+ parsedResult = JSON.parse(lastLine);
79
+ } catch (e) {
80
+ }
72
81
  }
73
82
  }
74
83
  return {
@@ -78,6 +87,27 @@ class VmBunInstance extends VmWithInstance {
78
87
  statusCode: result.statusCode ?? -1
79
88
  };
80
89
  }
90
+ async install(options) {
91
+ let command;
92
+ if (options?.global) {
93
+ command = `/opt/bun/bin/bun add -g ${options.deps.join(" ")}`;
94
+ } else {
95
+ const cdPrefix = options?.directory ? `cd ${options.directory} && ` : "";
96
+ if (!options?.deps) {
97
+ command = `${cdPrefix}/opt/bun/bin/bun install`;
98
+ } else {
99
+ const deps = Array.isArray(options.deps) ? options.deps : Object.entries(options.deps).map(([pkg, ver]) => `${pkg}@${ver}`);
100
+ const devFlag = options.dev ? " -d" : "";
101
+ command = `${cdPrefix}/opt/bun/bin/bun add${devFlag} ${deps.join(" ")}`;
102
+ }
103
+ }
104
+ const result = await this.vm.exec({ command });
105
+ return {
106
+ success: result.statusCode === 0,
107
+ stdout: result.stdout ?? void 0,
108
+ stderr: result.stderr ?? void 0
109
+ };
110
+ }
81
111
  }
82
112
 
83
113
  export { VmBun };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@freestyle-sh/with-bun",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "private": false,
5
5
  "dependencies": {
6
- "freestyle-sandboxes": "^0.1.2",
7
- "@freestyle-sh/with-type-js": "^0.2.0"
6
+ "freestyle-sandboxes": "^0.1.8",
7
+ "@freestyle-sh/with-type-js": "^0.2.2"
8
8
  },
9
9
  "type": "module",
10
10
  "main": "./dist/index.js",