@miosa/cli 1.0.86 → 1.0.88
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/dist/commands/sandbox.js
CHANGED
|
@@ -104,8 +104,9 @@ export function register(program) {
|
|
|
104
104
|
console.log(JSON.stringify(data, null, 2));
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
|
-
const
|
|
108
|
-
|
|
107
|
+
const sb = opts.port != null
|
|
108
|
+
? await showSandboxWithPreview(id, opts.port, opts.probePath)
|
|
109
|
+
: (unwrap(await client().apiGet(apiPath(`/sandboxes/${enc(id)}`))) ?? {});
|
|
109
110
|
printBanner({ subtitle: "Sandbox" });
|
|
110
111
|
const rows = [
|
|
111
112
|
{ label: "ID", value: chalk.bold(str(sb["id"])), icon: icon.info },
|
|
@@ -142,6 +143,23 @@ export function register(program) {
|
|
|
142
143
|
value: chalk.cyan(str(sb["public_url"])),
|
|
143
144
|
});
|
|
144
145
|
}
|
|
146
|
+
const preview = asRecord(sb["preview"]);
|
|
147
|
+
if (preview?.["url"]) {
|
|
148
|
+
rows.push({
|
|
149
|
+
label: "Preview URL",
|
|
150
|
+
value: chalk.cyan(str(preview["url"])),
|
|
151
|
+
});
|
|
152
|
+
rows.push({
|
|
153
|
+
label: "URL class",
|
|
154
|
+
value: str(preview["url_class"] ?? "temporary_preview"),
|
|
155
|
+
});
|
|
156
|
+
rows.push({
|
|
157
|
+
label: "Embeddable",
|
|
158
|
+
value: preview["stable_for_embedding"] === true
|
|
159
|
+
? chalk.green("yes")
|
|
160
|
+
: chalk.yellow("temporary"),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
145
163
|
if (sb["created_at"]) {
|
|
146
164
|
rows.push({
|
|
147
165
|
label: "Created",
|
|
@@ -733,6 +751,7 @@ export function register(program) {
|
|
|
733
751
|
return;
|
|
734
752
|
}
|
|
735
753
|
console.log(result.url);
|
|
754
|
+
printPreviewContractHint(result);
|
|
736
755
|
if (!result.ready) {
|
|
737
756
|
console.error(chalk.yellow(`Preview route created but not verified yet (${result.error ?? result.status ?? "pending"}).`));
|
|
738
757
|
}
|
|
@@ -1810,6 +1829,9 @@ async function showSandboxWithPreview(sandboxId, port, probePath) {
|
|
|
1810
1829
|
catch (err) {
|
|
1811
1830
|
preview = {
|
|
1812
1831
|
url: "",
|
|
1832
|
+
url_class: "temporary_preview",
|
|
1833
|
+
stable_for_embedding: false,
|
|
1834
|
+
recommended_next_action: "create_alias_or_publish",
|
|
1813
1835
|
ready: false,
|
|
1814
1836
|
status: null,
|
|
1815
1837
|
latency_ms: null,
|
|
@@ -1822,6 +1844,10 @@ async function showSandboxWithPreview(sandboxId, port, probePath) {
|
|
|
1822
1844
|
preview: {
|
|
1823
1845
|
url: preview?.url || null,
|
|
1824
1846
|
port,
|
|
1847
|
+
url_info: preview?.url_info ?? null,
|
|
1848
|
+
url_class: preview?.url_class ?? "temporary_preview",
|
|
1849
|
+
stable_for_embedding: preview?.stable_for_embedding ?? false,
|
|
1850
|
+
recommended_next_action: preview?.recommended_next_action ?? "create_alias_or_publish",
|
|
1825
1851
|
route_ready: Boolean(preview?.url),
|
|
1826
1852
|
tls_ready: preview?.ready ?? false,
|
|
1827
1853
|
last_status: preview?.status ?? null,
|
|
@@ -1844,12 +1870,28 @@ async function previewSandbox(sandboxId, port, opts) {
|
|
|
1844
1870
|
: await probePublicPreview(url, opts.probePath);
|
|
1845
1871
|
return {
|
|
1846
1872
|
url,
|
|
1873
|
+
url_class: stringField(exposed, "url_class") ??
|
|
1874
|
+
stringField(exposed, "class") ??
|
|
1875
|
+
"temporary_preview",
|
|
1876
|
+
stable_for_embedding: booleanField(exposed, "stable_for_embedding") ?? false,
|
|
1877
|
+
recommended_next_action: stringField(exposed, "recommended_next_action") ??
|
|
1878
|
+
"create_alias_or_publish",
|
|
1879
|
+
url_info: objectField(exposed, "url_info") ?? undefined,
|
|
1847
1880
|
ready: edge.ok,
|
|
1848
1881
|
status: edge.status,
|
|
1849
1882
|
latency_ms: edge.latency_ms ?? null,
|
|
1850
1883
|
error: edge.error,
|
|
1851
1884
|
};
|
|
1852
1885
|
}
|
|
1886
|
+
function printPreviewContractHint(result) {
|
|
1887
|
+
const urlClass = result.url_class ?? "temporary_preview";
|
|
1888
|
+
if (result.stable_for_embedding === true) {
|
|
1889
|
+
console.error(chalk.dim(`URL class: ${urlClass}, stable for embedding.`));
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
console.error(chalk.yellow(`URL class: ${urlClass}, temporary preview.`));
|
|
1893
|
+
console.error(chalk.dim(`For durable client use, next action: ${result.recommended_next_action ?? "create_alias_or_publish"}.`));
|
|
1894
|
+
}
|
|
1853
1895
|
async function waitSandboxReady(sandboxId, port, probePath, timeoutSec) {
|
|
1854
1896
|
const c = client();
|
|
1855
1897
|
await waitForSandboxRunning(c, sandboxId, Math.min(timeoutSec, 120));
|
|
@@ -2006,10 +2048,18 @@ async function deploySandbox(localDir, opts) {
|
|
|
2006
2048
|
const internal = await waitForInternalHttp(c, sandboxId, resolvedPort, resolvedProbePath, Math.min(opts.timeout, 60));
|
|
2007
2049
|
deployStep(opts, "Creating public preview route");
|
|
2008
2050
|
const exposed = await c.apiPost(apiPath(`/sandboxes/${enc(sandboxId)}/expose`), { port: resolvedPort, title: "app preview" });
|
|
2009
|
-
const
|
|
2051
|
+
const exposeData = unwrap(exposed);
|
|
2052
|
+
const previewUrl = extractUrl(exposeData);
|
|
2010
2053
|
if (!previewUrl) {
|
|
2011
2054
|
throw new UserError("Sandbox expose did not return a preview URL.");
|
|
2012
2055
|
}
|
|
2056
|
+
const previewUrlInfo = objectField(exposeData, "url_info") ?? undefined;
|
|
2057
|
+
const previewUrlClass = stringField(exposeData, "url_class") ??
|
|
2058
|
+
stringField(exposeData, "class") ??
|
|
2059
|
+
"temporary_preview";
|
|
2060
|
+
const stableForEmbedding = booleanField(exposeData, "stable_for_embedding") ?? false;
|
|
2061
|
+
const recommendedNextAction = stringField(exposeData, "recommended_next_action") ??
|
|
2062
|
+
"create_alias_or_publish";
|
|
2013
2063
|
if (opts.wait)
|
|
2014
2064
|
deployStep(opts, "Checking public preview readiness");
|
|
2015
2065
|
const edge = opts.wait
|
|
@@ -2037,6 +2087,10 @@ async function deploySandbox(localDir, opts) {
|
|
|
2037
2087
|
sandbox_id: sandboxId,
|
|
2038
2088
|
port: resolvedPort,
|
|
2039
2089
|
preview_url: previewUrl,
|
|
2090
|
+
preview_url_info: previewUrlInfo,
|
|
2091
|
+
preview_url_class: previewUrlClass,
|
|
2092
|
+
stable_for_embedding: stableForEmbedding,
|
|
2093
|
+
recommended_next_action: recommendedNextAction,
|
|
2040
2094
|
preview_ready: edge.ok,
|
|
2041
2095
|
persistent: true,
|
|
2042
2096
|
always_on: Boolean(opts.alwaysOn),
|
|
@@ -2149,6 +2203,25 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
2149
2203
|
extractUrl(deployment) ??
|
|
2150
2204
|
stringField(data, "url") ??
|
|
2151
2205
|
null;
|
|
2206
|
+
let urlInfo = objectField(response, "url_info") ??
|
|
2207
|
+
objectField(deployment, "url_info") ??
|
|
2208
|
+
objectField(data, "url_info") ??
|
|
2209
|
+
null;
|
|
2210
|
+
let urlClass = stringField(response, "url_class") ??
|
|
2211
|
+
stringField(response, "class") ??
|
|
2212
|
+
stringField(deployment, "url_class") ??
|
|
2213
|
+
stringField(deployment, "class") ??
|
|
2214
|
+
stringField(data, "url_class") ??
|
|
2215
|
+
stringField(data, "class") ??
|
|
2216
|
+
"durable_deployment";
|
|
2217
|
+
let stableForEmbedding = booleanField(response, "stable_for_embedding") ??
|
|
2218
|
+
booleanField(deployment, "stable_for_embedding") ??
|
|
2219
|
+
booleanField(data, "stable_for_embedding") ??
|
|
2220
|
+
true;
|
|
2221
|
+
let recommendedNextAction = stringField(response, "recommended_next_action") ??
|
|
2222
|
+
stringField(deployment, "recommended_next_action") ??
|
|
2223
|
+
stringField(data, "recommended_next_action") ??
|
|
2224
|
+
"attach_custom_domain";
|
|
2152
2225
|
let deploymentProduct = stringField(response, "deployment_product") ??
|
|
2153
2226
|
stringField(data, "deployment_product") ??
|
|
2154
2227
|
stringField(deployment, "deployment_product") ??
|
|
@@ -2164,6 +2237,15 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
2164
2237
|
const waited = await waitForDeploymentReady(c, deploymentId, opts.timeout);
|
|
2165
2238
|
state = stringField(waited, "state") ?? state;
|
|
2166
2239
|
url = extractUrl(waited) ?? url;
|
|
2240
|
+
urlInfo = objectField(waited, "url_info") ?? urlInfo;
|
|
2241
|
+
urlClass =
|
|
2242
|
+
stringField(waited, "url_class") ??
|
|
2243
|
+
stringField(waited, "class") ??
|
|
2244
|
+
urlClass;
|
|
2245
|
+
stableForEmbedding =
|
|
2246
|
+
booleanField(waited, "stable_for_embedding") ?? stableForEmbedding;
|
|
2247
|
+
recommendedNextAction =
|
|
2248
|
+
stringField(waited, "recommended_next_action") ?? recommendedNextAction;
|
|
2167
2249
|
deploymentProduct =
|
|
2168
2250
|
stringField(waited, "deployment_product") ??
|
|
2169
2251
|
stringField(asRecord(waited["metadata"]), "deployment_product") ??
|
|
@@ -2175,6 +2257,11 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
2175
2257
|
response["state"] = state;
|
|
2176
2258
|
if (url)
|
|
2177
2259
|
response["url"] = url;
|
|
2260
|
+
if (urlInfo)
|
|
2261
|
+
response["url_info"] = urlInfo;
|
|
2262
|
+
response["url_class"] = urlClass;
|
|
2263
|
+
response["stable_for_embedding"] = stableForEmbedding;
|
|
2264
|
+
response["recommended_next_action"] = recommendedNextAction;
|
|
2178
2265
|
data["deployment"] = waited;
|
|
2179
2266
|
data["promotion_pending"] = false;
|
|
2180
2267
|
data["app_consistency_pending"] = false;
|
|
@@ -2196,6 +2283,10 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
2196
2283
|
release_id: releaseId,
|
|
2197
2284
|
version_id: versionId,
|
|
2198
2285
|
url,
|
|
2286
|
+
url_info: urlInfo ?? undefined,
|
|
2287
|
+
url_class: urlClass,
|
|
2288
|
+
stable_for_embedding: stableForEmbedding,
|
|
2289
|
+
recommended_next_action: recommendedNextAction,
|
|
2199
2290
|
state,
|
|
2200
2291
|
deployment_product: deploymentProduct,
|
|
2201
2292
|
docker_deploy_host_id: dockerDeployHostId,
|
|
@@ -2220,7 +2311,7 @@ async function waitForDeploymentReady(c, deploymentId, timeoutSec) {
|
|
|
2220
2311
|
await sleep(2000);
|
|
2221
2312
|
}
|
|
2222
2313
|
const lastState = last ? String(last["state"] ?? "unknown") : "unknown";
|
|
2223
|
-
throw new UserError(`Deployment still building after ${timeoutSec}s — it may still finish. Re-check with \`miosa
|
|
2314
|
+
throw new UserError(`Deployment still building after ${timeoutSec}s — it may still finish. Re-check with \`miosa deploy show ${deploymentId}\` or \`miosa deploy logs ${deploymentId}\`.`, `Last state: ${lastState}`);
|
|
2224
2315
|
}
|
|
2225
2316
|
function parsePublishDatabase(value) {
|
|
2226
2317
|
if (!value)
|
|
@@ -2258,6 +2349,12 @@ async function doctorSandbox(sandboxId, port, probePath) {
|
|
|
2258
2349
|
exposeData = { error: err instanceof Error ? err.message : String(err) };
|
|
2259
2350
|
}
|
|
2260
2351
|
const previewUrl = extractUrl(exposeData);
|
|
2352
|
+
const urlClass = stringField(exposeData, "url_class") ??
|
|
2353
|
+
stringField(exposeData, "class") ??
|
|
2354
|
+
"temporary_preview";
|
|
2355
|
+
const stableForEmbedding = booleanField(exposeData, "stable_for_embedding") ?? false;
|
|
2356
|
+
const recommendedNextAction = stringField(exposeData, "recommended_next_action") ??
|
|
2357
|
+
"create_alias_or_publish";
|
|
2261
2358
|
const edge = previewUrl
|
|
2262
2359
|
? await probePublicPreview(previewUrl, probePath)
|
|
2263
2360
|
: { ok: false, status: null, error: "No preview URL returned" };
|
|
@@ -2275,6 +2372,10 @@ async function doctorSandbox(sandboxId, port, probePath) {
|
|
|
2275
2372
|
edge_probe: edge,
|
|
2276
2373
|
preview_ready: edge.ok,
|
|
2277
2374
|
preview_url: previewUrl,
|
|
2375
|
+
url_info: objectField(exposeData, "url_info") ?? null,
|
|
2376
|
+
url_class: urlClass,
|
|
2377
|
+
stable_for_embedding: stableForEmbedding,
|
|
2378
|
+
recommended_next_action: recommendedNextAction,
|
|
2278
2379
|
expose: exposeData,
|
|
2279
2380
|
};
|
|
2280
2381
|
}
|
|
@@ -2290,6 +2391,8 @@ function renderDoctorReport(report) {
|
|
|
2290
2391
|
console.log(` ${chalk.bold("Preview ready")} ${report["preview_ready"] ? chalk.green("yes") : chalk.red("no")}`);
|
|
2291
2392
|
if (report["preview_url"]) {
|
|
2292
2393
|
console.log(` ${chalk.bold("Preview URL")} ${chalk.cyan(String(report["preview_url"]))}`);
|
|
2394
|
+
console.log(` ${chalk.bold("URL class")} ${report["url_class"]}`);
|
|
2395
|
+
console.log(` ${chalk.bold("Embeddable")} ${report["stable_for_embedding"] === true ? chalk.green("yes") : chalk.yellow("temporary")}`);
|
|
2293
2396
|
}
|
|
2294
2397
|
console.log();
|
|
2295
2398
|
if (!report["preview_ready"]) {
|
|
@@ -3146,6 +3249,13 @@ function stringField(row, key) {
|
|
|
3146
3249
|
const value = row?.[key];
|
|
3147
3250
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
3148
3251
|
}
|
|
3252
|
+
function booleanField(row, key) {
|
|
3253
|
+
const value = row?.[key];
|
|
3254
|
+
return typeof value === "boolean" ? value : null;
|
|
3255
|
+
}
|
|
3256
|
+
function objectField(row, key) {
|
|
3257
|
+
return asRecord(row?.[key]);
|
|
3258
|
+
}
|
|
3149
3259
|
function isSandboxTarget(value) {
|
|
3150
3260
|
const idx = value.indexOf(":");
|
|
3151
3261
|
if (idx <= 0)
|