@miosa/sdk 1.2.3 → 1.2.5
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 +63 -39
- package/dist/index.d.ts +201 -182
- package/dist/index.js +433 -309
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +5 -5
- package/src/index.ts +16 -11
- package/src/resources/admin.ts +0 -11
- package/src/resources/api-keys.ts +0 -16
- package/src/resources/custom_domains.ts +1 -1
- package/src/resources/deployments.test.ts +127 -51
- package/src/resources/deployments.ts +326 -125
- package/src/resources/devices.test.ts +92 -0
- package/src/resources/devices.ts +291 -0
- package/src/resources/sandboxes.test.ts +2 -0
- package/src/resources/sandboxes.ts +4 -0
- package/src/resources/tenant.ts +19 -101
- package/src/resources/webhooks.ts +54 -39
- package/src/types.ts +5 -5
- package/src/resources/docker-deploy.test.ts +0 -102
- package/src/resources/docker-deploy.ts +0 -183
- package/src/resources/governance.test.ts +0 -355
- package/src/resources/governance.ts +0 -528
- package/src/resources/phase1.test.ts +0 -187
- package/src/resources/quotas.ts +0 -77
- package/src/resources/sandbox-processes.ts +0 -112
- package/src/resources/sandbox-shares.ts +0 -83
- package/src/resources/tenant-events.ts +0 -32
- package/src/resources/workspaces.ts +0 -285
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { CronJobs } from "./resources/cron-jobs.js";
|
|
|
15
15
|
import { Dashboard } from "./resources/dashboard.js";
|
|
16
16
|
import { Databases } from "./resources/databases.js";
|
|
17
17
|
import { Deployments } from "./resources/deployments.js";
|
|
18
|
-
import {
|
|
18
|
+
import { Devices } from "./resources/devices.js";
|
|
19
19
|
import { EgressAudit } from "./resources/egressAudit.js";
|
|
20
20
|
import { EgressNetwork } from "./resources/egressNetwork.js";
|
|
21
21
|
import { EgressSecrets } from "./resources/egressSecrets.js";
|
|
@@ -125,15 +125,15 @@ export class Miosa {
|
|
|
125
125
|
/** Sandboxes — native code-execution environments under `/sandboxes`. */
|
|
126
126
|
readonly sandboxes: Sandboxes;
|
|
127
127
|
|
|
128
|
+
/** Agent device facade — route work across Sandboxes, Computers, and deploy hosts. */
|
|
129
|
+
readonly devices: Devices;
|
|
130
|
+
|
|
128
131
|
/**
|
|
129
132
|
* Deployments — publish from a sandbox to a stable production URL.
|
|
130
133
|
* Versions, releases, rollback, custom domains.
|
|
131
134
|
*/
|
|
132
135
|
readonly deployments: Deployments;
|
|
133
136
|
|
|
134
|
-
/** Docker Deploy appliance hosts — one always-on workspace host, many apps. */
|
|
135
|
-
readonly dockerDeploy: DockerDeploy;
|
|
136
|
-
|
|
137
137
|
/** Credit balance and usage. */
|
|
138
138
|
readonly credits: Credits;
|
|
139
139
|
|
|
@@ -260,8 +260,8 @@ export class Miosa {
|
|
|
260
260
|
this.mcp = new Mcp(this.http);
|
|
261
261
|
this.computers = new Computers(this.http);
|
|
262
262
|
this.sandboxes = new Sandboxes(this.http);
|
|
263
|
+
this.devices = new Devices(this.http);
|
|
263
264
|
this.deployments = new Deployments(this.http);
|
|
264
|
-
this.dockerDeploy = new DockerDeploy(this.http);
|
|
265
265
|
this.credits = new Credits(this.http);
|
|
266
266
|
this.admin = new Admin(this.http);
|
|
267
267
|
this.openComputers = new OpenComputers(this.http);
|
package/src/index.ts
CHANGED
|
@@ -67,6 +67,16 @@ export type {
|
|
|
67
67
|
// Resource classes (useful for isinstance checks and extension)
|
|
68
68
|
export { Computer, ScopedFs } from "./resources/computer.js";
|
|
69
69
|
export { Computers } from "./resources/computers.js";
|
|
70
|
+
export { Devices } from "./resources/devices.js";
|
|
71
|
+
export type {
|
|
72
|
+
DeviceCatalogEntry,
|
|
73
|
+
DeviceKind,
|
|
74
|
+
DeviceListError,
|
|
75
|
+
DeviceListParams,
|
|
76
|
+
DeviceListResponse,
|
|
77
|
+
DeviceRecord,
|
|
78
|
+
DeviceSource,
|
|
79
|
+
} from "./resources/devices.js";
|
|
70
80
|
export { Desktop } from "./resources/desktop.js";
|
|
71
81
|
export { Exec } from "./resources/exec.js";
|
|
72
82
|
export { Files } from "./resources/files.js";
|
|
@@ -135,11 +145,17 @@ export type {
|
|
|
135
145
|
DeploymentVersionId,
|
|
136
146
|
DeploymentVersionKind,
|
|
137
147
|
DeploymentVersionState,
|
|
148
|
+
DockerDeployDesignReferencePreset,
|
|
138
149
|
DockerDeployCreateParams,
|
|
139
150
|
DockerDeployDoctorCheck,
|
|
140
151
|
DockerDeployDoctorParams,
|
|
141
152
|
DockerDeployDoctorProbe,
|
|
142
153
|
DockerDeployDoctorResult,
|
|
154
|
+
DockerDeployTemplateData,
|
|
155
|
+
DockerDeployTemplateListParams,
|
|
156
|
+
DockerDeployHostData,
|
|
157
|
+
DockerDeployHostEnsureParams,
|
|
158
|
+
DockerDeployHostListParams,
|
|
143
159
|
ExternalAttribution,
|
|
144
160
|
PublishFromSandboxParams,
|
|
145
161
|
PublishParams,
|
|
@@ -151,17 +167,6 @@ export type {
|
|
|
151
167
|
RuntimeLogsResult,
|
|
152
168
|
VersionListParams,
|
|
153
169
|
} from "./resources/deployments.js";
|
|
154
|
-
export { DockerDeploy } from "./resources/docker-deploy.js";
|
|
155
|
-
export type {
|
|
156
|
-
DockerDeployApplianceStatus,
|
|
157
|
-
DockerDeployHostData,
|
|
158
|
-
DockerDeployHostEnsureParams,
|
|
159
|
-
DockerDeployHostId,
|
|
160
|
-
DockerDeployHostListParams,
|
|
161
|
-
DockerDeployHostListResponse,
|
|
162
|
-
DockerDeployHostResponse,
|
|
163
|
-
DockerDeployHostStatus,
|
|
164
|
-
} from "./resources/docker-deploy.js";
|
|
165
170
|
export type {
|
|
166
171
|
SnapshotData,
|
|
167
172
|
SnapshotStatus,
|
package/src/resources/admin.ts
CHANGED
|
@@ -345,15 +345,4 @@ export class Admin {
|
|
|
345
345
|
model_id: modelId,
|
|
346
346
|
});
|
|
347
347
|
}
|
|
348
|
-
|
|
349
|
-
/** POST /api/v1/admin/impersonate — returns {token, expires_at}. */
|
|
350
|
-
impersonate(
|
|
351
|
-
externalUserId: string,
|
|
352
|
-
options: { ttlSec?: number } = {},
|
|
353
|
-
): Promise<{ token: string; expires_at: string }> {
|
|
354
|
-
return this.http.post("/admin/impersonate", {
|
|
355
|
-
external_user_id: externalUserId,
|
|
356
|
-
ttl_sec: options.ttlSec ?? 3600,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
348
|
}
|
|
@@ -113,22 +113,6 @@ export class ApiKeys {
|
|
|
113
113
|
return unwrap<ApiKeyCreateResult>(data);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
/** POST /api/v1/api-keys/scoped — L2 delegation token bound to one external user. */
|
|
117
|
-
async createScoped(params: {
|
|
118
|
-
externalUserId: string;
|
|
119
|
-
scopes: string[];
|
|
120
|
-
expiresAt?: string;
|
|
121
|
-
}): Promise<ApiKeyCreateResult> {
|
|
122
|
-
const body = stripUndefined({
|
|
123
|
-
external_user_id: params.externalUserId,
|
|
124
|
-
scopes: params.scopes,
|
|
125
|
-
expires_at: params.expiresAt,
|
|
126
|
-
});
|
|
127
|
-
return unwrap<ApiKeyCreateResult>(
|
|
128
|
-
await this.http.post<unknown>("/api-keys/scoped", body),
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
116
|
async delete(keyId: string): Promise<void> {
|
|
133
117
|
await this.http.delete<unknown>(`/api-keys/${keyId}`);
|
|
134
118
|
}
|
|
@@ -41,7 +41,7 @@ export interface CustomDomainRegisterParams {
|
|
|
41
41
|
* // 1. Register the domain
|
|
42
42
|
* const domain = await computer.domains.register("app.example.com");
|
|
43
43
|
* console.log(domain.instructions);
|
|
44
|
-
* // => "Add a CNAME record: app.example.com → <slug>.sandbox
|
|
44
|
+
* // => "Add a CNAME record: app.example.com → <slug>.sandbox.<tenant-domain>"
|
|
45
45
|
*
|
|
46
46
|
* // 2. Add the CNAME in your DNS registrar, then...
|
|
47
47
|
*
|
|
@@ -14,7 +14,6 @@ function makeHttp(): HttpClient {
|
|
|
14
14
|
|
|
15
15
|
beforeEach(() => {
|
|
16
16
|
vi.clearAllMocks();
|
|
17
|
-
vi.unstubAllGlobals();
|
|
18
17
|
});
|
|
19
18
|
|
|
20
19
|
describe("Deployments", () => {
|
|
@@ -56,66 +55,143 @@ describe("Deployments", () => {
|
|
|
56
55
|
expect(deployment.docker_deploy_host_id).toBe("ddh_123");
|
|
57
56
|
});
|
|
58
57
|
|
|
59
|
-
it("
|
|
60
|
-
mockGet.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
id: "
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (path === "/docker-deploy/hosts/ddh_123") {
|
|
81
|
-
return {
|
|
82
|
-
data: {
|
|
83
|
-
id: "ddh_123",
|
|
84
|
-
tenant_id: "ten_123",
|
|
85
|
-
workspace_id: "ws_123",
|
|
86
|
-
status: "active",
|
|
87
|
-
size: "medium",
|
|
88
|
-
region: "us",
|
|
89
|
-
appliance_status: "healthy",
|
|
58
|
+
it("lists Docker Deploy templates", async () => {
|
|
59
|
+
mockGet.mockResolvedValue({
|
|
60
|
+
data: {
|
|
61
|
+
templates: [
|
|
62
|
+
{
|
|
63
|
+
id: "nextjs-app",
|
|
64
|
+
name: "Next.js App",
|
|
65
|
+
runtime: "node",
|
|
66
|
+
framework: "nextjs",
|
|
67
|
+
design_md: "# Design",
|
|
68
|
+
design_reference_presets: [
|
|
69
|
+
{
|
|
70
|
+
id: "fintech-control",
|
|
71
|
+
name: "Fintech Control",
|
|
72
|
+
summary: "Metrics-heavy finance app.",
|
|
73
|
+
best_for: ["billing portals"],
|
|
74
|
+
},
|
|
75
|
+
],
|
|
90
76
|
},
|
|
91
|
-
|
|
92
|
-
}
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const templates = await new Deployments(
|
|
82
|
+
makeHttp(),
|
|
83
|
+
).listDockerDeployTemplates({
|
|
84
|
+
framework: "nextjs",
|
|
85
|
+
includePreview: true,
|
|
86
|
+
});
|
|
93
87
|
|
|
94
|
-
|
|
88
|
+
expect(mockGet).toHaveBeenCalledWith("/docker-deploy/templates", {
|
|
89
|
+
framework: "nextjs",
|
|
90
|
+
include_preview: true,
|
|
95
91
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
expect(templates[0]?.id).toBe("nextjs-app");
|
|
93
|
+
expect(templates[0]?.design_reference_presets?.[0]?.id).toBe(
|
|
94
|
+
"fintech-control",
|
|
99
95
|
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("gets one Docker Deploy template", async () => {
|
|
99
|
+
mockGet.mockResolvedValue({
|
|
100
|
+
data: {
|
|
101
|
+
id: "compose-full-stack",
|
|
102
|
+
name: "Compose Full Stack",
|
|
103
|
+
runtime: "docker-compose",
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const template = await new Deployments(makeHttp()).getDockerDeployTemplate(
|
|
108
|
+
"compose-full-stack",
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(mockGet).toHaveBeenCalledWith(
|
|
112
|
+
"/docker-deploy/templates/compose-full-stack",
|
|
113
|
+
);
|
|
114
|
+
expect(template.runtime).toBe("docker-compose");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("doctorDockerDeploy() proves appliance metadata and public URL", async () => {
|
|
118
|
+
mockGet
|
|
119
|
+
.mockResolvedValueOnce({
|
|
120
|
+
data: {
|
|
121
|
+
id: "dep_123",
|
|
122
|
+
tenant_id: "ten_123",
|
|
123
|
+
name: "Clinic Intake",
|
|
124
|
+
slug: "clinic-intake",
|
|
125
|
+
state: "running",
|
|
126
|
+
deployment_product: "docker_deploy",
|
|
127
|
+
docker_deploy_host_id: "ddh_123",
|
|
128
|
+
public_url: "https://clinic.osa.miosa.app",
|
|
129
|
+
metadata: {
|
|
130
|
+
deployment_product: "docker_deploy",
|
|
131
|
+
runtime: { ip: "172.16.74.246", port: 23906 },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
.mockResolvedValueOnce({
|
|
136
|
+
data: {
|
|
137
|
+
id: "ddh_123",
|
|
138
|
+
status: "active",
|
|
139
|
+
appliance_status: "healthy",
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
const fetchImpl = vi.fn().mockResolvedValue({
|
|
143
|
+
ok: true,
|
|
144
|
+
status: 200,
|
|
145
|
+
text: async () => JSON.stringify({ ok: true, product: "clinic" }),
|
|
146
|
+
});
|
|
100
147
|
|
|
101
148
|
const result = await new Deployments(makeHttp()).doctorDockerDeploy(
|
|
102
149
|
"dep_123",
|
|
103
|
-
{ probePath: "/health" },
|
|
150
|
+
{ probePath: "/health", fetchImpl },
|
|
104
151
|
);
|
|
105
152
|
|
|
153
|
+
expect(mockGet).toHaveBeenNthCalledWith(1, "/deployments/dep_123");
|
|
154
|
+
expect(mockGet).toHaveBeenNthCalledWith(2, "/docker-deploy/hosts/ddh_123");
|
|
155
|
+
expect(fetchImpl).toHaveBeenCalledWith(
|
|
156
|
+
"https://clinic.osa.miosa.app/health",
|
|
157
|
+
expect.objectContaining({ headers: { Accept: "*/*" } }),
|
|
158
|
+
);
|
|
106
159
|
expect(result.ok).toBe(true);
|
|
107
|
-
expect(
|
|
108
|
-
expect(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
160
|
+
expect(result.host?.id).toBe("ddh_123");
|
|
161
|
+
expect(result.probe?.status).toBe(200);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("doctorDockerDeploy() flags gateway JSON as not the user app", async () => {
|
|
165
|
+
mockGet
|
|
166
|
+
.mockResolvedValueOnce({
|
|
167
|
+
data: {
|
|
168
|
+
id: "dep_123",
|
|
169
|
+
tenant_id: "ten_123",
|
|
170
|
+
name: "Clinic Intake",
|
|
171
|
+
slug: "clinic-intake",
|
|
172
|
+
state: "running",
|
|
173
|
+
deployment_product: "docker_deploy",
|
|
174
|
+
docker_deploy_host_id: "ddh_123",
|
|
175
|
+
public_url: "https://clinic.osa.miosa.app",
|
|
176
|
+
metadata: { runtime: { ip: "172.16.74.246", port: 23906 } },
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
.mockResolvedValueOnce({ data: { id: "ddh_123", status: "active" } });
|
|
180
|
+
const fetchImpl = vi.fn().mockResolvedValue({
|
|
181
|
+
ok: true,
|
|
182
|
+
status: 200,
|
|
183
|
+
text: async () => JSON.stringify({ ok: true, run_id: "ciq-123" }),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const result = await new Deployments(makeHttp()).doctorDockerDeploy(
|
|
187
|
+
"dep_123",
|
|
188
|
+
{ fetchImpl },
|
|
112
189
|
);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"
|
|
118
|
-
|
|
119
|
-
]);
|
|
190
|
+
|
|
191
|
+
expect(result.ok).toBe(false);
|
|
192
|
+
expect(result.probe?.gatewayJson).toBe(true);
|
|
193
|
+
expect(
|
|
194
|
+
result.checks.find((check) => check.name === "public_url_probe")?.message,
|
|
195
|
+
).toContain("gateway JSON");
|
|
120
196
|
});
|
|
121
197
|
});
|