@freestyle-sh/with-nodejs 0.2.7 → 0.2.9
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 +77 -0
- package/dist/index.d.ts +45 -1
- package/dist/index.js +132 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -91,6 +91,83 @@ type InstallResult = {
|
|
|
91
91
|
};
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
## Workspaces and Tasks
|
|
95
|
+
|
|
96
|
+
Use the Node.js builder to attach a workspace and run an npm script as a managed systemd service.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { freestyle, VmSpec } from "freestyle-sandboxes";
|
|
100
|
+
import { VmNodeJs } from "@freestyle-sh/with-nodejs";
|
|
101
|
+
|
|
102
|
+
const SOURCE_REPO = "https://github.com/freestyle-sh/freestyle-next";
|
|
103
|
+
|
|
104
|
+
const node = new VmNodeJs();
|
|
105
|
+
const workspace = node.workspace({ path: "/root/app", install: true });
|
|
106
|
+
const appTask = workspace.task("dev", {
|
|
107
|
+
env: {
|
|
108
|
+
HOST: "0.0.0.0",
|
|
109
|
+
PORT: "3000",
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const spec = new VmSpec()
|
|
114
|
+
.with("node", node)
|
|
115
|
+
.repo(SOURCE_REPO, "/root/app")
|
|
116
|
+
.with("workspace", workspace)
|
|
117
|
+
.with("app", appTask)
|
|
118
|
+
.snapshot()
|
|
119
|
+
.waitFor("curl http://localhost:3000")
|
|
120
|
+
.snapshot();
|
|
121
|
+
|
|
122
|
+
const { repoId } = await freestyle.git.repos.create({
|
|
123
|
+
source: {
|
|
124
|
+
url: SOURCE_REPO,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const domain = `${repoId}.style.dev`;
|
|
129
|
+
|
|
130
|
+
const { vm } = await freestyle.vms.create({
|
|
131
|
+
spec,
|
|
132
|
+
domains: [{ domain, vmPort: 3000 }],
|
|
133
|
+
git: {
|
|
134
|
+
repos: [{ repo: repoId, path: "/root/app" }],
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(await vm.app.logs());
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Workspace API
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const workspace = node.workspace({
|
|
145
|
+
path: "/root/app",
|
|
146
|
+
install: true,
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- `path`: Working directory for `npm install` and task execution.
|
|
151
|
+
- `install`: When true, runs `npm install` in the workspace during VM startup.
|
|
152
|
+
|
|
153
|
+
### Task API
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const task = workspace.task("dev", {
|
|
157
|
+
env: {
|
|
158
|
+
HOST: "0.0.0.0",
|
|
159
|
+
PORT: "3000",
|
|
160
|
+
},
|
|
161
|
+
serviceName: "my-node-app",
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
- `name`: Script name from `package.json`.
|
|
166
|
+
- `env`: Optional environment variables for the task service.
|
|
167
|
+
- `serviceName`: Optional explicit systemd service name.
|
|
168
|
+
|
|
169
|
+
When added to the spec with `.with("app", task)`, you can access task logs with `vm.app.logs()`.
|
|
170
|
+
|
|
94
171
|
## Documentation
|
|
95
172
|
|
|
96
173
|
- [Freestyle Documentation](https://docs.freestyle.sh)
|
package/dist/index.d.ts
CHANGED
|
@@ -11,11 +11,55 @@ type NodeJsResolvedOptions = {
|
|
|
11
11
|
};
|
|
12
12
|
declare class VmNodeJs extends VmWith<NodeJsRuntimeInstance> implements VmJavaScriptRuntime<VmJavaScriptRuntimeInstance> {
|
|
13
13
|
options: NodeJsResolvedOptions;
|
|
14
|
+
workspaces: NodeJsWorkspace[];
|
|
14
15
|
constructor(options?: NodeJsOptions);
|
|
15
16
|
configureSnapshotSpec(spec: VmSpec): VmSpec;
|
|
16
17
|
createInstance(): NodeJsRuntimeInstance;
|
|
18
|
+
workspace(options: {
|
|
19
|
+
path: string;
|
|
20
|
+
install?: boolean;
|
|
21
|
+
}): NodeJsWorkspace;
|
|
17
22
|
installServiceName(): string;
|
|
18
23
|
}
|
|
24
|
+
declare class NodeJsWorkspace extends VmWith<NodeJsWorkspaceInstance> {
|
|
25
|
+
options: {
|
|
26
|
+
path: string;
|
|
27
|
+
install?: boolean;
|
|
28
|
+
};
|
|
29
|
+
env?: Record<string, string>;
|
|
30
|
+
constructor(options: {
|
|
31
|
+
path: string;
|
|
32
|
+
install?: boolean;
|
|
33
|
+
}, env?: Record<string, string>);
|
|
34
|
+
task(name: string, options?: {
|
|
35
|
+
env?: Record<string, string>;
|
|
36
|
+
serviceName?: string;
|
|
37
|
+
}): NodeJsWorkspaceTask;
|
|
38
|
+
getInstallServiceName(): string;
|
|
39
|
+
configureSpec(spec: VmSpec): VmSpec;
|
|
40
|
+
createInstance(): NodeJsWorkspaceInstance;
|
|
41
|
+
}
|
|
42
|
+
declare class NodeJsWorkspaceInstance extends VmWithInstance {
|
|
43
|
+
}
|
|
44
|
+
declare class NodeJsWorkspaceTask extends VmWith<NodeJsWorkspaceTaskInstance> {
|
|
45
|
+
name: string;
|
|
46
|
+
workspace: NodeJsWorkspace;
|
|
47
|
+
env?: Record<string, string>;
|
|
48
|
+
serviceName?: string;
|
|
49
|
+
constructor(name: string, workspace: NodeJsWorkspace, env?: Record<string, string>, serviceName?: string);
|
|
50
|
+
getServiceName(): string;
|
|
51
|
+
configureSpec(spec: VmSpec): VmSpec;
|
|
52
|
+
createInstance(): NodeJsWorkspaceTaskInstance;
|
|
53
|
+
}
|
|
54
|
+
declare class NodeJsWorkspaceTaskInstance extends VmWithInstance {
|
|
55
|
+
name: string;
|
|
56
|
+
workspace: NodeJsWorkspace;
|
|
57
|
+
env?: Record<string, string>;
|
|
58
|
+
serviceName?: string;
|
|
59
|
+
constructor(name: string, workspace: NodeJsWorkspace, env?: Record<string, string>, serviceName?: string);
|
|
60
|
+
getServiceName(): string;
|
|
61
|
+
logs(): Promise<string[] | undefined>;
|
|
62
|
+
}
|
|
19
63
|
declare class NodeJsRuntimeInstance extends VmWithInstance implements VmJavaScriptRuntimeInstance {
|
|
20
64
|
builder: VmNodeJs;
|
|
21
65
|
constructor(builder: VmNodeJs);
|
|
@@ -28,4 +72,4 @@ declare class NodeJsRuntimeInstance extends VmWithInstance implements VmJavaScri
|
|
|
28
72
|
install(options?: InstallOptions): Promise<InstallResult>;
|
|
29
73
|
}
|
|
30
74
|
|
|
31
|
-
export { VmNodeJs };
|
|
75
|
+
export { NodeJsWorkspace, NodeJsWorkspaceInstance, NodeJsWorkspaceTask, NodeJsWorkspaceTaskInstance, VmNodeJs };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { VmWith, VmSpec, VmWithInstance } from 'freestyle-sandboxes';
|
|
|
2
2
|
|
|
3
3
|
class VmNodeJs extends VmWith {
|
|
4
4
|
options;
|
|
5
|
+
workspaces = [];
|
|
5
6
|
constructor(options) {
|
|
6
7
|
super();
|
|
7
8
|
this.options = {
|
|
@@ -53,10 +54,140 @@ npm -v
|
|
|
53
54
|
createInstance() {
|
|
54
55
|
return new NodeJsRuntimeInstance(this);
|
|
55
56
|
}
|
|
57
|
+
workspace(options) {
|
|
58
|
+
const workspace = new NodeJsWorkspace(options);
|
|
59
|
+
this.workspaces.push(workspace);
|
|
60
|
+
return workspace;
|
|
61
|
+
}
|
|
56
62
|
installServiceName() {
|
|
57
63
|
return `install-nodejs.service`;
|
|
58
64
|
}
|
|
59
65
|
}
|
|
66
|
+
class NodeJsWorkspace extends VmWith {
|
|
67
|
+
options;
|
|
68
|
+
env;
|
|
69
|
+
constructor(options, env) {
|
|
70
|
+
super();
|
|
71
|
+
this.options = options;
|
|
72
|
+
this.env = env;
|
|
73
|
+
}
|
|
74
|
+
task(name, options) {
|
|
75
|
+
return new NodeJsWorkspaceTask(
|
|
76
|
+
name,
|
|
77
|
+
this,
|
|
78
|
+
{
|
|
79
|
+
...this.env,
|
|
80
|
+
...options?.env
|
|
81
|
+
},
|
|
82
|
+
options?.serviceName
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
getInstallServiceName() {
|
|
86
|
+
return `nodejs-install-${this.options.path.replace(/\//g, "-")}`;
|
|
87
|
+
}
|
|
88
|
+
configureSpec(spec) {
|
|
89
|
+
if (this.options.install) {
|
|
90
|
+
return this.composeSpecs(
|
|
91
|
+
spec,
|
|
92
|
+
new VmSpec({
|
|
93
|
+
systemd: {
|
|
94
|
+
services: [
|
|
95
|
+
{
|
|
96
|
+
name: this.getInstallServiceName(),
|
|
97
|
+
mode: "oneshot",
|
|
98
|
+
exec: ['bash -lc "source /opt/nvm/nvm.sh && npm install"'],
|
|
99
|
+
workdir: this.options.path,
|
|
100
|
+
env: {
|
|
101
|
+
HOME: "/root",
|
|
102
|
+
NVM_DIR: "/opt/nvm",
|
|
103
|
+
...this.env
|
|
104
|
+
},
|
|
105
|
+
user: "root"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return spec;
|
|
113
|
+
}
|
|
114
|
+
createInstance() {
|
|
115
|
+
return new NodeJsWorkspaceInstance();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
class NodeJsWorkspaceInstance extends VmWithInstance {
|
|
119
|
+
}
|
|
120
|
+
class NodeJsWorkspaceTask extends VmWith {
|
|
121
|
+
name;
|
|
122
|
+
workspace;
|
|
123
|
+
env;
|
|
124
|
+
serviceName;
|
|
125
|
+
constructor(name, workspace, env, serviceName) {
|
|
126
|
+
super();
|
|
127
|
+
this.name = name;
|
|
128
|
+
this.workspace = workspace;
|
|
129
|
+
this.env = env;
|
|
130
|
+
this.serviceName = serviceName;
|
|
131
|
+
}
|
|
132
|
+
getServiceName() {
|
|
133
|
+
return this.serviceName ?? `nodejs-workspace-${this.workspace.options.path.replace(/\//g, "-")}-task-${this.name}`;
|
|
134
|
+
}
|
|
135
|
+
configureSpec(spec) {
|
|
136
|
+
return this.composeSpecs(
|
|
137
|
+
spec,
|
|
138
|
+
new VmSpec({
|
|
139
|
+
systemd: {
|
|
140
|
+
services: [
|
|
141
|
+
{
|
|
142
|
+
name: this.getServiceName(),
|
|
143
|
+
exec: [
|
|
144
|
+
`bash -lc "source /opt/nvm/nvm.sh && npm run ${this.name}"`
|
|
145
|
+
],
|
|
146
|
+
workdir: this.workspace.options.path,
|
|
147
|
+
after: this.workspace.options.install ? [this.workspace.getInstallServiceName()] : void 0,
|
|
148
|
+
requires: this.workspace.options.install ? [this.workspace.getInstallServiceName()] : void 0,
|
|
149
|
+
env: {
|
|
150
|
+
HOME: "/root",
|
|
151
|
+
NVM_DIR: "/opt/nvm",
|
|
152
|
+
...this.env
|
|
153
|
+
},
|
|
154
|
+
user: "root"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
createInstance() {
|
|
162
|
+
return new NodeJsWorkspaceTaskInstance(
|
|
163
|
+
this.name,
|
|
164
|
+
this.workspace,
|
|
165
|
+
this.env,
|
|
166
|
+
this.serviceName
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
class NodeJsWorkspaceTaskInstance extends VmWithInstance {
|
|
171
|
+
name;
|
|
172
|
+
workspace;
|
|
173
|
+
env;
|
|
174
|
+
serviceName;
|
|
175
|
+
constructor(name, workspace, env, serviceName) {
|
|
176
|
+
super();
|
|
177
|
+
this.name = name;
|
|
178
|
+
this.workspace = workspace;
|
|
179
|
+
this.env = env;
|
|
180
|
+
this.serviceName = serviceName;
|
|
181
|
+
}
|
|
182
|
+
getServiceName() {
|
|
183
|
+
return this.serviceName ?? `nodejs-workspace-${this.workspace.options.path.replace(/\//g, "-")}-task-${this.name}`;
|
|
184
|
+
}
|
|
185
|
+
logs() {
|
|
186
|
+
return this.vm.exec({
|
|
187
|
+
command: `journalctl -u ${this.getServiceName()} --no-pager -n 30`
|
|
188
|
+
}).then((result) => result.stdout?.trim().split("\n"));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
60
191
|
class NodeJsRuntimeInstance extends VmWithInstance {
|
|
61
192
|
builder;
|
|
62
193
|
constructor(builder) {
|
|
@@ -118,4 +249,4 @@ class NodeJsRuntimeInstance extends VmWithInstance {
|
|
|
118
249
|
}
|
|
119
250
|
}
|
|
120
251
|
|
|
121
|
-
export { VmNodeJs };
|
|
252
|
+
export { NodeJsWorkspace, NodeJsWorkspaceInstance, NodeJsWorkspaceTask, NodeJsWorkspaceTaskInstance, VmNodeJs };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@freestyle-sh/with-nodejs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"freestyle-sandboxes": "^0.1.
|
|
7
|
-
"@freestyle-sh/with-type-js": "^0.2.
|
|
6
|
+
"freestyle-sandboxes": "^0.1.41",
|
|
7
|
+
"@freestyle-sh/with-type-js": "^0.2.9"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"main": "./dist/index.js",
|