oblien 2.1.5 → 2.1.7
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 +140 -439
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -0
- package/dist/client.js.map +1 -1
- package/dist/domain.d.ts +45 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +57 -0
- package/dist/domain.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +37 -25
- package/dist/mcp/tools.js.map +1 -1
- package/dist/pages.d.ts +18 -18
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +29 -29
- package/dist/pages.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/pages.d.ts +0 -1
- package/dist/types/pages.d.ts.map +1 -1
- package/dist/types/workspace-resources.d.ts +42 -0
- package/dist/types/workspace-resources.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Cloud workspaces that boot in milliseconds and run anything.
|
|
4
4
|
|
|
5
|
-
Oblien gives you hardware-isolated microVMs
|
|
5
|
+
Oblien gives you hardware-isolated microVMs — each with its own kernel, its own memory, and full root access. Use them to give an AI agent a live environment, deploy a service with a public URL, run untrusted code in a throwaway sandbox, or spin up a dev machine you can SSH into. The workspace is the only primitive. What it becomes is up to you.
|
|
6
6
|
|
|
7
|
-
This is the official TypeScript SDK. It covers the full Oblien API surface
|
|
7
|
+
This is the official TypeScript SDK. It covers the full Oblien API surface.
|
|
8
8
|
|
|
9
9
|
**Documentation:** [https://oblien.com/docs](https://oblien.com/docs)
|
|
10
10
|
|
|
@@ -12,23 +12,23 @@ This is the official TypeScript SDK. It covers the full Oblien API surface: work
|
|
|
12
12
|
|
|
13
13
|
## Platform
|
|
14
14
|
|
|
15
|
-
Oblien is a workspace platform. Every workspace is a microVM that boots in under a second from any Docker image. Workspaces can be temporary (auto-delete after a TTL) or permanent (run indefinitely). They can be air-gapped or wired to other workspaces over a private internal network. They can expose ports to the internet
|
|
15
|
+
Oblien is a workspace platform. Every workspace is a microVM that boots in under a second from any Docker image. Workspaces can be temporary (auto-delete after a TTL) or permanent (run indefinitely). They can be air-gapped or wired to other workspaces over a private internal network. They can expose ports to the internet with automatic TLS — or stay completely invisible.
|
|
16
16
|
|
|
17
17
|
The architecture is split into two planes:
|
|
18
18
|
|
|
19
|
-
- **Control plane** (`api.oblien.com`)
|
|
20
|
-
- **Data plane** (`workspace.oblien.com`)
|
|
19
|
+
- **Control plane** (`api.oblien.com`) — Create, configure, start, stop, snapshot, and destroy workspaces. Manage networking, domains, pages, namespaces, and billing.
|
|
20
|
+
- **Data plane** (`workspace.oblien.com`) — Interact with a running workspace's filesystem, execute commands, open terminal sessions, watch files, and stream events over WebSocket.
|
|
21
21
|
|
|
22
22
|
The SDK wraps both planes in a single client.
|
|
23
23
|
|
|
24
24
|
### What people build with it
|
|
25
25
|
|
|
26
|
-
- **AI agent environments**
|
|
27
|
-
- **Service hosting**
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
26
|
+
- **AI agent environments** — A permanent workspace is the agent's home. It creates short-lived sandboxes on demand for tasks, user code, or deployments.
|
|
27
|
+
- **Service hosting** — Run an API server, a queue worker, or a database. Map it to a custom domain.
|
|
28
|
+
- **Static pages** — Deploy build output from a workspace to the edge CDN. No running VM required.
|
|
29
|
+
- **Remote development** — SSH into a workspace, install your stack, expose a port for live preview.
|
|
30
|
+
- **Per-user environments** — One workspace per customer with scoped networking, credit quotas, and full isolation.
|
|
31
|
+
- **Enterprise routing** — Route subdomains to external upstreams through the edge proxy.
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
@@ -52,20 +52,16 @@ const client = new Oblien({
|
|
|
52
52
|
clientSecret: process.env.OBLIEN_CLIENT_SECRET,
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
const ws = client.workspaces;
|
|
56
|
-
|
|
57
55
|
// Create a workspace
|
|
58
|
-
const workspace = await
|
|
56
|
+
const workspace = await client.workspaces.create({
|
|
59
57
|
image: 'node-20',
|
|
60
58
|
mode: 'permanent',
|
|
61
|
-
|
|
59
|
+
cpus: 2,
|
|
60
|
+
memory_mb: 4096,
|
|
62
61
|
});
|
|
63
62
|
|
|
64
|
-
//
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
// Connect to the runtime -- filesystem, exec, terminal
|
|
68
|
-
const rt = await ws.runtime(workspace.id);
|
|
63
|
+
// Connect to the runtime — filesystem, exec, terminal
|
|
64
|
+
const rt = await client.workspaces.runtime(workspace.id);
|
|
69
65
|
|
|
70
66
|
// Run a command
|
|
71
67
|
const result = await rt.exec.run(['node', '--version']);
|
|
@@ -74,454 +70,188 @@ console.log(result.stdout);
|
|
|
74
70
|
// Read a file
|
|
75
71
|
const file = await rt.files.read({ filePath: '/etc/os-release' });
|
|
76
72
|
console.log(file.content);
|
|
77
|
-
|
|
78
|
-
// Expose port 3000 to the internet
|
|
79
|
-
await ws.publicAccess.expose(workspace.id, { port: 3000 });
|
|
80
73
|
```
|
|
81
74
|
|
|
82
75
|
---
|
|
83
76
|
|
|
84
|
-
##
|
|
85
|
-
|
|
86
|
-
### Client and workspaces
|
|
77
|
+
## SDK structure
|
|
87
78
|
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
```
|
|
80
|
+
client
|
|
81
|
+
├── workspaces Control-plane workspace CRUD + power + sub-resources
|
|
82
|
+
│ ├── lifecycle Permanent/temporary mode, TTL, ping
|
|
83
|
+
│ ├── network Firewall, private links, outbound IP
|
|
84
|
+
│ ├── ssh SSH enable/disable, password/key
|
|
85
|
+
│ ├── publicAccess Expose ports with public URLs
|
|
86
|
+
│ ├── domains Custom domains with automatic SSL
|
|
87
|
+
│ ├── resources CPU, memory, disk allocation
|
|
88
|
+
│ ├── snapshots Snapshots and versioned archives
|
|
89
|
+
│ ├── workloads Managed background processes
|
|
90
|
+
│ ├── metrics Live stats, VM info/config
|
|
91
|
+
│ ├── usage Credit usage and activity tracking
|
|
92
|
+
│ ├── metadata Key-value metadata store
|
|
93
|
+
│ ├── apiAccess Runtime API tokens (gateway JWT / raw)
|
|
94
|
+
│ ├── logs Boot and command logs
|
|
95
|
+
│ └── images Available base images
|
|
96
|
+
│
|
|
97
|
+
├── pages Static pages — deploy to the edge CDN from any workspace
|
|
98
|
+
├── namespaces Group workspaces, enforce resource limits and quotas
|
|
99
|
+
├── edgeProxy Enterprise reverse proxy — route subdomains to upstreams
|
|
100
|
+
├── domain Pre-flight checks — slug availability + DNS verification
|
|
101
|
+
│
|
|
102
|
+
└── workspace(id) Scoped handle — all methods pre-filled with a workspace ID
|
|
93
103
|
```
|
|
94
104
|
|
|
95
|
-
|
|
105
|
+
---
|
|
96
106
|
|
|
97
|
-
|
|
98
|
-
|-----------|-------------|
|
|
99
|
-
| `ws.lifecycle` | Permanent/temporary mode, TTL, ping, destroy |
|
|
100
|
-
| `ws.network` | Firewall rules, private links, outbound IP |
|
|
101
|
-
| `ws.ssh` | Enable SSH, set password or public key |
|
|
102
|
-
| `ws.publicAccess` | Expose and revoke public ports |
|
|
103
|
-
| `ws.resources` | CPU, memory, disk allocation |
|
|
104
|
-
| `ws.snapshots` | Create, restore, archive, and manage snapshots |
|
|
105
|
-
| `ws.workloads` | Managed background processes with log streaming |
|
|
106
|
-
| `ws.metrics` | Live CPU/memory/disk/network stats, VM info and config |
|
|
107
|
-
| `ws.usage` | Credit usage, activity tracking |
|
|
108
|
-
| `ws.metadata` | Key-value metadata store |
|
|
109
|
-
| `ws.apiAccess` | Runtime API server -- enable, disable, rotate tokens |
|
|
110
|
-
| `ws.logs` | Boot and command logs |
|
|
111
|
-
| `ws.images` | Available workspace images |
|
|
112
|
-
|
|
113
|
-
### CRUD
|
|
107
|
+
## Workspaces
|
|
114
108
|
|
|
115
109
|
```typescript
|
|
116
|
-
|
|
117
|
-
const workspace = await ws.create({ image: 'node-20', mode: 'permanent' });
|
|
118
|
-
|
|
119
|
-
// List
|
|
120
|
-
const { workspaces } = await ws.list({ page: 1, limit: 20 });
|
|
121
|
-
|
|
122
|
-
// Get
|
|
123
|
-
const data = await ws.get('ws_a1b2c3d4');
|
|
124
|
-
|
|
125
|
-
// Update
|
|
126
|
-
await ws.update('ws_a1b2c3d4', { name: 'production-api' });
|
|
127
|
-
|
|
128
|
-
// Delete
|
|
129
|
-
await ws.delete('ws_a1b2c3d4');
|
|
130
|
-
```
|
|
110
|
+
const ws = client.workspaces;
|
|
131
111
|
|
|
132
|
-
|
|
112
|
+
// CRUD
|
|
113
|
+
const workspace = await ws.create({ image: 'node-20' });
|
|
114
|
+
const { workspaces } = await ws.list();
|
|
115
|
+
const data = await ws.get(workspace.id);
|
|
116
|
+
await ws.update(workspace.id, { name: 'my-api' });
|
|
117
|
+
await ws.delete(workspace.id);
|
|
133
118
|
|
|
134
|
-
|
|
119
|
+
// Power
|
|
135
120
|
await ws.start(id);
|
|
136
121
|
await ws.stop(id);
|
|
137
122
|
await ws.restart(id);
|
|
138
|
-
await ws.pause(id);
|
|
123
|
+
await ws.pause(id);
|
|
139
124
|
await ws.resume(id);
|
|
140
|
-
await ws.ping(id); // renews TTL for temporary workspaces
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Account-level queries
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
const quota = await ws.getQuota();
|
|
147
|
-
const estimate = await ws.getEstimate({ cpu: 4, ram_mb: 8192 });
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Runtime (data plane)
|
|
153
|
-
|
|
154
|
-
The runtime connects to a running workspace and provides direct access to its filesystem, command execution, terminal sessions, search, and file watchers.
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
const rt = await ws.runtime('ws_a1b2c3d4');
|
|
158
125
|
```
|
|
159
126
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
### Files
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// List directory
|
|
166
|
-
const entries = await rt.files.list({ dirPath: '/app' });
|
|
167
|
-
|
|
168
|
-
// Read file
|
|
169
|
-
const { content } = await rt.files.read({ filePath: '/app/index.js' });
|
|
170
|
-
|
|
171
|
-
// Write file
|
|
172
|
-
await rt.files.write({ fullPath: '/app/config.json', content: '{}' });
|
|
127
|
+
Sub-resources are accessed through namespaces on the workspaces object — `ws.lifecycle`, `ws.network`, `ws.domains`, etc. See the [API reference](https://oblien.com/docs/api) for full details on each.
|
|
173
128
|
|
|
174
|
-
|
|
175
|
-
await rt.files.mkdir({ path: '/app/logs' });
|
|
129
|
+
### Scoped handle
|
|
176
130
|
|
|
177
|
-
|
|
178
|
-
const stat = await rt.files.stat({ path: '/app/index.js' });
|
|
179
|
-
|
|
180
|
-
// Delete
|
|
181
|
-
await rt.files.delete({ path: '/app/tmp' });
|
|
182
|
-
|
|
183
|
-
// Stream directory tree (async generator)
|
|
184
|
-
for await (const entry of rt.files.stream({ dirPath: '/app' })) {
|
|
185
|
-
console.log(entry.path);
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Exec
|
|
131
|
+
Bind to a single workspace so you don't have to pass the ID every time:
|
|
190
132
|
|
|
191
133
|
```typescript
|
|
192
|
-
|
|
193
|
-
const result = await rt.exec.run(['npm', 'test']);
|
|
194
|
-
console.log(result.exitCode, result.stdout, result.stderr);
|
|
195
|
-
|
|
196
|
-
// Stream output as it happens (async generator)
|
|
197
|
-
for await (const event of rt.exec.stream(['npm', 'run', 'build'])) {
|
|
198
|
-
process.stdout.write(event.data);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// List running tasks
|
|
202
|
-
const tasks = await rt.exec.list();
|
|
203
|
-
|
|
204
|
-
// Kill a task
|
|
205
|
-
await rt.exec.kill(taskId);
|
|
134
|
+
const handle = client.workspace('ws_abc');
|
|
206
135
|
|
|
207
|
-
|
|
208
|
-
await
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
for await (const event of rt.exec.subscribe(taskId)) {
|
|
212
|
-
console.log(event);
|
|
213
|
-
}
|
|
136
|
+
await handle.start();
|
|
137
|
+
const rt = await handle.runtime();
|
|
138
|
+
await rt.exec.run(['npm', 'test']);
|
|
139
|
+
await handle.stop();
|
|
214
140
|
```
|
|
215
141
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
// Create a terminal session
|
|
220
|
-
const session = await rt.terminal.create({ shell: '/bin/bash' });
|
|
221
|
-
|
|
222
|
-
// List sessions
|
|
223
|
-
const sessions = await rt.terminal.list();
|
|
224
|
-
|
|
225
|
-
// Get scrollback buffer
|
|
226
|
-
const { data } = await rt.terminal.scrollback(session.id, { bytes: 4096 });
|
|
142
|
+
---
|
|
227
143
|
|
|
228
|
-
|
|
229
|
-
await rt.terminal.close(session.id);
|
|
230
|
-
```
|
|
144
|
+
## Runtime (data plane)
|
|
231
145
|
|
|
232
|
-
|
|
146
|
+
The runtime connects to a running workspace and gives you direct access to its filesystem, command execution, terminal sessions, code search, and file watchers.
|
|
233
147
|
|
|
234
148
|
```typescript
|
|
235
|
-
|
|
236
|
-
const hits = await rt.search.content({ query: 'TODO', path: '/app' });
|
|
237
|
-
|
|
238
|
-
// Search file names
|
|
239
|
-
const files = await rt.search.files({ query: 'config', path: '/app' });
|
|
240
|
-
|
|
241
|
-
// Index status and initialization
|
|
242
|
-
const status = await rt.search.status();
|
|
243
|
-
await rt.search.init();
|
|
149
|
+
const rt = await client.workspaces.runtime('ws_abc');
|
|
244
150
|
```
|
|
245
151
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
// Watch a directory for changes
|
|
250
|
-
const watcher = await rt.watcher.create({ path: '/app/src' });
|
|
251
|
-
|
|
252
|
-
// List active watchers
|
|
253
|
-
const watchers = await rt.watcher.list();
|
|
152
|
+
This enables the Runtime API server (if needed), fetches a gateway JWT, and returns a `Runtime` instance. The token is cached — subsequent calls for the same workspace return instantly.
|
|
254
153
|
|
|
255
|
-
|
|
256
|
-
|
|
154
|
+
| Namespace | What it does |
|
|
155
|
+
|-----------|-------------|
|
|
156
|
+
| `rt.files` | List, read, write, stat, mkdir, delete, stream directory trees |
|
|
157
|
+
| `rt.exec` | Run commands, stream output, list/kill tasks, send stdin |
|
|
158
|
+
| `rt.terminal` | Create PTY sessions, get scrollback, close sessions |
|
|
159
|
+
| `rt.search` | Content search (ripgrep) and filename search |
|
|
160
|
+
| `rt.watcher` | Watch directories for real-time file change events |
|
|
161
|
+
| `rt.ws()` | WebSocket — persistent connection for terminal I/O and watcher events |
|
|
257
162
|
|
|
258
|
-
|
|
259
|
-
await rt.watcher.delete(watcher.id);
|
|
260
|
-
```
|
|
163
|
+
See the [Runtime API docs](https://oblien.com/docs/runtime-api) for full endpoint reference.
|
|
261
164
|
|
|
262
165
|
---
|
|
263
166
|
|
|
264
|
-
##
|
|
167
|
+
## Pages
|
|
265
168
|
|
|
266
|
-
|
|
169
|
+
Deploy static files from a workspace to the edge CDN. The workspace can stop or be deleted after export — the page stays live with automatic TLS.
|
|
267
170
|
|
|
268
171
|
```typescript
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
socket.onTerminalOutput((data) => {
|
|
276
|
-
process.stdout.write(data.output);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
socket.onWatcherEvent((event) => {
|
|
280
|
-
console.log(event.type, event.path);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
socket.onClose(() => {
|
|
284
|
-
console.log('disconnected');
|
|
172
|
+
// Deploy a page
|
|
173
|
+
const { page } = await client.pages.create({
|
|
174
|
+
workspace_id: 'ws_abc',
|
|
175
|
+
path: '/app/dist',
|
|
176
|
+
name: 'my-app',
|
|
285
177
|
});
|
|
286
178
|
|
|
287
|
-
|
|
288
|
-
|
|
179
|
+
// Re-deploy with fresh files
|
|
180
|
+
await client.pages.deploy(page.slug, {
|
|
181
|
+
workspace_id: 'ws_abc',
|
|
182
|
+
path: '/app/dist',
|
|
289
183
|
});
|
|
290
184
|
|
|
291
|
-
|
|
185
|
+
// Custom domain
|
|
186
|
+
await client.pages.connectDomain(page.slug, { domain: 'app.example.com' });
|
|
292
187
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// Resize terminal
|
|
297
|
-
socket.resizeTerminal(sessionId, { cols: 120, rows: 40 });
|
|
188
|
+
// Toggle
|
|
189
|
+
await client.pages.disable(page.slug);
|
|
190
|
+
await client.pages.enable(page.slug);
|
|
298
191
|
```
|
|
299
192
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
## SSE streaming
|
|
303
|
-
|
|
304
|
-
Several endpoints return server-sent events as async generators. Consume them with `for await`:
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
// Stream workspace logs
|
|
308
|
-
for await (const line of ws.logs.streamBoot(id)) {
|
|
309
|
-
console.log(line);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Stream workload output
|
|
313
|
-
for await (const event of ws.workloads.logsStream(id, workloadId)) {
|
|
314
|
-
process.stdout.write(event.data);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Stream live metrics
|
|
318
|
-
for await (const snapshot of ws.metrics.statsStream(id)) {
|
|
319
|
-
console.log(snapshot.cpu_percent, snapshot.memory_used_mb);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Stream workload stats
|
|
323
|
-
for await (const stats of ws.workloads.statsStream(id, workloadId)) {
|
|
324
|
-
console.log(stats);
|
|
325
|
-
}
|
|
326
|
-
```
|
|
193
|
+
See the [Pages docs](https://oblien.com/docs/concepts/pages) for concepts and the [Pages API](https://oblien.com/docs/api/pages) for the full reference.
|
|
327
194
|
|
|
328
195
|
---
|
|
329
196
|
|
|
330
|
-
##
|
|
331
|
-
|
|
332
|
-
### Lifecycle
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
const status = await ws.lifecycle.get(id);
|
|
336
|
-
|
|
337
|
-
// Convert to permanent
|
|
338
|
-
await ws.lifecycle.makePermanent(id);
|
|
339
|
-
|
|
340
|
-
// Convert to temporary with TTL
|
|
341
|
-
await ws.lifecycle.makeTemporary(id, { ttl_seconds: 3600 });
|
|
342
|
-
|
|
343
|
-
// Update TTL
|
|
344
|
-
await ws.lifecycle.updateTtl(id, { ttl_seconds: 7200 });
|
|
345
|
-
|
|
346
|
-
// Destroy (irreversible)
|
|
347
|
-
await ws.lifecycle.destroy(id);
|
|
348
|
-
```
|
|
197
|
+
## Domains
|
|
349
198
|
|
|
350
|
-
|
|
199
|
+
Pre-flight checks before connecting custom domains or claiming slugs. These are standalone — not scoped to a specific workspace or page.
|
|
351
200
|
|
|
352
201
|
```typescript
|
|
353
|
-
|
|
202
|
+
// Check if a slug is available
|
|
203
|
+
const { available, url } = await client.domain.checkSlug({ slug: 'my-app' });
|
|
354
204
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
205
|
+
// Verify DNS for a custom domain
|
|
206
|
+
const { verified, cname, required_records } = await client.domain.verify({
|
|
207
|
+
domain: 'app.example.com',
|
|
208
|
+
resource_id: 'ws_abc',
|
|
359
209
|
});
|
|
360
|
-
|
|
361
|
-
// Assign a dedicated outbound IP
|
|
362
|
-
await ws.network.applyOutboundIp(id, { ip: '203.0.113.50' });
|
|
363
210
|
```
|
|
364
211
|
|
|
365
|
-
|
|
212
|
+
---
|
|
366
213
|
|
|
367
|
-
|
|
368
|
-
await ws.ssh.enable(id, { password: 'secure-password' });
|
|
369
|
-
await ws.ssh.enable(id, { publicKey: 'ssh-ed25519 AAAA...' });
|
|
370
|
-
await ws.ssh.disable(id);
|
|
371
|
-
const sshStatus = await ws.ssh.status(id);
|
|
372
|
-
```
|
|
214
|
+
## Namespaces
|
|
373
215
|
|
|
374
|
-
|
|
216
|
+
Group workspaces into isolated namespaces with resource limits, spending quotas, and lifecycle controls.
|
|
375
217
|
|
|
376
218
|
```typescript
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
domain: 'app.yourdomain.com',
|
|
219
|
+
const ns = await client.namespaces.create({
|
|
220
|
+
name: 'production',
|
|
221
|
+
resource_limits: { max_workspaces: 50, max_cpus: 100 },
|
|
381
222
|
});
|
|
382
223
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
await ws.publicAccess.revoke(id, { port: 3000 });
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Snapshots
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
// Create a snapshot
|
|
394
|
-
await ws.snapshots.create(id, { label: 'before-deploy' });
|
|
395
|
-
|
|
396
|
-
// Restore
|
|
397
|
-
await ws.snapshots.restore(id);
|
|
398
|
-
|
|
399
|
-
// Archives
|
|
400
|
-
await ws.snapshots.createArchive(id, { label: 'v1.0' });
|
|
401
|
-
const archives = await ws.snapshots.listArchives(id);
|
|
402
|
-
const archive = await ws.snapshots.getArchive(id, 'v1');
|
|
403
|
-
await ws.snapshots.deleteArchive(id, 'v1');
|
|
404
|
-
await ws.snapshots.deleteAllArchives(id);
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Workloads
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
// Create a managed workload
|
|
411
|
-
await ws.workloads.create(id, {
|
|
412
|
-
name: 'server',
|
|
413
|
-
cmd: ['node', 'server.js'],
|
|
414
|
-
env: { PORT: '3000' },
|
|
224
|
+
await client.namespaces.setQuota(ns.id, {
|
|
225
|
+
period: 'monthly',
|
|
226
|
+
max_credits: 500,
|
|
227
|
+
overdraft_action: 'stop',
|
|
415
228
|
});
|
|
416
229
|
|
|
417
|
-
const
|
|
418
|
-
const workload = await ws.workloads.get(id, workloadId);
|
|
419
|
-
await ws.workloads.start(id, workloadId);
|
|
420
|
-
await ws.workloads.stop(id, workloadId);
|
|
421
|
-
await ws.workloads.delete(id, workloadId);
|
|
422
|
-
|
|
423
|
-
// Logs and stats (async generators)
|
|
424
|
-
for await (const line of ws.workloads.logsStream(id, workloadId)) {
|
|
425
|
-
console.log(line);
|
|
426
|
-
}
|
|
427
|
-
for await (const snapshot of ws.workloads.statsStream(id, workloadId)) {
|
|
428
|
-
console.log(snapshot);
|
|
429
|
-
}
|
|
230
|
+
const { namespaces } = await client.namespaces.list();
|
|
430
231
|
```
|
|
431
232
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
```typescript
|
|
435
|
-
const stats = await ws.metrics.stats(id);
|
|
436
|
-
const info = await ws.metrics.info(id);
|
|
437
|
-
const config = await ws.metrics.config(id);
|
|
438
|
-
|
|
439
|
-
for await (const snapshot of ws.metrics.statsStream(id)) {
|
|
440
|
-
console.log(snapshot);
|
|
441
|
-
}
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### Usage
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
const usage = await ws.usage.get(id);
|
|
448
|
-
const totals = await ws.usage.totals(id);
|
|
449
|
-
const chart = await ws.usage.creditsChart(id);
|
|
450
|
-
const global = await ws.usage.global();
|
|
451
|
-
const activity = await ws.usage.activity();
|
|
452
|
-
await ws.usage.wipe(id);
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### Metadata
|
|
456
|
-
|
|
457
|
-
```typescript
|
|
458
|
-
const meta = await ws.metadata.get(id);
|
|
459
|
-
await ws.metadata.update(id, { key: 'env', value: 'production' });
|
|
460
|
-
await ws.metadata.patch(id, { key: 'version', value: '2.1.0' });
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### API access
|
|
464
|
-
|
|
465
|
-
```typescript
|
|
466
|
-
const status = await ws.apiAccess.status(id);
|
|
467
|
-
const access = await ws.apiAccess.enable(id);
|
|
468
|
-
await ws.apiAccess.disable(id);
|
|
469
|
-
await ws.apiAccess.rotateToken(id);
|
|
470
|
-
const token = await ws.apiAccess.getToken(id);
|
|
471
|
-
const raw = await ws.apiAccess.rawToken(id);
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Logs
|
|
475
|
-
|
|
476
|
-
```typescript
|
|
477
|
-
const log = await ws.logs.get(id);
|
|
478
|
-
await ws.logs.clear(id);
|
|
479
|
-
const files = await ws.logs.listFiles(id);
|
|
480
|
-
const file = await ws.logs.getFile(id, 'boot.log');
|
|
481
|
-
|
|
482
|
-
for await (const line of ws.logs.streamBoot(id)) {
|
|
483
|
-
console.log(line);
|
|
484
|
-
}
|
|
485
|
-
for await (const line of ws.logs.streamCmd(id)) {
|
|
486
|
-
console.log(line);
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
### Images
|
|
491
|
-
|
|
492
|
-
```typescript
|
|
493
|
-
const images = await ws.images.list();
|
|
494
|
-
const image = await ws.images.get('node-20');
|
|
495
|
-
```
|
|
233
|
+
See the [Namespaces API](https://oblien.com/docs/api/namespaces) for the full reference.
|
|
496
234
|
|
|
497
235
|
---
|
|
498
236
|
|
|
499
|
-
##
|
|
237
|
+
## Edge Proxy
|
|
500
238
|
|
|
501
|
-
|
|
239
|
+
Enterprise-only reverse proxy — route subdomains to external upstreams through the edge.
|
|
502
240
|
|
|
503
241
|
```typescript
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
// Runtime (data plane) -- standalone with a raw token
|
|
511
|
-
import { Runtime } from 'oblien/runtime';
|
|
512
|
-
|
|
513
|
-
const rt = new Runtime({
|
|
514
|
-
token: 'your_gateway_jwt',
|
|
242
|
+
const { proxy } = await client.edgeProxy.create({
|
|
243
|
+
name: 'staging-api',
|
|
244
|
+
slug: 'staging-api',
|
|
245
|
+
domain: 'edge.example.com',
|
|
246
|
+
target: 'https://internal-staging.example.com:8080',
|
|
515
247
|
});
|
|
516
|
-
await rt.files.list({ dirPath: '/' });
|
|
517
248
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
token: 'raw_token',
|
|
521
|
-
baseUrl: 'http://10.0.1.5:9990',
|
|
522
|
-
});
|
|
249
|
+
await client.edgeProxy.disable(proxy.id);
|
|
250
|
+
await client.edgeProxy.enable(proxy.id);
|
|
523
251
|
```
|
|
524
252
|
|
|
253
|
+
See the [Edge Proxy docs](https://oblien.com/docs/concepts/edge-proxy) for details.
|
|
254
|
+
|
|
525
255
|
---
|
|
526
256
|
|
|
527
257
|
## Error handling
|
|
@@ -529,44 +259,24 @@ const directRt = new Runtime({
|
|
|
529
259
|
Every API error is an instance of `OblienError` with typed subclasses:
|
|
530
260
|
|
|
531
261
|
```typescript
|
|
532
|
-
import
|
|
533
|
-
OblienError,
|
|
534
|
-
AuthenticationError,
|
|
535
|
-
NotFoundError,
|
|
536
|
-
RateLimitError,
|
|
537
|
-
ValidationError,
|
|
538
|
-
PaymentRequiredError,
|
|
539
|
-
ConflictError,
|
|
540
|
-
} from 'oblien';
|
|
262
|
+
import { NotFoundError, RateLimitError, PaymentRequiredError } from 'oblien';
|
|
541
263
|
|
|
542
264
|
try {
|
|
543
|
-
await
|
|
265
|
+
await client.workspaces.get('ws_nonexistent');
|
|
544
266
|
} catch (err) {
|
|
545
|
-
if (err instanceof NotFoundError) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
console.log('Bad credentials');
|
|
549
|
-
} else if (err instanceof RateLimitError) {
|
|
550
|
-
console.log('Slow down -- retry after backoff');
|
|
551
|
-
} else if (err instanceof PaymentRequiredError) {
|
|
552
|
-
console.log('Quota exceeded -- upgrade your plan');
|
|
553
|
-
} else if (err instanceof ValidationError) {
|
|
554
|
-
console.log('Invalid parameters:', err.message);
|
|
555
|
-
} else if (err instanceof ConflictError) {
|
|
556
|
-
console.log('Workspace is in the wrong state for this operation');
|
|
557
|
-
} else if (err instanceof OblienError) {
|
|
558
|
-
console.log(`API error ${err.status}: ${err.message}`);
|
|
559
|
-
}
|
|
267
|
+
if (err instanceof NotFoundError) { /* 404 */ }
|
|
268
|
+
if (err instanceof RateLimitError) { /* 429 — back off */ }
|
|
269
|
+
if (err instanceof PaymentRequiredError) { /* 402 — quota exceeded */ }
|
|
560
270
|
}
|
|
561
271
|
```
|
|
562
272
|
|
|
563
|
-
| Error class | HTTP
|
|
564
|
-
|
|
273
|
+
| Error class | HTTP | When |
|
|
274
|
+
|-------------|------|------|
|
|
565
275
|
| `AuthenticationError` | 401 | Invalid or missing credentials |
|
|
566
276
|
| `PaymentRequiredError` | 402 | Credit quota exceeded |
|
|
567
277
|
| `NotFoundError` | 404 | Resource does not exist |
|
|
568
|
-
| `ConflictError` | 409 | Resource in wrong state
|
|
569
|
-
| `ValidationError` | 422 | Invalid
|
|
278
|
+
| `ConflictError` | 409 | Resource in wrong state |
|
|
279
|
+
| `ValidationError` | 422 | Invalid parameters |
|
|
570
280
|
| `RateLimitError` | 429 | Too many requests |
|
|
571
281
|
|
|
572
282
|
---
|
|
@@ -581,29 +291,21 @@ const client = new Oblien({
|
|
|
581
291
|
});
|
|
582
292
|
```
|
|
583
293
|
|
|
584
|
-
|
|
585
|
-
|--------|------|---------|-------------|
|
|
586
|
-
| `clientId` | `string` | -- | Your API client ID |
|
|
587
|
-
| `clientSecret` | `string` | -- | Your API client secret |
|
|
588
|
-
| `baseUrl` | `string` | `https://api.oblien.com` | Control plane API base URL |
|
|
589
|
-
|
|
590
|
-
Get your API keys from the [dashboard](https://oblien.com/dashboard).
|
|
294
|
+
Get your API keys from the [dashboard](https://oblien.com/dashboard/settings).
|
|
591
295
|
|
|
592
296
|
---
|
|
593
297
|
|
|
594
298
|
## TypeScript
|
|
595
299
|
|
|
596
|
-
|
|
300
|
+
Written in TypeScript with full type declarations shipped. All request parameters, response shapes, and event types are exported:
|
|
597
301
|
|
|
598
302
|
```typescript
|
|
599
303
|
import type {
|
|
600
|
-
WorkspaceCreateParams,
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
WSTerminalEvent,
|
|
606
|
-
WSWatcherEvent,
|
|
304
|
+
WorkspaceCreateParams, WorkspaceData,
|
|
305
|
+
PageCreateParams, PageData,
|
|
306
|
+
CheckSlugParams, VerifyDomainParams,
|
|
307
|
+
EdgeProxyCreateParams,
|
|
308
|
+
ExecStreamEvent, WSTerminalEvent,
|
|
607
309
|
} from 'oblien';
|
|
608
310
|
```
|
|
609
311
|
|
|
@@ -620,12 +322,11 @@ import type {
|
|
|
620
322
|
## Links
|
|
621
323
|
|
|
622
324
|
- [Documentation](https://oblien.com/docs)
|
|
623
|
-
- [SDK setup guide](https://oblien.com/docs/workspace/sdk-setup)
|
|
624
325
|
- [Quickstart](https://oblien.com/docs/workspace/quickstart)
|
|
326
|
+
- [SDK setup guide](https://oblien.com/docs/workspace/sdk-setup)
|
|
625
327
|
- [API reference](https://oblien.com/docs/api)
|
|
626
|
-
- [Runtime
|
|
328
|
+
- [Runtime API](https://oblien.com/docs/runtime-api)
|
|
627
329
|
- [Dashboard](https://oblien.com/dashboard)
|
|
628
|
-
- [GitHub](https://github.com/oblien/sdk)
|
|
629
330
|
|
|
630
331
|
---
|
|
631
332
|
|