@wix/himalaya-cli 0.880.0 → 0.881.0
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.
|
@@ -39,8 +39,8 @@ export interface WixGetPostRequest {
|
|
|
39
39
|
* request type has no `fieldsets` field, so that fallback path cannot carry the
|
|
40
40
|
* body.
|
|
41
41
|
*
|
|
42
|
-
* When that fallback ALSO finds nothing
|
|
43
|
-
*
|
|
42
|
+
* When that fallback ALSO finds nothing — a deleted post, or one this visitor
|
|
43
|
+
* may not see — we reject rather than resolve. `WixGetPostResponse.post`
|
|
44
44
|
* is non-optional, so returning `{ post: resp.posts?.[0] }` would hand callers an
|
|
45
45
|
* `undefined` the type promises is present, and the `post.title` access that type
|
|
46
46
|
* licenses throws a `TypeError` deep inside the caller — the exact hard error
|
package/dist/cli.mjs
CHANGED
|
@@ -22773,7 +22773,7 @@ var init_app_module = __esm({
|
|
|
22773
22773
|
|
|
22774
22774
|
// ../../core/dev-server/src/app-assets.ts
|
|
22775
22775
|
import { createHash as createHash8 } from "node:crypto";
|
|
22776
|
-
import { existsSync as existsSync27, lstatSync as
|
|
22776
|
+
import { existsSync as existsSync27, lstatSync as lstatSync4, readFileSync as readFileSync29, readdirSync as readdirSync14, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
|
|
22777
22777
|
import { join as join31, resolve as resolve19, sep as sep5 } from "node:path";
|
|
22778
22778
|
function contentTypeFor(name) {
|
|
22779
22779
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
@@ -22851,7 +22851,7 @@ function collectBrandFonts(appDir2) {
|
|
|
22851
22851
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
22852
22852
|
const path = join31(appDir2, rel);
|
|
22853
22853
|
try {
|
|
22854
|
-
if (!
|
|
22854
|
+
if (!lstatSync4(path).isFile()) continue;
|
|
22855
22855
|
const root = realpathSync3(appDir2);
|
|
22856
22856
|
if (!realpathSync3(path).startsWith(root + sep5)) continue;
|
|
22857
22857
|
} catch {
|
|
@@ -46910,13 +46910,13 @@ __export(app_source_exports, {
|
|
|
46910
46910
|
writeConflicts: () => writeConflicts,
|
|
46911
46911
|
zipAppSource: () => zipAppSource
|
|
46912
46912
|
});
|
|
46913
|
-
import { readdirSync as readdirSync21, lstatSync as
|
|
46913
|
+
import { readdirSync as readdirSync21, lstatSync as lstatSync5, readFileSync as readFileSync44, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14, existsSync as existsSync38, rmSync as rmSync6, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
46914
46914
|
import { join as join37, resolve as resolve34, sep as sep7 } from "node:path";
|
|
46915
46915
|
function walkSourceTree(dir, file, skip) {
|
|
46916
46916
|
const walk2 = (relDir) => {
|
|
46917
46917
|
for (const name of readdirSync21(join37(dir, relDir))) {
|
|
46918
46918
|
const rel = relDir ? join37(relDir, name) : name;
|
|
46919
|
-
const st =
|
|
46919
|
+
const st = lstatSync5(join37(dir, rel));
|
|
46920
46920
|
if (st.isSymbolicLink()) {
|
|
46921
46921
|
skip(rel);
|
|
46922
46922
|
continue;
|
|
@@ -46964,7 +46964,7 @@ function readAppSource(zip) {
|
|
|
46964
46964
|
}
|
|
46965
46965
|
function pathKind(p) {
|
|
46966
46966
|
try {
|
|
46967
|
-
return
|
|
46967
|
+
return lstatSync5(p);
|
|
46968
46968
|
} catch {
|
|
46969
46969
|
return null;
|
|
46970
46970
|
}
|
|
@@ -47061,7 +47061,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
47061
47061
|
for (const name of readdirSync21(rel ? join37(root, rel) : root)) {
|
|
47062
47062
|
const childRel = rel ? join37(rel, name) : name;
|
|
47063
47063
|
const posix3 = childRel.split(sep7).join("/");
|
|
47064
|
-
const kind =
|
|
47064
|
+
const kind = lstatSync5(join37(root, childRel));
|
|
47065
47065
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name)) {
|
|
47066
47066
|
empty = false;
|
|
47067
47067
|
continue;
|
|
@@ -51239,8 +51239,9 @@ ${releaseId}`;
|
|
|
51239
51239
|
if (packageShare) {
|
|
51240
51240
|
const shareId = packageShare[1];
|
|
51241
51241
|
const wantsMetadata = url.searchParams.get("metadata") === "1";
|
|
51242
|
+
const wantsDownload = url.searchParams.get("download") === "1";
|
|
51242
51243
|
const wantsHtml = (request.headers.get("accept") ?? "").includes("text/html");
|
|
51243
|
-
if (wantsMetadata || wantsHtml) {
|
|
51244
|
+
if (wantsMetadata || wantsHtml && !wantsDownload) {
|
|
51244
51245
|
const share = await resolvePackageShareMetadata(await getStore(), shareId);
|
|
51245
51246
|
if (!share) return json3(404, { error: "package_share_not_found" });
|
|
51246
51247
|
if (wantsMetadata) return json3(200, share, { "cache-control": "no-store" });
|
|
@@ -59411,7 +59412,7 @@ var init_site_oauth_client = __esm({
|
|
|
59411
59412
|
});
|
|
59412
59413
|
|
|
59413
59414
|
// src/cli.ts
|
|
59414
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync64, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync53, rmSync as rmSync9, readdirSync as readdirSync24, statSync as statSync12, lstatSync as
|
|
59415
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync64, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync53, rmSync as rmSync9, readdirSync as readdirSync24, statSync as statSync12, lstatSync as lstatSync6 } from "node:fs";
|
|
59415
59416
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
59416
59417
|
import { createHash as createHash24 } from "node:crypto";
|
|
59417
59418
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
@@ -59872,6 +59873,7 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
59872
59873
|
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
59873
59874
|
import {
|
|
59874
59875
|
existsSync as existsSync3,
|
|
59876
|
+
lstatSync as lstatSync3,
|
|
59875
59877
|
mkdirSync as mkdirSync5,
|
|
59876
59878
|
realpathSync,
|
|
59877
59879
|
readlinkSync as readlinkSync2,
|
|
@@ -60230,6 +60232,24 @@ if (process.argv[1] && basename(process.argv[1]) === "diff-hash.mjs" && import.m
|
|
|
60230
60232
|
|
|
60231
60233
|
// src/attestation.ts
|
|
60232
60234
|
var DEFAULT_MAX_RUNS = 20;
|
|
60235
|
+
var ATTESTATION_VERSION = 2;
|
|
60236
|
+
function attestationVersionOf(value) {
|
|
60237
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
60238
|
+
const version = value.attestation;
|
|
60239
|
+
return typeof version === "number" && Number.isInteger(version) && version > 0 ? version : null;
|
|
60240
|
+
}
|
|
60241
|
+
function classifyRetainedRun(dir, name) {
|
|
60242
|
+
let value;
|
|
60243
|
+
try {
|
|
60244
|
+
value = JSON.parse(readFileSync5(join6(dir, name), "utf8"));
|
|
60245
|
+
} catch {
|
|
60246
|
+
return { kind: "unreadable" };
|
|
60247
|
+
}
|
|
60248
|
+
if (isAttestationV2(value)) return { kind: "current", run: value };
|
|
60249
|
+
const version = attestationVersionOf(value);
|
|
60250
|
+
if (version === null || version === ATTESTATION_VERSION) return { kind: "malformed" };
|
|
60251
|
+
return { kind: version < ATTESTATION_VERSION ? "legacy" : "future" };
|
|
60252
|
+
}
|
|
60233
60253
|
function screenshotArtifactPath(contentDir2, hash) {
|
|
60234
60254
|
return join6(resolve6(contentDir2), ".himi", "attestations", "artifacts", `${hash}.png`);
|
|
60235
60255
|
}
|
|
@@ -60297,7 +60317,15 @@ function currentGitUntrackedHash(contentDir2) {
|
|
|
60297
60317
|
for (const path of listed.split("\0").filter(Boolean).sort()) {
|
|
60298
60318
|
const local = relative(absolute, join6(root, path));
|
|
60299
60319
|
if (local.split(/[\\/]/)[0] === ".himi") continue;
|
|
60300
|
-
|
|
60320
|
+
const full = join6(root, path);
|
|
60321
|
+
const stats = lstatSync3(full, { throwIfNoEntry: false });
|
|
60322
|
+
if (!stats) continue;
|
|
60323
|
+
const kind = stats.isSymbolicLink() ? "link" : stats.isDirectory() ? "dir" : stats.isFile() ? "file" : null;
|
|
60324
|
+
if (!kind) continue;
|
|
60325
|
+
const payload = kind === "link" ? Buffer.from(readlinkSync2(full)) : kind === "file" ? readFileSync5(full) : Buffer.alloc(0);
|
|
60326
|
+
const pathBytes = Buffer.from(path);
|
|
60327
|
+
hash.update(`${kind} ${pathBytes.length} ${payload.length}
|
|
60328
|
+
`).update(pathBytes).update(payload);
|
|
60301
60329
|
}
|
|
60302
60330
|
return hash.digest("hex");
|
|
60303
60331
|
}
|
|
@@ -60317,17 +60345,17 @@ function sourceTreeHash(root) {
|
|
|
60317
60345
|
return hash.digest("hex");
|
|
60318
60346
|
}
|
|
60319
60347
|
var stringRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((item) => typeof item === "string");
|
|
60320
|
-
function
|
|
60348
|
+
function isAttestationV2(value) {
|
|
60321
60349
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
60322
60350
|
const a = value;
|
|
60323
60351
|
const coverage = a.coverage;
|
|
60324
60352
|
const report = a.report;
|
|
60325
|
-
return a.attestation ===
|
|
60353
|
+
return a.attestation === 2 && typeof a.runId === "string" && ["himi-test", "himi-render", "himi-shots"].includes(a.tool) && [a.app, a.contentDir, a.gitDiffHash, a.gitUntrackedHash, a.releaseId, a.releaseHash, a.selfHash].every((item) => typeof item === "string" && item.length > 0) && stringRecord(a.descriptorHashes) && stringRecord(a.screenshots) && !!coverage && [coverage.screens, coverage.actionsDispatched, coverage.uncoveredFns, coverage.gaps].every((count) => typeof count === "number" && Number.isFinite(count) && count >= 0) && typeof report?.ok === "boolean" && !!report.counts && [report.counts.errors, report.counts.warnings, report.counts.gaps].every((count) => typeof count === "number" && Number.isFinite(count) && count >= 0) && (a.prev === null || typeof a.prev === "string");
|
|
60326
60354
|
}
|
|
60327
60355
|
function readLatestAttestation(contentDir2) {
|
|
60328
60356
|
try {
|
|
60329
60357
|
const parsed = JSON.parse(readFileSync5(join6(resolve6(contentDir2), ".himi", "attestations", "latest.json"), "utf8"));
|
|
60330
|
-
return
|
|
60358
|
+
return isAttestationV2(parsed) ? parsed : null;
|
|
60331
60359
|
} catch {
|
|
60332
60360
|
return null;
|
|
60333
60361
|
}
|
|
@@ -60340,13 +60368,15 @@ function readRetainedAttestations(contentDir2) {
|
|
|
60340
60368
|
const parsedRuns = [];
|
|
60341
60369
|
const errors = [];
|
|
60342
60370
|
for (const name of names) {
|
|
60343
|
-
|
|
60344
|
-
|
|
60345
|
-
|
|
60346
|
-
|
|
60347
|
-
}
|
|
60371
|
+
const classified = classifyRetainedRun(dir, name);
|
|
60372
|
+
if (classified.kind === "current") parsedRuns.push(classified.run);
|
|
60373
|
+
else if (classified.kind === "legacy") {
|
|
60374
|
+
errors.push(`attestation history contains retained run ${name} from an older attestation version \u2014 re-run himi test/render to start a v${ATTESTATION_VERSION} chain`);
|
|
60375
|
+
} else if (classified.kind === "future") {
|
|
60376
|
+
errors.push(`attestation history contains retained run ${name} from a newer attestation version \u2014 upgrade himi rather than deleting it`);
|
|
60377
|
+
} else if (classified.kind === "unreadable") {
|
|
60348
60378
|
errors.push(`attestation history contains unreadable retained run ${name}`);
|
|
60349
|
-
}
|
|
60379
|
+
} else errors.push(`attestation history contains malformed retained run ${name}`);
|
|
60350
60380
|
}
|
|
60351
60381
|
const latest = readLatestAttestation(contentDir2);
|
|
60352
60382
|
if (existsSync3(join6(dir, "latest.json")) && !latest) errors.push("attestation history has no valid latest.json");
|
|
@@ -60430,7 +60460,7 @@ function writeAttestation(input, opts = {}) {
|
|
|
60430
60460
|
if (!existsSync3(artifact)) writeFileSync5(artifact, bytes2);
|
|
60431
60461
|
}
|
|
60432
60462
|
const unsigned = {
|
|
60433
|
-
attestation:
|
|
60463
|
+
attestation: 2,
|
|
60434
60464
|
runId,
|
|
60435
60465
|
tool: input.tool,
|
|
60436
60466
|
app: input.app,
|
|
@@ -60452,16 +60482,20 @@ function writeAttestation(input, opts = {}) {
|
|
|
60452
60482
|
writeFileSync5(join6(dir, runFile), json5);
|
|
60453
60483
|
writeFileSync5(join6(dir, "latest.json"), json5);
|
|
60454
60484
|
const keep = Math.max(1, opts.maxRuns ?? DEFAULT_MAX_RUNS);
|
|
60455
|
-
const
|
|
60485
|
+
const allPriorRuns = readdirSync3(dir).filter((name) => name.endsWith(".json") && name !== "latest.json").filter((name) => name !== runFile).sort().reverse();
|
|
60486
|
+
const priorRuns = allPriorRuns.filter((name) => {
|
|
60487
|
+
const kind = classifyRetainedRun(dir, name).kind;
|
|
60488
|
+
if (kind === "legacy") {
|
|
60489
|
+
unlinkSync(join6(dir, name));
|
|
60490
|
+
return false;
|
|
60491
|
+
}
|
|
60492
|
+
return kind !== "future";
|
|
60493
|
+
});
|
|
60456
60494
|
for (const name of priorRuns.slice(Math.max(0, keep - 1))) unlinkSync(join6(dir, name));
|
|
60457
60495
|
const retainedFiles = readdirSync3(dir).filter((name) => name.endsWith(".json") && name !== "latest.json");
|
|
60458
60496
|
const retainedRuns = retainedFiles.map((name) => {
|
|
60459
|
-
|
|
60460
|
-
|
|
60461
|
-
return isAttestationV1(value) ? value : null;
|
|
60462
|
-
} catch {
|
|
60463
|
-
return null;
|
|
60464
|
-
}
|
|
60497
|
+
const classified = classifyRetainedRun(dir, name);
|
|
60498
|
+
return classified.kind === "current" ? classified.run : null;
|
|
60465
60499
|
});
|
|
60466
60500
|
if (retainedRuns.every((run2) => run2 !== null)) {
|
|
60467
60501
|
const retainedScreenshotHashes = new Set(
|
|
@@ -60485,14 +60519,8 @@ function verifyAttestation(attestation, contentDir2, descriptors, expectedApp, r
|
|
|
60485
60519
|
if (!latest || opts.requireLatest !== false && latest.selfHash !== attestation.selfHash) {
|
|
60486
60520
|
errors.push("attestation does not match latest.json");
|
|
60487
60521
|
} else {
|
|
60488
|
-
const
|
|
60489
|
-
|
|
60490
|
-
const value = JSON.parse(readFileSync5(join6(dir, name), "utf8"));
|
|
60491
|
-
return isAttestationV1(value) ? value : null;
|
|
60492
|
-
} catch {
|
|
60493
|
-
return null;
|
|
60494
|
-
}
|
|
60495
|
-
});
|
|
60522
|
+
const classified = readdirSync3(dir).filter((name) => name.endsWith(".json") && name !== "latest.json").map((name) => classifyRetainedRun(dir, name)).filter((entry) => entry.kind !== "future");
|
|
60523
|
+
const retained = classified.map((entry) => entry.kind === "current" ? entry.run : null);
|
|
60496
60524
|
if (retained.some((run2) => run2 === null)) {
|
|
60497
60525
|
errors.push("attestation history contains a malformed retained run");
|
|
60498
60526
|
} else {
|
|
@@ -63966,7 +63994,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
|
|
|
63966
63994
|
function symlinkDestinationIssue(dest) {
|
|
63967
63995
|
let kind;
|
|
63968
63996
|
try {
|
|
63969
|
-
kind =
|
|
63997
|
+
kind = lstatSync6(dest);
|
|
63970
63998
|
} catch {
|
|
63971
63999
|
return null;
|
|
63972
64000
|
}
|
|
@@ -6590,7 +6590,7 @@
|
|
|
6590
6590
|
{
|
|
6591
6591
|
"name": "getPost",
|
|
6592
6592
|
"kind": "function",
|
|
6593
|
-
"jsdoc": "/** Fetch a single PUBLISHED post by id — GET /blog/v3/posts/{id}. The list\n * (queryPosts) returns published posts, so the detail reads them here (draft\n * ids are a different space — getDraftPost is for the edit/create flow).\n *\n * Body fieldsets (#826): Blog v3 `GET /posts/{id}` returns 200 but only the\n * LIST projection (title / excerpt / meta) unless the caller asks for the body —\n * the bare GET has NO `richContent` / `contentText`. So we request\n * RICH_CONTENT + CONTENT_TEXT by default and the article body loads on the happy\n * path; callers can override via `req.fieldsets`. (Supersedes the old #507 note:\n * the 502 this GET once returned for anonymous visitors is gone — it 200s now —\n * but a body-less 200 was never the \"body preserved whenever the backend is\n * healthy\" the earlier comment claimed; the body was simply never requested.)\n *\n * On any rejection (network / backend error) we still fall back to a queryPosts\n * filter-by-id — a graceful degrade to the LIST projection (no body) that keeps\n * blog detail + saved screens rendering instead of erroring out. `queryPosts`'s\n * request type has no `fieldsets` field, so that fallback path cannot carry the\n * body.\n *\n * When that fallback ALSO finds nothing
|
|
6593
|
+
"jsdoc": "/** Fetch a single PUBLISHED post by id — GET /blog/v3/posts/{id}. The list\n * (queryPosts) returns published posts, so the detail reads them here (draft\n * ids are a different space — getDraftPost is for the edit/create flow).\n *\n * Body fieldsets (#826): Blog v3 `GET /posts/{id}` returns 200 but only the\n * LIST projection (title / excerpt / meta) unless the caller asks for the body —\n * the bare GET has NO `richContent` / `contentText`. So we request\n * RICH_CONTENT + CONTENT_TEXT by default and the article body loads on the happy\n * path; callers can override via `req.fieldsets`. (Supersedes the old #507 note:\n * the 502 this GET once returned for anonymous visitors is gone — it 200s now —\n * but a body-less 200 was never the \"body preserved whenever the backend is\n * healthy\" the earlier comment claimed; the body was simply never requested.)\n *\n * On any rejection (network / backend error) we still fall back to a queryPosts\n * filter-by-id — a graceful degrade to the LIST projection (no body) that keeps\n * blog detail + saved screens rendering instead of erroring out. `queryPosts`'s\n * request type has no `fieldsets` field, so that fallback path cannot carry the\n * body.\n *\n * When that fallback ALSO finds nothing — a deleted post, or one this visitor\n * may not see — we reject rather than resolve. `WixGetPostResponse.post`\n * is non-optional, so returning `{ post: resp.posts?.[0] }` would hand callers an\n * `undefined` the type promises is present, and the `post.title` access that type\n * licenses throws a `TypeError` deep inside the caller — the exact hard error\n * this fallback exists to prevent, and harder to diagnose than a clean rejection.\n * Every call site rides its own rejection path (cached-post state, draft-only\n * `catch`, or an `allSettled` filter), so rejecting is what routes them into the\n * graceful degrade they already implement. The originating failure travels as\n * `cause`, so the 404-vs-network distinction is not lost. */",
|
|
6594
6594
|
"decl": "export function getPost(\n postId: string,\n req: WixGetPostRequest = {},\n): Promise<WixGetPostResponse>;",
|
|
6595
6595
|
"http": "GET /blog/v3/posts/{…}"
|
|
6596
6596
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.881.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"artifactId": "himalaya-cli"
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
|
-
"falconPackageHash": "
|
|
66
|
+
"falconPackageHash": "c4de152d9d84b5fc2a1b6adaa22daab7e0b5e8f4fff6ccc83c1e72a3"
|
|
67
67
|
}
|