@wix/himalaya-cli 0.879.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
|
@@ -5241,6 +5241,7 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
5241
5241
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
5242
5242
|
var init_bindings = __esm({
|
|
5243
5243
|
"../../core/ts/src/bindings.ts"() {
|
|
5244
|
+
"use strict";
|
|
5244
5245
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
5245
5246
|
BINDING_SIGIL_RE = new RegExp(
|
|
5246
5247
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -22772,7 +22773,7 @@ var init_app_module = __esm({
|
|
|
22772
22773
|
|
|
22773
22774
|
// ../../core/dev-server/src/app-assets.ts
|
|
22774
22775
|
import { createHash as createHash8 } from "node:crypto";
|
|
22775
|
-
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";
|
|
22776
22777
|
import { join as join31, resolve as resolve19, sep as sep5 } from "node:path";
|
|
22777
22778
|
function contentTypeFor(name) {
|
|
22778
22779
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
@@ -22850,7 +22851,7 @@ function collectBrandFonts(appDir2) {
|
|
|
22850
22851
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
22851
22852
|
const path = join31(appDir2, rel);
|
|
22852
22853
|
try {
|
|
22853
|
-
if (!
|
|
22854
|
+
if (!lstatSync4(path).isFile()) continue;
|
|
22854
22855
|
const root = realpathSync3(appDir2);
|
|
22855
22856
|
if (!realpathSync3(path).startsWith(root + sep5)) continue;
|
|
22856
22857
|
} catch {
|
|
@@ -46909,13 +46910,13 @@ __export(app_source_exports, {
|
|
|
46909
46910
|
writeConflicts: () => writeConflicts,
|
|
46910
46911
|
zipAppSource: () => zipAppSource
|
|
46911
46912
|
});
|
|
46912
|
-
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";
|
|
46913
46914
|
import { join as join37, resolve as resolve34, sep as sep7 } from "node:path";
|
|
46914
46915
|
function walkSourceTree(dir, file, skip) {
|
|
46915
46916
|
const walk2 = (relDir) => {
|
|
46916
46917
|
for (const name of readdirSync21(join37(dir, relDir))) {
|
|
46917
46918
|
const rel = relDir ? join37(relDir, name) : name;
|
|
46918
|
-
const st =
|
|
46919
|
+
const st = lstatSync5(join37(dir, rel));
|
|
46919
46920
|
if (st.isSymbolicLink()) {
|
|
46920
46921
|
skip(rel);
|
|
46921
46922
|
continue;
|
|
@@ -46963,7 +46964,7 @@ function readAppSource(zip) {
|
|
|
46963
46964
|
}
|
|
46964
46965
|
function pathKind(p) {
|
|
46965
46966
|
try {
|
|
46966
|
-
return
|
|
46967
|
+
return lstatSync5(p);
|
|
46967
46968
|
} catch {
|
|
46968
46969
|
return null;
|
|
46969
46970
|
}
|
|
@@ -47060,7 +47061,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
47060
47061
|
for (const name of readdirSync21(rel ? join37(root, rel) : root)) {
|
|
47061
47062
|
const childRel = rel ? join37(rel, name) : name;
|
|
47062
47063
|
const posix3 = childRel.split(sep7).join("/");
|
|
47063
|
-
const kind =
|
|
47064
|
+
const kind = lstatSync5(join37(root, childRel));
|
|
47064
47065
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name)) {
|
|
47065
47066
|
empty = false;
|
|
47066
47067
|
continue;
|
|
@@ -51238,8 +51239,9 @@ ${releaseId}`;
|
|
|
51238
51239
|
if (packageShare) {
|
|
51239
51240
|
const shareId = packageShare[1];
|
|
51240
51241
|
const wantsMetadata = url.searchParams.get("metadata") === "1";
|
|
51242
|
+
const wantsDownload = url.searchParams.get("download") === "1";
|
|
51241
51243
|
const wantsHtml = (request.headers.get("accept") ?? "").includes("text/html");
|
|
51242
|
-
if (wantsMetadata || wantsHtml) {
|
|
51244
|
+
if (wantsMetadata || wantsHtml && !wantsDownload) {
|
|
51243
51245
|
const share = await resolvePackageShareMetadata(await getStore(), shareId);
|
|
51244
51246
|
if (!share) return json3(404, { error: "package_share_not_found" });
|
|
51245
51247
|
if (wantsMetadata) return json3(200, share, { "cache-control": "no-store" });
|
|
@@ -59410,7 +59412,7 @@ var init_site_oauth_client = __esm({
|
|
|
59410
59412
|
});
|
|
59411
59413
|
|
|
59412
59414
|
// src/cli.ts
|
|
59413
|
-
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";
|
|
59414
59416
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
59415
59417
|
import { createHash as createHash24 } from "node:crypto";
|
|
59416
59418
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
@@ -59871,6 +59873,7 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
59871
59873
|
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
59872
59874
|
import {
|
|
59873
59875
|
existsSync as existsSync3,
|
|
59876
|
+
lstatSync as lstatSync3,
|
|
59874
59877
|
mkdirSync as mkdirSync5,
|
|
59875
59878
|
realpathSync,
|
|
59876
59879
|
readlinkSync as readlinkSync2,
|
|
@@ -60229,6 +60232,24 @@ if (process.argv[1] && basename(process.argv[1]) === "diff-hash.mjs" && import.m
|
|
|
60229
60232
|
|
|
60230
60233
|
// src/attestation.ts
|
|
60231
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
|
+
}
|
|
60232
60253
|
function screenshotArtifactPath(contentDir2, hash) {
|
|
60233
60254
|
return join6(resolve6(contentDir2), ".himi", "attestations", "artifacts", `${hash}.png`);
|
|
60234
60255
|
}
|
|
@@ -60296,7 +60317,15 @@ function currentGitUntrackedHash(contentDir2) {
|
|
|
60296
60317
|
for (const path of listed.split("\0").filter(Boolean).sort()) {
|
|
60297
60318
|
const local = relative(absolute, join6(root, path));
|
|
60298
60319
|
if (local.split(/[\\/]/)[0] === ".himi") continue;
|
|
60299
|
-
|
|
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);
|
|
60300
60329
|
}
|
|
60301
60330
|
return hash.digest("hex");
|
|
60302
60331
|
}
|
|
@@ -60316,17 +60345,17 @@ function sourceTreeHash(root) {
|
|
|
60316
60345
|
return hash.digest("hex");
|
|
60317
60346
|
}
|
|
60318
60347
|
var stringRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((item) => typeof item === "string");
|
|
60319
|
-
function
|
|
60348
|
+
function isAttestationV2(value) {
|
|
60320
60349
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
60321
60350
|
const a = value;
|
|
60322
60351
|
const coverage = a.coverage;
|
|
60323
60352
|
const report = a.report;
|
|
60324
|
-
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");
|
|
60325
60354
|
}
|
|
60326
60355
|
function readLatestAttestation(contentDir2) {
|
|
60327
60356
|
try {
|
|
60328
60357
|
const parsed = JSON.parse(readFileSync5(join6(resolve6(contentDir2), ".himi", "attestations", "latest.json"), "utf8"));
|
|
60329
|
-
return
|
|
60358
|
+
return isAttestationV2(parsed) ? parsed : null;
|
|
60330
60359
|
} catch {
|
|
60331
60360
|
return null;
|
|
60332
60361
|
}
|
|
@@ -60339,13 +60368,15 @@ function readRetainedAttestations(contentDir2) {
|
|
|
60339
60368
|
const parsedRuns = [];
|
|
60340
60369
|
const errors = [];
|
|
60341
60370
|
for (const name of names) {
|
|
60342
|
-
|
|
60343
|
-
|
|
60344
|
-
|
|
60345
|
-
|
|
60346
|
-
}
|
|
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") {
|
|
60347
60378
|
errors.push(`attestation history contains unreadable retained run ${name}`);
|
|
60348
|
-
}
|
|
60379
|
+
} else errors.push(`attestation history contains malformed retained run ${name}`);
|
|
60349
60380
|
}
|
|
60350
60381
|
const latest = readLatestAttestation(contentDir2);
|
|
60351
60382
|
if (existsSync3(join6(dir, "latest.json")) && !latest) errors.push("attestation history has no valid latest.json");
|
|
@@ -60429,7 +60460,7 @@ function writeAttestation(input, opts = {}) {
|
|
|
60429
60460
|
if (!existsSync3(artifact)) writeFileSync5(artifact, bytes2);
|
|
60430
60461
|
}
|
|
60431
60462
|
const unsigned = {
|
|
60432
|
-
attestation:
|
|
60463
|
+
attestation: 2,
|
|
60433
60464
|
runId,
|
|
60434
60465
|
tool: input.tool,
|
|
60435
60466
|
app: input.app,
|
|
@@ -60451,16 +60482,20 @@ function writeAttestation(input, opts = {}) {
|
|
|
60451
60482
|
writeFileSync5(join6(dir, runFile), json5);
|
|
60452
60483
|
writeFileSync5(join6(dir, "latest.json"), json5);
|
|
60453
60484
|
const keep = Math.max(1, opts.maxRuns ?? DEFAULT_MAX_RUNS);
|
|
60454
|
-
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
|
+
});
|
|
60455
60494
|
for (const name of priorRuns.slice(Math.max(0, keep - 1))) unlinkSync(join6(dir, name));
|
|
60456
60495
|
const retainedFiles = readdirSync3(dir).filter((name) => name.endsWith(".json") && name !== "latest.json");
|
|
60457
60496
|
const retainedRuns = retainedFiles.map((name) => {
|
|
60458
|
-
|
|
60459
|
-
|
|
60460
|
-
return isAttestationV1(value) ? value : null;
|
|
60461
|
-
} catch {
|
|
60462
|
-
return null;
|
|
60463
|
-
}
|
|
60497
|
+
const classified = classifyRetainedRun(dir, name);
|
|
60498
|
+
return classified.kind === "current" ? classified.run : null;
|
|
60464
60499
|
});
|
|
60465
60500
|
if (retainedRuns.every((run2) => run2 !== null)) {
|
|
60466
60501
|
const retainedScreenshotHashes = new Set(
|
|
@@ -60484,14 +60519,8 @@ function verifyAttestation(attestation, contentDir2, descriptors, expectedApp, r
|
|
|
60484
60519
|
if (!latest || opts.requireLatest !== false && latest.selfHash !== attestation.selfHash) {
|
|
60485
60520
|
errors.push("attestation does not match latest.json");
|
|
60486
60521
|
} else {
|
|
60487
|
-
const
|
|
60488
|
-
|
|
60489
|
-
const value = JSON.parse(readFileSync5(join6(dir, name), "utf8"));
|
|
60490
|
-
return isAttestationV1(value) ? value : null;
|
|
60491
|
-
} catch {
|
|
60492
|
-
return null;
|
|
60493
|
-
}
|
|
60494
|
-
});
|
|
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);
|
|
60495
60524
|
if (retained.some((run2) => run2 === null)) {
|
|
60496
60525
|
errors.push("attestation history contains a malformed retained run");
|
|
60497
60526
|
} else {
|
|
@@ -63965,7 +63994,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
|
|
|
63965
63994
|
function symlinkDestinationIssue(dest) {
|
|
63966
63995
|
let kind;
|
|
63967
63996
|
try {
|
|
63968
|
-
kind =
|
|
63997
|
+
kind = lstatSync6(dest);
|
|
63969
63998
|
} catch {
|
|
63970
63999
|
return null;
|
|
63971
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
|
}
|