layero 0.8.2 → 0.8.3
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 +1 -1
- package/dist/commands/deploy.js +56 -27
- package/package.json +2 -7
package/README.md
CHANGED
package/dist/commands/deploy.js
CHANGED
|
@@ -226,21 +226,44 @@ const PREBUILT_AUTO_DIRS = [
|
|
|
226
226
|
async function resolvePrebuiltDir(cwd, raw) {
|
|
227
227
|
if (raw === undefined || raw === false)
|
|
228
228
|
return null;
|
|
229
|
+
let dir = null;
|
|
229
230
|
if (typeof raw === "string" && raw.length > 0) {
|
|
230
|
-
|
|
231
|
+
dir = raw;
|
|
231
232
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
else {
|
|
234
|
+
// No explicit dir — pick the first existing common output directory.
|
|
235
|
+
for (const candidate of PREBUILT_AUTO_DIRS) {
|
|
236
|
+
try {
|
|
237
|
+
const stat = await fs.stat(path.join(cwd, candidate));
|
|
238
|
+
if (stat.isDirectory()) {
|
|
239
|
+
dir = candidate;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// try next
|
|
245
|
+
}
|
|
238
246
|
}
|
|
239
|
-
|
|
240
|
-
|
|
247
|
+
if (dir === null) {
|
|
248
|
+
throw new LayeroError("prebuilt_no_dir", "could not auto-detect a built artifact directory", `pass it explicitly: --prebuilt ./dist (tried: ${PREBUILT_AUTO_DIRS.join(", ")})`);
|
|
241
249
|
}
|
|
242
250
|
}
|
|
243
|
-
|
|
251
|
+
// Servability check (mirrors the builder-side gate, 2026-07-01 audit): a
|
|
252
|
+
// prebuilt dir with no index.html at its root isn't a servable site — the
|
|
253
|
+
// apex "/" would 404. Fail fast here, before packing + uploading, instead of
|
|
254
|
+
// the deploy going "ready" but broken.
|
|
255
|
+
let hasIndex = false;
|
|
256
|
+
try {
|
|
257
|
+
const entries = await fs.readdir(path.join(cwd, dir));
|
|
258
|
+
hasIndex = entries.some((e) => e.toLowerCase() === "index.html");
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
hasIndex = false;
|
|
262
|
+
}
|
|
263
|
+
if (!hasIndex) {
|
|
264
|
+
throw new LayeroError("prebuilt_no_index", `'${dir}' has no index.html — nothing to serve`, `point --prebuilt at the folder that contains your built index.html (e.g. --prebuilt ./dist)`);
|
|
265
|
+
}
|
|
266
|
+
return dir;
|
|
244
267
|
}
|
|
245
268
|
// Resolve the framework / build / output config to send to completeSetup.
|
|
246
269
|
// Precedence: explicit CLI args > .layero/project.json > auto-detect.
|
|
@@ -431,30 +454,36 @@ export async function deployCmd(opts) {
|
|
|
431
454
|
const dashboardUrl = projectUrl(cliCfg.apiUrl, project.id);
|
|
432
455
|
const apexUrl = `https://${project.apex_hostname}`;
|
|
433
456
|
const probe = await resolveReachability(api, deploy.environment_id);
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
//
|
|
439
|
-
//
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
|
|
443
|
-
|
|
457
|
+
// Публичный адрес сайта.
|
|
458
|
+
//
|
|
459
|
+
// Раньше здесь стоял гейт `cdn_ready`: пока YC CDN не подтвердил апекс,
|
|
460
|
+
// отдавали off-CDN превью, потому что свежий апекс 10-15 минут отвечал
|
|
461
|
+
// 404, а runtime-приложения на апексе вообще не принимали POST (CDN резал
|
|
462
|
+
// не-GET). После EDGE-02 CDN перед пользовательскими зонами нет: апекс
|
|
463
|
+
// валиден с момента создания проекта (wildcard-запись + wildcard-серт), а
|
|
464
|
+
// `cdn_ready` бекенд отдаёт false НАВСЕГДА — строки в `cdn_hostnames` у
|
|
465
|
+
// новых проектов не появляется вовсе.
|
|
466
|
+
//
|
|
467
|
+
// Из-за этого условие не выполнялось никогда, и после успешной публикации
|
|
468
|
+
// CLI выдавал ссылку на дашборд вместо адреса сайта. Проверено вживую
|
|
469
|
+
// 2026-07-26: `layero deploy` вернул `url: https://app.layero.ru/projects/…`.
|
|
470
|
+
//
|
|
471
|
+
// Апекс — адрес по умолчанию; превью остаётся для деплоя ветки, которую
|
|
472
|
+
// не промоутили: там апекс ведёт на другую сборку.
|
|
473
|
+
const liveUrl = promoted || !opts.branch
|
|
444
474
|
? probe?.canonical_url ?? apexUrl
|
|
445
|
-
: probe?.preview_url ??
|
|
446
|
-
probe?.canonical_url ??
|
|
447
|
-
(promoted || !opts.branch ? apexUrl : dashboardUrl);
|
|
475
|
+
: probe?.preview_url ?? probe?.canonical_url ?? apexUrl;
|
|
448
476
|
emit({
|
|
449
477
|
event: "ready",
|
|
450
478
|
url: liveUrl,
|
|
451
479
|
deploy_id: deploy.id,
|
|
452
480
|
preview_url: probe?.preview_url ?? undefined,
|
|
453
481
|
dashboard_url: dashboardUrl,
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
482
|
+
// `available` от пробы, а НЕ `cdn_ready`: последний после EDGE-02
|
|
483
|
+
// остаётся false навсегда, и потребитель JSON-вывода ждал бы события,
|
|
484
|
+
// которого не будет. ETA пропагации убран по той же причине —
|
|
485
|
+
// распространять больше нечего.
|
|
486
|
+
edge_ready: probe ? probe.available : undefined,
|
|
458
487
|
});
|
|
459
488
|
}
|
|
460
489
|
finally {
|
package/package.json
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "layero",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Layero CLI — publish a local site with one command. No git, no GitHub, agent-friendly (Cursor, Claude Code).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://layero.ru",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/LayeroInfra/core.git",
|
|
11
|
-
"directory": "cli"
|
|
12
|
-
},
|
|
13
8
|
"bugs": {
|
|
14
|
-
"url": "https://
|
|
9
|
+
"url": "https://docs.layero.ru/contacts/"
|
|
15
10
|
},
|
|
16
11
|
"keywords": [
|
|
17
12
|
"layero",
|