@wix/himalaya-cli 0.1432.0 → 0.1433.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.
- package/dist/cli.mjs +856 -417
- package/guides/base44-app-to-himi-app.md +75 -29
- package/guides/base44-entities.md +0 -1
- package/guides/himi-json-output.md +18 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -842,37 +842,37 @@ var init_file_store = __esm({
|
|
|
842
842
|
mkdirSync2(this.appDir(app), { recursive: true });
|
|
843
843
|
writeFileSync2(join2(this.appDir(app), "release-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
844
844
|
}
|
|
845
|
-
async putScreen(app, screenId,
|
|
845
|
+
async putScreen(app, screenId, json8) {
|
|
846
846
|
const dir = join2(this.appDir(app), "screens");
|
|
847
847
|
mkdirSync2(dir, { recursive: true });
|
|
848
|
-
writeFileSync2(join2(dir, `${this.safe(screenId)}.json`),
|
|
848
|
+
writeFileSync2(join2(dir, `${this.safe(screenId)}.json`), json8);
|
|
849
849
|
}
|
|
850
|
-
async putBundle(app,
|
|
850
|
+
async putBundle(app, sha2567, bytes2) {
|
|
851
851
|
const dir = join2(this.appDir(app), "bundles");
|
|
852
852
|
mkdirSync2(dir, { recursive: true });
|
|
853
|
-
writeFileSync2(join2(dir, `${this.safe(
|
|
853
|
+
writeFileSync2(join2(dir, `${this.safe(sha2567)}.bundle.js`), bytes2);
|
|
854
854
|
}
|
|
855
|
-
async putTokens(app,
|
|
855
|
+
async putTokens(app, json8) {
|
|
856
856
|
mkdirSync2(this.appDir(app), { recursive: true });
|
|
857
|
-
writeFileSync2(join2(this.appDir(app), "tokens.json"),
|
|
857
|
+
writeFileSync2(join2(this.appDir(app), "tokens.json"), json8);
|
|
858
858
|
}
|
|
859
|
-
async putDoc(app,
|
|
859
|
+
async putDoc(app, sha2567, json8) {
|
|
860
860
|
const dir = join2(this.appDir(app), "docs");
|
|
861
861
|
mkdirSync2(dir, { recursive: true });
|
|
862
|
-
writeFileSync2(join2(dir, `${this.safe(
|
|
862
|
+
writeFileSync2(join2(dir, `${this.safe(sha2567)}.json`), json8);
|
|
863
863
|
}
|
|
864
|
-
async putAppConfig(app,
|
|
864
|
+
async putAppConfig(app, json8) {
|
|
865
865
|
mkdirSync2(this.appDir(app), { recursive: true });
|
|
866
|
-
writeFileSync2(join2(this.appDir(app), "app-config.json"),
|
|
866
|
+
writeFileSync2(join2(this.appDir(app), "app-config.json"), json8);
|
|
867
867
|
}
|
|
868
868
|
async putIcon(app, bytes2) {
|
|
869
869
|
mkdirSync2(this.appDir(app), { recursive: true });
|
|
870
870
|
writeFileSync2(join2(this.appDir(app), "icon.png"), bytes2);
|
|
871
871
|
}
|
|
872
|
-
async putWidget(app, widgetId,
|
|
872
|
+
async putWidget(app, widgetId, json8) {
|
|
873
873
|
const dir = join2(this.appDir(app), "widgets");
|
|
874
874
|
mkdirSync2(dir, { recursive: true });
|
|
875
|
-
writeFileSync2(join2(dir, `${this.safe(widgetId)}.json`),
|
|
875
|
+
writeFileSync2(join2(dir, `${this.safe(widgetId)}.json`), json8);
|
|
876
876
|
}
|
|
877
877
|
// Per-app settings (registry visibility) — release-independent, so it lives beside the
|
|
878
878
|
// manifest, not inside it. NOTE: listApps() keys on release-manifest.json/ledger presence,
|
|
@@ -883,16 +883,16 @@ var init_file_store = __esm({
|
|
|
883
883
|
}
|
|
884
884
|
// Template scaffold source archive — a content-addressed JSON doc, so it rides the same
|
|
885
885
|
// docs/ slot as putDoc (retention via retainedReleaseRefs.docs, which includes sourceHash).
|
|
886
|
-
async putSource(app,
|
|
887
|
-
return this.putDoc(app,
|
|
886
|
+
async putSource(app, sha2567, json8) {
|
|
887
|
+
return this.putDoc(app, sha2567, json8);
|
|
888
888
|
}
|
|
889
889
|
// App-owned resources. Stored EXTENSIONLESS under assets/<sha> — the content-type lives
|
|
890
890
|
// on the manifest record, so the bytes on disk carry no format assumption (unlike
|
|
891
891
|
// bundles/<sha>.bundle.js, which bakes ".bundle.js" into the filename).
|
|
892
|
-
async putAsset(app,
|
|
892
|
+
async putAsset(app, sha2567, bytes2) {
|
|
893
893
|
const dir = join2(this.appDir(app), "assets");
|
|
894
894
|
mkdirSync2(dir, { recursive: true });
|
|
895
|
-
writeFileSync2(join2(dir, this.safe(
|
|
895
|
+
writeFileSync2(join2(dir, this.safe(sha2567)), bytes2);
|
|
896
896
|
}
|
|
897
897
|
async getManifest(app) {
|
|
898
898
|
try {
|
|
@@ -911,8 +911,8 @@ var init_file_store = __esm({
|
|
|
911
911
|
async getScreen(app, screenId) {
|
|
912
912
|
return this.read(app, "screens", `${this.safe(screenId)}.json`);
|
|
913
913
|
}
|
|
914
|
-
async getBundle(app,
|
|
915
|
-
return this.read(app, "bundles", `${this.safe(
|
|
914
|
+
async getBundle(app, sha2567) {
|
|
915
|
+
return this.read(app, "bundles", `${this.safe(sha2567)}.bundle.js`);
|
|
916
916
|
}
|
|
917
917
|
async getTokens(app) {
|
|
918
918
|
return this.read(app, "tokens.json");
|
|
@@ -923,8 +923,8 @@ var init_file_store = __esm({
|
|
|
923
923
|
async getIcon(app) {
|
|
924
924
|
return this.read(app, "icon.png");
|
|
925
925
|
}
|
|
926
|
-
async getDoc(app,
|
|
927
|
-
return this.read(app, "docs", `${this.safe(
|
|
926
|
+
async getDoc(app, sha2567) {
|
|
927
|
+
return this.read(app, "docs", `${this.safe(sha2567)}.json`);
|
|
928
928
|
}
|
|
929
929
|
async getWidget(app, widgetId) {
|
|
930
930
|
return this.read(app, "widgets", `${this.safe(widgetId)}.json`);
|
|
@@ -938,11 +938,11 @@ var init_file_store = __esm({
|
|
|
938
938
|
return null;
|
|
939
939
|
}
|
|
940
940
|
}
|
|
941
|
-
async getSource(app,
|
|
942
|
-
return this.getDoc(app,
|
|
941
|
+
async getSource(app, sha2567) {
|
|
942
|
+
return this.getDoc(app, sha2567);
|
|
943
943
|
}
|
|
944
|
-
async getAsset(app,
|
|
945
|
-
return this.read(app, "assets", this.safe(
|
|
944
|
+
async getAsset(app, sha2567) {
|
|
945
|
+
return this.read(app, "assets", this.safe(sha2567));
|
|
946
946
|
}
|
|
947
947
|
async listApps() {
|
|
948
948
|
try {
|
|
@@ -1010,11 +1010,11 @@ var init_file_store = __esm({
|
|
|
1010
1010
|
writeFileSync2(join2(this.appDir(app), "_wip.json"), JSON.stringify(next, null, 2));
|
|
1011
1011
|
return true;
|
|
1012
1012
|
}
|
|
1013
|
-
bundleUrl(_app,
|
|
1014
|
-
return `/v1/bundles/${
|
|
1013
|
+
bundleUrl(_app, sha2567) {
|
|
1014
|
+
return `/v1/bundles/${sha2567}.bundle.js`;
|
|
1015
1015
|
}
|
|
1016
|
-
assetUrl(_app,
|
|
1017
|
-
return `/v1/asset/${
|
|
1016
|
+
assetUrl(_app, sha2567) {
|
|
1017
|
+
return `/v1/asset/${sha2567}`;
|
|
1018
1018
|
}
|
|
1019
1019
|
async prune(app, keepReleaseIds) {
|
|
1020
1020
|
const manifest = await this.getManifest(app);
|
|
@@ -3135,10 +3135,10 @@ function writeAttestation(input, opts = {}) {
|
|
|
3135
3135
|
};
|
|
3136
3136
|
const attestation = { ...unsigned, selfHash: "" };
|
|
3137
3137
|
attestation.selfHash = selfHashFor(attestation);
|
|
3138
|
-
const
|
|
3138
|
+
const json8 = JSON.stringify(attestation, null, 2) + "\n";
|
|
3139
3139
|
const runFile = `${runId.replace(/:/g, "-")}.json`;
|
|
3140
|
-
writeFileSync5(join6(dir, runFile),
|
|
3141
|
-
writeFileSync5(join6(dir, "latest.json"),
|
|
3140
|
+
writeFileSync5(join6(dir, runFile), json8);
|
|
3141
|
+
writeFileSync5(join6(dir, "latest.json"), json8);
|
|
3142
3142
|
const keep = Math.max(1, opts.maxRuns ?? DEFAULT_MAX_RUNS);
|
|
3143
3143
|
const allPriorRuns = readdirSync3(dir).filter((name) => name.endsWith(".json") && name !== "latest.json").filter((name) => name !== runFile).sort().reverse();
|
|
3144
3144
|
const priorRuns = allPriorRuns.filter((name) => {
|
|
@@ -5893,10 +5893,10 @@ function decodeCatalogEnvelope(value) {
|
|
|
5893
5893
|
const envelope = value;
|
|
5894
5894
|
if (!envelope || envelope.encoding !== "gzip-base64" || typeof envelope.data !== "string" || typeof envelope.sha256 !== "string")
|
|
5895
5895
|
throw new Error("Unsupported HHP catalog encoding; regenerate the catalog.");
|
|
5896
|
-
const
|
|
5897
|
-
if (createHash5("sha256").update(
|
|
5896
|
+
const json8 = gunzipSync(Buffer.from(envelope.data, "base64"), { maxOutputLength: 2 * 1024 * 1024 }).toString("utf8");
|
|
5897
|
+
if (createHash5("sha256").update(json8).digest("hex") !== envelope.sha256)
|
|
5898
5898
|
throw new Error("HHP catalog integrity check failed; regenerate the catalog.");
|
|
5899
|
-
return JSON.parse(
|
|
5899
|
+
return JSON.parse(json8);
|
|
5900
5900
|
}
|
|
5901
5901
|
var init_catalog_envelope = __esm({
|
|
5902
5902
|
"../html-to-t5/src/v2/catalog-envelope.ts"() {
|
|
@@ -10359,16 +10359,16 @@ function utf8Length(s2, cap) {
|
|
|
10359
10359
|
}
|
|
10360
10360
|
return n2;
|
|
10361
10361
|
}
|
|
10362
|
-
function repairLoneSurrogateEscapes(
|
|
10363
|
-
if (!
|
|
10362
|
+
function repairLoneSurrogateEscapes(json8) {
|
|
10363
|
+
if (!json8.includes("\\u")) return json8;
|
|
10364
10364
|
const hexAt = (i2) => {
|
|
10365
|
-
const h2 =
|
|
10365
|
+
const h2 = json8.slice(i2, i2 + 4);
|
|
10366
10366
|
return /^[0-9A-Fa-f]{4}$/.test(h2) ? parseInt(h2, 16) : -1;
|
|
10367
10367
|
};
|
|
10368
10368
|
let out2 = "";
|
|
10369
10369
|
let inString = false;
|
|
10370
|
-
for (let i2 = 0; i2 <
|
|
10371
|
-
const c2 =
|
|
10370
|
+
for (let i2 = 0; i2 < json8.length; i2++) {
|
|
10371
|
+
const c2 = json8[i2];
|
|
10372
10372
|
if (!inString) {
|
|
10373
10373
|
if (c2 === '"') inString = true;
|
|
10374
10374
|
out2 += c2;
|
|
@@ -10379,11 +10379,11 @@ function repairLoneSurrogateEscapes(json7) {
|
|
|
10379
10379
|
out2 += c2;
|
|
10380
10380
|
continue;
|
|
10381
10381
|
}
|
|
10382
|
-
if (c2 !== "\\" || i2 + 1 >=
|
|
10382
|
+
if (c2 !== "\\" || i2 + 1 >= json8.length) {
|
|
10383
10383
|
out2 += c2;
|
|
10384
10384
|
continue;
|
|
10385
10385
|
}
|
|
10386
|
-
const e2 =
|
|
10386
|
+
const e2 = json8[i2 + 1];
|
|
10387
10387
|
const v2 = e2 === "u" ? hexAt(i2 + 2) : -1;
|
|
10388
10388
|
if (v2 < 0) {
|
|
10389
10389
|
out2 += c2 + e2;
|
|
@@ -10391,9 +10391,9 @@ function repairLoneSurrogateEscapes(json7) {
|
|
|
10391
10391
|
continue;
|
|
10392
10392
|
}
|
|
10393
10393
|
if (v2 >= 55296 && v2 <= 56319) {
|
|
10394
|
-
const low =
|
|
10394
|
+
const low = json8[i2 + 6] === "\\" && json8[i2 + 7] === "u" ? hexAt(i2 + 8) : -1;
|
|
10395
10395
|
if (low >= 56320 && low <= 57343) {
|
|
10396
|
-
out2 +=
|
|
10396
|
+
out2 += json8.slice(i2, i2 + 12);
|
|
10397
10397
|
i2 += 11;
|
|
10398
10398
|
continue;
|
|
10399
10399
|
}
|
|
@@ -10406,7 +10406,7 @@ function repairLoneSurrogateEscapes(json7) {
|
|
|
10406
10406
|
i2 += 5;
|
|
10407
10407
|
continue;
|
|
10408
10408
|
}
|
|
10409
|
-
out2 +=
|
|
10409
|
+
out2 += json8.slice(i2, i2 + 6);
|
|
10410
10410
|
i2 += 5;
|
|
10411
10411
|
}
|
|
10412
10412
|
return out2;
|
|
@@ -10425,12 +10425,12 @@ function measure(nodes, limits) {
|
|
|
10425
10425
|
}
|
|
10426
10426
|
return count2 > limits.maxNodes ? "too_many_nodes" : null;
|
|
10427
10427
|
}
|
|
10428
|
-
function layoutRichContent(
|
|
10429
|
-
if (
|
|
10430
|
-
if (utf8Length(
|
|
10428
|
+
function layoutRichContent(json8, limits = RICH_CONTENT_LIMITS2) {
|
|
10429
|
+
if (json8 === "") return { blocks: [] };
|
|
10430
|
+
if (utf8Length(json8, limits.maxBytes) > limits.maxBytes) return { rejected: "too_large" };
|
|
10431
10431
|
let parsed;
|
|
10432
10432
|
try {
|
|
10433
|
-
parsed = JSON.parse(repairLoneSurrogateEscapes(
|
|
10433
|
+
parsed = JSON.parse(repairLoneSurrogateEscapes(json8));
|
|
10434
10434
|
} catch {
|
|
10435
10435
|
return { rejected: "invalid_json" };
|
|
10436
10436
|
}
|
|
@@ -11051,14 +11051,14 @@ function resolveActionEvaluator(explicit) {
|
|
|
11051
11051
|
}
|
|
11052
11052
|
function responseBytes(value) {
|
|
11053
11053
|
try {
|
|
11054
|
-
const
|
|
11055
|
-
if (typeof
|
|
11054
|
+
const json8 = JSON.stringify(value);
|
|
11055
|
+
if (typeof json8 !== "string") return 0;
|
|
11056
11056
|
const envelope = JSON.stringify({
|
|
11057
11057
|
protocol: "himi.t5.frame/1",
|
|
11058
11058
|
type: "bridge",
|
|
11059
|
-
payload: { op: "wix_result", id: "k000000", ok: true, payload:
|
|
11059
|
+
payload: { op: "wix_result", id: "k000000", ok: true, payload: json8 }
|
|
11060
11060
|
});
|
|
11061
|
-
return typeof envelope === "string" ? utf8Budget(envelope) : utf8Budget(
|
|
11061
|
+
return typeof envelope === "string" ? utf8Budget(envelope) : utf8Budget(json8);
|
|
11062
11062
|
} catch {
|
|
11063
11063
|
return 0;
|
|
11064
11064
|
}
|
|
@@ -16474,8 +16474,8 @@ __export(quickjs_evaluator_exports, {
|
|
|
16474
16474
|
uninstallQuickJsBootEvaluator: () => uninstallQuickJsBootEvaluator
|
|
16475
16475
|
});
|
|
16476
16476
|
function inputJson(input) {
|
|
16477
|
-
const
|
|
16478
|
-
return
|
|
16477
|
+
const json8 = JSON.stringify(input ?? {});
|
|
16478
|
+
return json8 === void 0 ? "{}" : json8;
|
|
16479
16479
|
}
|
|
16480
16480
|
function timerGlobals(hide, live3) {
|
|
16481
16481
|
const hidden = new Set(hide ?? []);
|
|
@@ -19721,22 +19721,22 @@ import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
|
19721
19721
|
function hasVendoredFloor() {
|
|
19722
19722
|
return existsSync24(VENDORED_DIR);
|
|
19723
19723
|
}
|
|
19724
|
-
function faceSource(file2,
|
|
19724
|
+
function faceSource(file2, sha2567) {
|
|
19725
19725
|
const vendored = join24(VENDORED_DIR, basename8(file2));
|
|
19726
|
-
if (existsSync24(vendored) && createHash9("sha256").update(readFileSync23(vendored)).digest("hex") ===
|
|
19726
|
+
if (existsSync24(vendored) && createHash9("sha256").update(readFileSync23(vendored)).digest("hex") === sha2567) {
|
|
19727
19727
|
return vendored;
|
|
19728
19728
|
}
|
|
19729
|
-
const cached3 = join24(CACHE_DIR,
|
|
19729
|
+
const cached3 = join24(CACHE_DIR, sha2567);
|
|
19730
19730
|
if (existsSync24(cached3)) return cached3;
|
|
19731
19731
|
return null;
|
|
19732
19732
|
}
|
|
19733
19733
|
function upstreamFaceUrl(ref, dir, file2) {
|
|
19734
19734
|
return `${RAW}/google/fonts/${ref}/${dir}/${encodeURIComponent(file2)}`;
|
|
19735
19735
|
}
|
|
19736
|
-
function faceUpstream(
|
|
19736
|
+
function faceUpstream(sha2567, catalog3 = loadCatalog()) {
|
|
19737
19737
|
for (const [name, fam] of Object.entries(catalog3.families)) {
|
|
19738
19738
|
if (!fam.dir || !UPSTREAM_DIR.test(fam.dir)) continue;
|
|
19739
|
-
const face = fam.faces.find((f2) => f2.sha256 ===
|
|
19739
|
+
const face = fam.faces.find((f2) => f2.sha256 === sha2567);
|
|
19740
19740
|
if (face) return { family: name, url: upstreamFaceUrl(catalog3.source.ref, fam.dir, face.file) };
|
|
19741
19741
|
}
|
|
19742
19742
|
return null;
|
|
@@ -19783,7 +19783,7 @@ async function ensureFaceBytes(face, opts = {}) {
|
|
|
19783
19783
|
});
|
|
19784
19784
|
return result;
|
|
19785
19785
|
}
|
|
19786
|
-
async function fetchVerifyAndCache(url,
|
|
19786
|
+
async function fetchVerifyAndCache(url, sha2567, fetcher) {
|
|
19787
19787
|
let bytes2;
|
|
19788
19788
|
try {
|
|
19789
19789
|
bytes2 = Buffer.from(await fetcher(url));
|
|
@@ -19791,10 +19791,10 @@ async function fetchVerifyAndCache(url, sha2566, fetcher) {
|
|
|
19791
19791
|
return { ok: false, reason: `fetching ${url} failed: ${err.message}` };
|
|
19792
19792
|
}
|
|
19793
19793
|
const got = sha256Hex3(bytes2);
|
|
19794
|
-
if (got !==
|
|
19794
|
+
if (got !== sha2567) {
|
|
19795
19795
|
return {
|
|
19796
19796
|
ok: false,
|
|
19797
|
-
reason: `${url} returned bytes hashing to ${got.slice(0, 12)}\u2026, but the catalog pins ${
|
|
19797
|
+
reason: `${url} returned bytes hashing to ${got.slice(0, 12)}\u2026, but the catalog pins ${sha2567.slice(0, 12)}\u2026 \u2014 refused`
|
|
19798
19798
|
};
|
|
19799
19799
|
}
|
|
19800
19800
|
try {
|
|
@@ -19836,10 +19836,10 @@ async function offRepoFontBytes(plan, opts = {}) {
|
|
|
19836
19836
|
}
|
|
19837
19837
|
return out2;
|
|
19838
19838
|
}
|
|
19839
|
-
async function catalogFaceBytes(
|
|
19839
|
+
async function catalogFaceBytes(sha2567, opts = {}) {
|
|
19840
19840
|
const catalog3 = opts.catalog ?? loadCatalog();
|
|
19841
19841
|
for (const family of [...Object.values(catalog3.families), ...Object.values(catalog3.bundled)]) {
|
|
19842
|
-
const face = family.faces.find((f2) => f2.sha256 ===
|
|
19842
|
+
const face = family.faces.find((f2) => f2.sha256 === sha2567);
|
|
19843
19843
|
if (!face) continue;
|
|
19844
19844
|
if (hasVendoredFloor()) {
|
|
19845
19845
|
const local = faceSource(face.file, face.sha256);
|
|
@@ -25408,14 +25408,14 @@ function isSymlink(file2) {
|
|
|
25408
25408
|
function archiveBytes(dir, bytes2) {
|
|
25409
25409
|
const ext = imageExtension(bytes2);
|
|
25410
25410
|
if (!ext) return null;
|
|
25411
|
-
const
|
|
25412
|
-
const rel = join36(HISTORY_DIR, `${
|
|
25411
|
+
const sha2567 = createHash12("sha256").update(bytes2).digest("hex");
|
|
25412
|
+
const rel = join36(HISTORY_DIR, `${sha2567}.${ext}`);
|
|
25413
25413
|
const dest = join36(dir, rel);
|
|
25414
25414
|
if (!realDirIn(dir, HISTORY_DIR)) throw new UnsafeHimiDirError(HISTORY_DIR);
|
|
25415
25415
|
if (!existsSync35(dest)) {
|
|
25416
25416
|
writeFileAtomic(dest, bytes2);
|
|
25417
25417
|
}
|
|
25418
|
-
return { sha256:
|
|
25418
|
+
return { sha256: sha2567, ext, file: toPosix(rel) };
|
|
25419
25419
|
}
|
|
25420
25420
|
function appendProgress(dir, input) {
|
|
25421
25421
|
const message = input.message.trim();
|
|
@@ -26241,15 +26241,15 @@ function himiPluginManifest() {
|
|
|
26241
26241
|
};
|
|
26242
26242
|
}
|
|
26243
26243
|
function himiPluginFiles(skillMd) {
|
|
26244
|
-
const
|
|
26244
|
+
const json8 = (o2) => `${JSON.stringify(o2, null, 2)}
|
|
26245
26245
|
`;
|
|
26246
26246
|
return [
|
|
26247
|
-
{ path: ".claude-plugin/plugin.json", text:
|
|
26248
|
-
{ path: ".mcp.json", text:
|
|
26247
|
+
{ path: ".claude-plugin/plugin.json", text: json8(himiPluginManifest()) },
|
|
26248
|
+
{ path: ".mcp.json", text: json8({ mcpServers: { [HIMI_PLUGIN_NAME]: { command: HIMI_MCP_SERVER.command, args: [...HIMI_MCP_SERVER.args] } } }) },
|
|
26249
26249
|
{ path: "skills/himalaya/SKILL.md", text: skillMd }
|
|
26250
26250
|
];
|
|
26251
26251
|
}
|
|
26252
|
-
function himiMarketplace(archiveUrl,
|
|
26252
|
+
function himiMarketplace(archiveUrl, sha2567) {
|
|
26253
26253
|
return {
|
|
26254
26254
|
name: HIMI_MARKETPLACE_NAME,
|
|
26255
26255
|
description: "Wix native app building for Claude Code",
|
|
@@ -26258,7 +26258,7 @@ function himiMarketplace(archiveUrl, sha2566) {
|
|
|
26258
26258
|
{
|
|
26259
26259
|
name: HIMI_PLUGIN_NAME,
|
|
26260
26260
|
description: HIMI_PLUGIN_DESCRIPTION,
|
|
26261
|
-
source: { source: "archive", url: archiveUrl, ...
|
|
26261
|
+
source: { source: "archive", url: archiveUrl, ...sha2567 ? { sha256: sha2567 } : {} }
|
|
26262
26262
|
}
|
|
26263
26263
|
]
|
|
26264
26264
|
};
|
|
@@ -26273,19 +26273,19 @@ function connectorPluginManifest() {
|
|
|
26273
26273
|
};
|
|
26274
26274
|
}
|
|
26275
26275
|
function connectorPluginFiles(mcpUrl, skillMd) {
|
|
26276
|
-
const
|
|
26276
|
+
const json8 = (o2) => `${JSON.stringify(o2, null, 2)}
|
|
26277
26277
|
`;
|
|
26278
26278
|
return [
|
|
26279
|
-
{ path: ".claude-plugin/plugin.json", text:
|
|
26280
|
-
{ path: ".mcp.json", text:
|
|
26279
|
+
{ path: ".claude-plugin/plugin.json", text: json8(connectorPluginManifest()) },
|
|
26280
|
+
{ path: ".mcp.json", text: json8({ mcpServers: { [CONNECTOR_PLUGIN_NAME]: { type: "http", url: mcpUrl } } }) },
|
|
26281
26281
|
{ path: `skills/${CONNECTOR_PLUGIN_NAME}/SKILL.md`, text: skillMd }
|
|
26282
26282
|
];
|
|
26283
26283
|
}
|
|
26284
|
-
function connectorMarketplaceEntry(archiveUrl,
|
|
26284
|
+
function connectorMarketplaceEntry(archiveUrl, sha2567) {
|
|
26285
26285
|
return {
|
|
26286
26286
|
name: CONNECTOR_PLUGIN_NAME,
|
|
26287
26287
|
description: CONNECTOR_PLUGIN_DESCRIPTION,
|
|
26288
|
-
source: { source: "archive", url: archiveUrl, ...
|
|
26288
|
+
source: { source: "archive", url: archiveUrl, ...sha2567 ? { sha256: sha2567 } : {} }
|
|
26289
26289
|
};
|
|
26290
26290
|
}
|
|
26291
26291
|
function storeZip(files) {
|
|
@@ -27173,9 +27173,9 @@ function inferScreenDisplayName(screenId) {
|
|
|
27173
27173
|
const words = (opaque ? id.slice(0, opaque.index) : id).replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[_\/\s-]+/).filter(Boolean).map((word) => /^(cms|faq|api|ai|id|url)$/i.test(word) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
27174
27174
|
return `${words || screenId}${opaque ? ` (${opaque[1]})` : ""}`;
|
|
27175
27175
|
}
|
|
27176
|
-
function screenDisplayName(screenId,
|
|
27176
|
+
function screenDisplayName(screenId, displayName3, title, navigationLabel) {
|
|
27177
27177
|
const literal = (value) => typeof value === "string" && !!value.trim() && !value.trim().startsWith("$") && !/^__[A-Z0-9_]+__$/.test(value.trim());
|
|
27178
|
-
if (literal(
|
|
27178
|
+
if (literal(displayName3)) return displayName3.trim();
|
|
27179
27179
|
if (literal(title) && title.trim() !== screenId) return title.trim();
|
|
27180
27180
|
if (literal(navigationLabel)) return navigationLabel.trim();
|
|
27181
27181
|
return inferScreenDisplayName(screenId);
|
|
@@ -29010,9 +29010,9 @@ function addScreen(dir, id, entry, opts = {}) {
|
|
|
29010
29010
|
if (content) {
|
|
29011
29011
|
if (content.screens !== void 0) {
|
|
29012
29012
|
const route = findRoute(reparsed, id);
|
|
29013
|
-
const
|
|
29013
|
+
const displayName3 = screenDisplayName(id, opts.displayName, route.block.title);
|
|
29014
29014
|
try {
|
|
29015
|
-
const metadata2 = parseScreenMetadata({ ...parseScreenMetadata(content.screens), [id]: { displayName:
|
|
29015
|
+
const metadata2 = parseScreenMetadata({ ...parseScreenMetadata(content.screens), [id]: { displayName: displayName3 } });
|
|
29016
29016
|
validateScreenMetadata(metadata2);
|
|
29017
29017
|
content.screens = metadata2;
|
|
29018
29018
|
} catch (error) {
|
|
@@ -29386,8 +29386,8 @@ function lastDistFromJob(job, now = /* @__PURE__ */ new Date()) {
|
|
|
29386
29386
|
const capabilities = [...new Set(job.buildCapabilities.filter((x2) => typeof x2 === "string").map(catalogKey))].sort();
|
|
29387
29387
|
return { app: job.app, jobId: job.jobId, shell: job.shell, capabilities, finishedAt: now.toISOString() };
|
|
29388
29388
|
}
|
|
29389
|
-
function needsBinaryNotice(
|
|
29390
|
-
const nb =
|
|
29389
|
+
function needsBinaryNotice(json8) {
|
|
29390
|
+
const nb = json8?.needsBinary;
|
|
29391
29391
|
if (!nb || !Array.isArray(nb.missing)) return null;
|
|
29392
29392
|
const missing = nb.missing.filter((x2) => typeof x2 === "string");
|
|
29393
29393
|
if (!missing.length) return null;
|
|
@@ -29729,12 +29729,12 @@ function updateSiteViewMetadata(existing, before, after) {
|
|
|
29729
29729
|
const bounded2 = suffix2.length > 100 ? `${suffix2.slice(0, 99)})` : suffix2;
|
|
29730
29730
|
return title.slice(0, 120 - bounded2.length).trimEnd() + bounded2;
|
|
29731
29731
|
};
|
|
29732
|
-
let
|
|
29733
|
-
if (claimed.has(screenDisplayNameKey(
|
|
29732
|
+
let displayName3 = fit2();
|
|
29733
|
+
if (claimed.has(screenDisplayNameKey(displayName3))) displayName3 = fit2(` (${page.id})`);
|
|
29734
29734
|
let suffix = 2;
|
|
29735
|
-
while (claimed.has(screenDisplayNameKey(
|
|
29736
|
-
updated[id] = { displayName:
|
|
29737
|
-
claimed.add(screenDisplayNameKey(
|
|
29735
|
+
while (claimed.has(screenDisplayNameKey(displayName3))) displayName3 = fit2(` (${suffix++}, ${page.id})`);
|
|
29736
|
+
updated[id] = { displayName: displayName3 };
|
|
29737
|
+
claimed.add(screenDisplayNameKey(displayName3));
|
|
29738
29738
|
}
|
|
29739
29739
|
validateScreenMetadata(updated);
|
|
29740
29740
|
return updated;
|
|
@@ -39399,10 +39399,10 @@ function createRicosHostSession(o2) {
|
|
|
39399
39399
|
});
|
|
39400
39400
|
};
|
|
39401
39401
|
const writes = () => committed || state.dirty;
|
|
39402
|
-
const moved = (
|
|
39403
|
-
if (
|
|
39404
|
-
lastContent =
|
|
39405
|
-
if (
|
|
39402
|
+
const moved = (json8) => {
|
|
39403
|
+
if (json8 === lastContent) return false;
|
|
39404
|
+
lastContent = json8;
|
|
39405
|
+
if (json8 !== baseline) {
|
|
39406
39406
|
state.dirty = true;
|
|
39407
39407
|
if (dirtyTimer !== null) t2.clearTimeout(dirtyTimer);
|
|
39408
39408
|
dirtyTimer = t2.setTimeout(() => {
|
|
@@ -39626,13 +39626,13 @@ async function runRicosImageUpload(o2) {
|
|
|
39626
39626
|
return fail6("put");
|
|
39627
39627
|
}
|
|
39628
39628
|
if (!res.ok) return fail6("put");
|
|
39629
|
-
let
|
|
39629
|
+
let json8;
|
|
39630
39630
|
try {
|
|
39631
|
-
|
|
39631
|
+
json8 = await res.json();
|
|
39632
39632
|
} catch {
|
|
39633
39633
|
return fail6("bad_descriptor");
|
|
39634
39634
|
}
|
|
39635
|
-
const root =
|
|
39635
|
+
const root = json8 && typeof json8 === "object" ? json8 : {};
|
|
39636
39636
|
const d2 = root.file && typeof root.file === "object" ? root.file : root;
|
|
39637
39637
|
const id = typeof d2.id === "string" ? d2.id : "";
|
|
39638
39638
|
if (!id) return fail6("bad_descriptor");
|
|
@@ -39833,9 +39833,9 @@ function RichContentEditorView({ props, ctx, wrap, nodeId, renderChild, ...dom }
|
|
|
39833
39833
|
locale: ctx.localeTag ?? "en",
|
|
39834
39834
|
rtl: ctx.isRTL ?? document.documentElement.dir === "rtl",
|
|
39835
39835
|
palette: { text: C2("textPrimary", "#13171E"), background: C2("surfacePrimary", "#FFFFFF"), accent: C2("accentPrimary", "#116DFF") },
|
|
39836
|
-
onContent: (
|
|
39836
|
+
onContent: (json8) => {
|
|
39837
39837
|
const b2 = bagRef.current, n2 = nameRef.current;
|
|
39838
|
-
if (b2 && n2) b2.set(n2,
|
|
39838
|
+
if (b2 && n2) b2.set(n2, json8);
|
|
39839
39839
|
},
|
|
39840
39840
|
onToolbar: setToolbar,
|
|
39841
39841
|
onFocusChange: setFocused,
|
|
@@ -40202,13 +40202,13 @@ async function runMediaFieldUpload(o2) {
|
|
|
40202
40202
|
return { ok: false, reason: e2 instanceof Deadline || expired ? "timeout" : "put" };
|
|
40203
40203
|
}
|
|
40204
40204
|
if (!res.ok) return { ok: false, reason: "put" };
|
|
40205
|
-
let
|
|
40205
|
+
let json8;
|
|
40206
40206
|
try {
|
|
40207
|
-
|
|
40207
|
+
json8 = await bounded2(res.json());
|
|
40208
40208
|
} catch (e2) {
|
|
40209
40209
|
return { ok: false, reason: e2 instanceof Deadline || expired ? "timeout" : "bad_descriptor" };
|
|
40210
40210
|
}
|
|
40211
|
-
const root =
|
|
40211
|
+
const root = json8 && typeof json8 === "object" ? json8 : {};
|
|
40212
40212
|
const d2 = root.file && typeof root.file === "object" ? root.file : root;
|
|
40213
40213
|
const mediaId = typeof d2.id === "string" ? d2.id : "";
|
|
40214
40214
|
if (!mediaId) return { ok: false, reason: "bad_descriptor" };
|
|
@@ -45273,7 +45273,7 @@ var init_pdf = __esm({
|
|
|
45273
45273
|
var defineProperty = Object.defineProperty;
|
|
45274
45274
|
var stringSlice = uncurryThis("".slice);
|
|
45275
45275
|
var replace = uncurryThis("".replace);
|
|
45276
|
-
var
|
|
45276
|
+
var join92 = uncurryThis([].join);
|
|
45277
45277
|
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
|
|
45278
45278
|
return defineProperty(function() {
|
|
45279
45279
|
}, "length", { value: 8 }).length !== 8;
|
|
@@ -45300,7 +45300,7 @@ var init_pdf = __esm({
|
|
|
45300
45300
|
}
|
|
45301
45301
|
var state = enforceInternalState(value);
|
|
45302
45302
|
if (!hasOwn(state, "source")) {
|
|
45303
|
-
state.source =
|
|
45303
|
+
state.source = join92(TEMPLATE, typeof name == "string" ? name : "");
|
|
45304
45304
|
}
|
|
45305
45305
|
return value;
|
|
45306
45306
|
};
|
|
@@ -47327,7 +47327,7 @@ var init_pdf = __esm({
|
|
|
47327
47327
|
var currentOrdered;
|
|
47328
47328
|
var marked = false;
|
|
47329
47329
|
var root = true;
|
|
47330
|
-
var
|
|
47330
|
+
var json8 = stringifyWithProperSymbolsConversion(text9, function(key3, value) {
|
|
47331
47331
|
key3 = $String(key3);
|
|
47332
47332
|
if (propertyList) {
|
|
47333
47333
|
if (key3 === END_MARK) {
|
|
@@ -47354,16 +47354,16 @@ var init_pdf = __esm({
|
|
|
47354
47354
|
}
|
|
47355
47355
|
return value;
|
|
47356
47356
|
}, space);
|
|
47357
|
-
if (typeof
|
|
47358
|
-
if (ILL_FORMED_UNICODE)
|
|
47359
|
-
if (!marked) return
|
|
47357
|
+
if (typeof json8 != "string") return json8;
|
|
47358
|
+
if (ILL_FORMED_UNICODE) json8 = replace(json8, surrogates, fixIllFormedJSON);
|
|
47359
|
+
if (!marked) return json8;
|
|
47360
47360
|
var result = "";
|
|
47361
|
-
var length =
|
|
47361
|
+
var length = json8.length;
|
|
47362
47362
|
for (var i2 = 0; i2 < length; i2++) {
|
|
47363
|
-
var chr = charAt(
|
|
47363
|
+
var chr = charAt(json8, i2);
|
|
47364
47364
|
if (chr === '"') {
|
|
47365
|
-
var end = parseJSONString(
|
|
47366
|
-
var string5 = slice(
|
|
47365
|
+
var end = parseJSONString(json8, ++i2).end - 1;
|
|
47366
|
+
var string5 = slice(json8, i2, end);
|
|
47367
47367
|
if (slice(string5, 0, RAW_MARK_LENGTH) === RAW_MARK) result += rawStrings[slice(string5, RAW_MARK_LENGTH)];
|
|
47368
47368
|
else if (slice(string5, 0, KEY_MARK_LENGTH) === KEY_MARK) result += '"' + slice(string5, KEY_MARK_LENGTH) + '"';
|
|
47369
47369
|
else result += '"' + string5 + '"';
|
|
@@ -47823,7 +47823,7 @@ var init_pdf = __esm({
|
|
|
47823
47823
|
var charAt = uncurryThis("".charAt);
|
|
47824
47824
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
47825
47825
|
var $Array = globalThis2.Array;
|
|
47826
|
-
var
|
|
47826
|
+
var join92 = uncurryThis([].join);
|
|
47827
47827
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
|
|
47828
47828
|
try {
|
|
47829
47829
|
var target = new Uint8Array2();
|
|
@@ -47869,7 +47869,7 @@ var init_pdf = __esm({
|
|
|
47869
47869
|
result[written++] = "=";
|
|
47870
47870
|
}
|
|
47871
47871
|
}
|
|
47872
|
-
return
|
|
47872
|
+
return join92(result, "");
|
|
47873
47873
|
}
|
|
47874
47874
|
});
|
|
47875
47875
|
},
|
|
@@ -47881,7 +47881,7 @@ var init_pdf = __esm({
|
|
|
47881
47881
|
var anUint8Array = __webpack_require__3(4154);
|
|
47882
47882
|
var notDetached = __webpack_require__3(5169);
|
|
47883
47883
|
var numberToString2 = uncurryThis(1.1.toString);
|
|
47884
|
-
var
|
|
47884
|
+
var join92 = uncurryThis([].join);
|
|
47885
47885
|
var $Array = Array;
|
|
47886
47886
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
47887
47887
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
|
|
@@ -47901,7 +47901,7 @@ var init_pdf = __esm({
|
|
|
47901
47901
|
var hex2 = numberToString2(this[i2], 16);
|
|
47902
47902
|
result[i2] = hex2.length === 1 ? "0" + hex2 : hex2;
|
|
47903
47903
|
}
|
|
47904
|
-
return
|
|
47904
|
+
return join92(result, "");
|
|
47905
47905
|
}
|
|
47906
47906
|
});
|
|
47907
47907
|
},
|
|
@@ -124985,9 +124985,9 @@ function renderInner(node, ctx) {
|
|
|
124985
124985
|
}
|
|
124986
124986
|
const transitionKey = typeof modifiers?.transitionId === "string" ? resolvedComponentId(modifiers.transitionId, ctx) : void 0;
|
|
124987
124987
|
if (transitionKey && !ctx.reduceMotion()) {
|
|
124988
|
-
let
|
|
124989
|
-
if (/^[0-9-]/.test(
|
|
124990
|
-
wrap.viewTransitionName =
|
|
124988
|
+
let ident2 = transitionKey.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
124989
|
+
if (/^[0-9-]/.test(ident2)) ident2 = `h-${ident2}`;
|
|
124990
|
+
wrap.viewTransitionName = ident2;
|
|
124991
124991
|
}
|
|
124992
124992
|
if (modifiers?.revealOnScroll && tr2 && !ctx.reduceMotion()) {
|
|
124993
124993
|
const spec = enterAnimSpec(tr2, modifiers?.motion ?? ctx.kit?.motion, ctx);
|
|
@@ -139729,10 +139729,10 @@ async function bakeWidgets(fetchPath, putWidget, ownBundles) {
|
|
|
139729
139729
|
}
|
|
139730
139730
|
continue;
|
|
139731
139731
|
}
|
|
139732
|
-
const
|
|
139733
|
-
await putWidget(widgetId,
|
|
139732
|
+
const json8 = JSON.stringify(snap);
|
|
139733
|
+
await putWidget(widgetId, json8);
|
|
139734
139734
|
widgets[widgetId] = {
|
|
139735
|
-
contentEtag: snap.contentEtag ?? sha2564(
|
|
139735
|
+
contentEtag: snap.contentEtag ?? sha2564(json8),
|
|
139736
139736
|
ttlSeconds: snap.refresh?.ttlSeconds ?? 0
|
|
139737
139737
|
};
|
|
139738
139738
|
}
|
|
@@ -139756,10 +139756,10 @@ function tokensSnapshotMessage(app, base, status) {
|
|
|
139756
139756
|
const why = status === 400 ? `the dev-server rejected the app id as malformed (400 bad_app). It must be lowercase letters, digits and hyphens, starting with a letter or digit, at most 63 characters, with at most one interior dot \u2014 so a leading underscore or an uppercase letter fails, on every build of that app. A single dot is FINE (an owner-namespaced slug), so do not remove one to get past this` : `${status} from the tokens route`;
|
|
139757
139757
|
return `[release-build] tokens snapshot FAILED for "${app}" (${why}; ${base}/v1/tokens) \u2014 this release carries no tokensHash and the app will render with NO design tokens. On iOS an undefined colour token is invisible, not merely unstyled.` + (status === 400 ? ` Fix the app id (himalaya.content.json "name", or the package directory basename) to match that grammar \u2014 but do NOT drop an owner prefix's dot: \`himi push\` requires the manifest name to equal the composed <ownerPrefix>.<name>, so removing it trades this warning for a 400 "manifest.app must match app" and the app cannot publish at all.` : "");
|
|
139758
139758
|
}
|
|
139759
|
-
function pinBakedServerBaseUrl(
|
|
139759
|
+
function pinBakedServerBaseUrl(json8, base) {
|
|
139760
139760
|
const escaped = base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
139761
139761
|
const boundary = /:\d+$/.test(base) ? "(?!\\d)" : "(?![\\w.-])(?!:\\d)";
|
|
139762
|
-
return
|
|
139762
|
+
return json8.replace(new RegExp(`${escaped}${boundary}`, "g"), BAKED_SERVER_BASE_URL);
|
|
139763
139763
|
}
|
|
139764
139764
|
function stableStringify2(v2) {
|
|
139765
139765
|
if (v2 === null || typeof v2 !== "object") return JSON.stringify(v2);
|
|
@@ -140500,15 +140500,15 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140500
140500
|
}
|
|
140501
140501
|
tierScreens.push(summarize3({ ...descriptor, ...lb ? { logicBundle: lb } : {} }));
|
|
140502
140502
|
delete descriptor.etag;
|
|
140503
|
-
const
|
|
140504
|
-
await store.putScreen(app, screenId,
|
|
140505
|
-
screens[screenId] = { descriptorHash: sha2564(
|
|
140506
|
-
rememberInput(bundleName, JSON.parse(
|
|
140503
|
+
const json8 = pinBakedServerBaseUrl(JSON.stringify(descriptor), base);
|
|
140504
|
+
await store.putScreen(app, screenId, json8);
|
|
140505
|
+
screens[screenId] = { descriptorHash: sha2564(json8), bundle: bundleName, ...screenMetadataFor(screenMetadata, screenId) };
|
|
140506
|
+
rememberInput(bundleName, JSON.parse(json8));
|
|
140507
140507
|
if (collect2?.descriptors) {
|
|
140508
140508
|
baked.push({
|
|
140509
140509
|
screenId,
|
|
140510
|
-
descriptor: JSON.parse(
|
|
140511
|
-
descriptorJson:
|
|
140510
|
+
descriptor: JSON.parse(json8),
|
|
140511
|
+
descriptorJson: json8,
|
|
140512
140512
|
bundleName,
|
|
140513
140513
|
bundleJs: bundleName ? readBundle(bundleName) ?? null : null,
|
|
140514
140514
|
...bundleMapFor(tier5Dir, bundleName ?? void 0)
|
|
@@ -140662,14 +140662,14 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140662
140662
|
lint.push({ screenId, ok: false, issues: fresh });
|
|
140663
140663
|
}
|
|
140664
140664
|
}
|
|
140665
|
-
const
|
|
140666
|
-
await store.putScreen(app, screenId,
|
|
140667
|
-
screens[screenId] = { descriptorHash: sha2564(
|
|
140668
|
-
rememberInput(bundleName, JSON.parse(
|
|
140665
|
+
const json8 = pinBakedServerBaseUrl(JSON.stringify(descriptor), base);
|
|
140666
|
+
await store.putScreen(app, screenId, json8);
|
|
140667
|
+
screens[screenId] = { descriptorHash: sha2564(json8), bundle: bundleName, ...screenMetadataFor(screenMetadata, screenId, canonical5) };
|
|
140668
|
+
rememberInput(bundleName, JSON.parse(json8));
|
|
140669
140669
|
if (collect2?.descriptors) {
|
|
140670
140670
|
baked.push({
|
|
140671
140671
|
screenId,
|
|
140672
|
-
descriptor: JSON.parse(
|
|
140672
|
+
descriptor: JSON.parse(json8),
|
|
140673
140673
|
// The EXACT baked bytes, exactly as the exact-screen path hands
|
|
140674
140674
|
// them over. Omitting them did not degrade the crawl quietly — it
|
|
140675
140675
|
// took out the native-decode oracle for the whole app, which
|
|
@@ -140678,7 +140678,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140678
140678
|
// bytes") and throws rather than skipping. So one templated route
|
|
140679
140679
|
// anywhere in an app meant `himi test --native` reported nothing
|
|
140680
140680
|
// for ANY of its screens.
|
|
140681
|
-
descriptorJson:
|
|
140681
|
+
descriptorJson: json8,
|
|
140682
140682
|
bundleName,
|
|
140683
140683
|
bundleJs: bundleName ? readBundle(bundleName) ?? null : null,
|
|
140684
140684
|
...bundleMapFor(tier5Dir, bundleName ?? void 0)
|
|
@@ -140771,7 +140771,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140771
140771
|
if (store.putWidget) {
|
|
140772
140772
|
const bakedWidgets = await bakeWidgets(
|
|
140773
140773
|
(path2) => devFetch(`${base}${path2}`, { headers: { "X-Himalaya-App": app } }),
|
|
140774
|
-
(widgetId,
|
|
140774
|
+
(widgetId, json8) => store.putWidget(app, widgetId, json8),
|
|
140775
140775
|
// `opts.tier5Dir`, NOT the `tier5Dir` local — that one falls back to the
|
|
140776
140776
|
// repo-global dir, where this package's widgets cannot be told from anyone
|
|
140777
140777
|
// else's and the filter would claim every app's rows as ours.
|
|
@@ -140790,9 +140790,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140790
140790
|
if (!js2) continue;
|
|
140791
140791
|
try {
|
|
140792
140792
|
const input = bundleInputs.get(name);
|
|
140793
|
-
const
|
|
140794
|
-
const hash2 = sha2564(
|
|
140795
|
-
await store.putDoc(app, hash2,
|
|
140793
|
+
const json8 = JSON.stringify(extractBundleServices(js2, input ? { input } : {}));
|
|
140794
|
+
const hash2 = sha2564(json8);
|
|
140795
|
+
await store.putDoc(app, hash2, json8);
|
|
140796
140796
|
meta.servicesHash = hash2;
|
|
140797
140797
|
} catch {
|
|
140798
140798
|
}
|
|
@@ -153273,7 +153273,7 @@ function recommendTemplates(input) {
|
|
|
153273
153273
|
const text9 = input.text ?? "";
|
|
153274
153274
|
const owner = OWNER_WORDS.test(text9);
|
|
153275
153275
|
const want = new Set(tokens(text9));
|
|
153276
|
-
const
|
|
153276
|
+
const byName3 = /* @__PURE__ */ new Map();
|
|
153277
153277
|
for (const row of input.catalog) {
|
|
153278
153278
|
const reasons = [];
|
|
153279
153279
|
let score = 0;
|
|
@@ -153294,24 +153294,24 @@ function recommendTemplates(input) {
|
|
|
153294
153294
|
score -= 0.3;
|
|
153295
153295
|
}
|
|
153296
153296
|
}
|
|
153297
|
-
|
|
153297
|
+
byName3.set(row.name, { name: row.name, score, reasons, ...row.source ? { source: row.source } : {} });
|
|
153298
153298
|
}
|
|
153299
153299
|
if (input.verticals?.length) {
|
|
153300
153300
|
for (const c2 of scoreOverlays(input.verticals, "")) {
|
|
153301
|
-
const name = owner &&
|
|
153302
|
-
const rec =
|
|
153301
|
+
const name = owner && byName3.has(`${c2.id}-owner`) ? `${c2.id}-owner` : c2.id;
|
|
153302
|
+
const rec = byName3.get(name);
|
|
153303
153303
|
if (!rec || c2.score <= 0) continue;
|
|
153304
153304
|
rec.score += c2.score;
|
|
153305
153305
|
rec.reasons.push(`site verticals: ${c2.why}`);
|
|
153306
153306
|
}
|
|
153307
153307
|
}
|
|
153308
153308
|
const fallback = owner ? "owner-lite" : "branded-lite";
|
|
153309
|
-
const fb =
|
|
153309
|
+
const fb = byName3.get(fallback);
|
|
153310
153310
|
if (fb) {
|
|
153311
153311
|
fb.score += 0.25;
|
|
153312
153312
|
fb.reasons.push(owner ? "the default start for owner/operations apps" : "the default start for a customer app on a Wix site");
|
|
153313
153313
|
}
|
|
153314
|
-
const ranked = [...
|
|
153314
|
+
const ranked = [...byName3.values()].map((r2) => ({ ...r2, score: Math.round(r2.score * 1e3) / 1e3 })).filter((r2) => r2.score > 0).sort((a2, b2) => b2.score - a2.score || a2.name.localeCompare(b2.name));
|
|
153315
153315
|
return { owner, ranked };
|
|
153316
153316
|
}
|
|
153317
153317
|
var OWNER_WORDS, STOP, tokens;
|
|
@@ -156823,8 +156823,8 @@ function memoryStore(manifest, built) {
|
|
|
156823
156823
|
},
|
|
156824
156824
|
// The two members the cast used to paper over. Serve-relative, as FileReleaseStore's is; and
|
|
156825
156825
|
// nothing to prune, since this store only ever holds the one release it was built with.
|
|
156826
|
-
bundleUrl(_app,
|
|
156827
|
-
return `/v1/bundles/${
|
|
156826
|
+
bundleUrl(_app, sha2567) {
|
|
156827
|
+
return `/v1/bundles/${sha2567}.bundle.js`;
|
|
156828
156828
|
},
|
|
156829
156829
|
async prune() {
|
|
156830
156830
|
return 0;
|
|
@@ -158801,9 +158801,9 @@ function verifyReport(dir, app, manifest) {
|
|
|
158801
158801
|
function addAssetPayload(manifest, filePath, opts) {
|
|
158802
158802
|
const bytes2 = readFileSync84(filePath);
|
|
158803
158803
|
const name = opts.name ?? basename17(filePath);
|
|
158804
|
-
const
|
|
158804
|
+
const sha2567 = assetSha256(bytes2);
|
|
158805
158805
|
const record2 = {
|
|
158806
|
-
sha256:
|
|
158806
|
+
sha256: sha2567,
|
|
158807
158807
|
sri: assetSri(bytes2),
|
|
158808
158808
|
bytes: bytes2.length,
|
|
158809
158809
|
contentType: opts.contentType ?? contentTypeFor(name),
|
|
@@ -158816,7 +158816,7 @@ function addAssetPayload(manifest, filePath, opts) {
|
|
|
158816
158816
|
const assets = { ...manifest.assets ?? {}, [name]: record2 };
|
|
158817
158817
|
const next = { ...manifest, assets, releaseId: opts.mintReleaseId({ ...manifest, assets, releaseId: void 0 }) };
|
|
158818
158818
|
return {
|
|
158819
|
-
payload: { app: manifest.app, manifest: next, screens: {}, bundles: {}, assets: { [
|
|
158819
|
+
payload: { app: manifest.app, manifest: next, screens: {}, bundles: {}, assets: { [sha2567]: bytes2.toString("base64") } },
|
|
158820
158820
|
record: record2,
|
|
158821
158821
|
name
|
|
158822
158822
|
};
|
|
@@ -165461,9 +165461,9 @@ var init_store_iap = __esm({
|
|
|
165461
165461
|
UsageError = class extends Error {
|
|
165462
165462
|
};
|
|
165463
165463
|
CommandOutput = class {
|
|
165464
|
-
constructor(io2,
|
|
165464
|
+
constructor(io2, json8) {
|
|
165465
165465
|
this.io = io2;
|
|
165466
|
-
this.json =
|
|
165466
|
+
this.json = json8;
|
|
165467
165467
|
}
|
|
165468
165468
|
secrets = [];
|
|
165469
165469
|
get interactive() {
|
|
@@ -165634,7 +165634,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165634
165634
|
const invokedAs = pos[0];
|
|
165635
165635
|
const sub = invokedAs === "testflight" ? "upload" : pos[1];
|
|
165636
165636
|
const app = invokedAs === "testflight" ? pos[1] : pos[2];
|
|
165637
|
-
const
|
|
165637
|
+
const json8 = on3(flags.json);
|
|
165638
165638
|
const print = (o2) => io2.log(JSON.stringify(o2, null, 2));
|
|
165639
165639
|
const fail6 = (error, extra = {}) => {
|
|
165640
165640
|
io2.error(JSON.stringify({ error, ...extra }));
|
|
@@ -165672,7 +165672,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165672
165672
|
}
|
|
165673
165673
|
try {
|
|
165674
165674
|
const s2 = await deps.ascStatus(app, credsToEnv(creds2));
|
|
165675
|
-
if (
|
|
165675
|
+
if (json8) print({ ok: true, app, team: creds2.team, ...s2 });
|
|
165676
165676
|
else {
|
|
165677
165677
|
io2.log(` ${pad2("app")}${app} team ${creds2.team} appStoreId ${s2.appStoreId}`);
|
|
165678
165678
|
for (const b2 of s2.builds.slice(0, 5)) io2.log(` ${pad2("build")}${b2.version} ${b2.processingState}`);
|
|
@@ -165692,7 +165692,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165692
165692
|
}
|
|
165693
165693
|
const { errors, warnings } = partitionFindings(findings);
|
|
165694
165694
|
if (sub === "preflight") {
|
|
165695
|
-
if (
|
|
165695
|
+
if (json8) print({ ok: errors.length === 0, app, findings });
|
|
165696
165696
|
else {
|
|
165697
165697
|
for (const f2 of findings) io2.log(` ${f2.level === "error" ? "\u2717" : "!"} ${f2.message}`);
|
|
165698
165698
|
io2.log(errors.length === 0 ? `
|
|
@@ -165730,7 +165730,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165730
165730
|
const reuseExisting = on3(flags["skip-build"]);
|
|
165731
165731
|
const nextBuild = reuseExisting ? version4.build : version4.build + 1;
|
|
165732
165732
|
const plannedSteps = UPLOAD_STEPS.filter((s2) => !(reuseExisting && BUILD_STEPS.has(s2)));
|
|
165733
|
-
if (!
|
|
165733
|
+
if (!json8) {
|
|
165734
165734
|
io2.log("");
|
|
165735
165735
|
for (const line of accountHeader({ app, bundleId, version: version4, nextBuild, creds, track })) io2.log(line);
|
|
165736
165736
|
io2.log("");
|
|
@@ -165758,7 +165758,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165758
165758
|
steps: [...plannedSteps],
|
|
165759
165759
|
warnings: warnings.map((w2) => w2.message)
|
|
165760
165760
|
};
|
|
165761
|
-
if (
|
|
165761
|
+
if (json8) print(plan);
|
|
165762
165762
|
else {
|
|
165763
165763
|
io2.log(`
|
|
165764
165764
|
dry run \u2014 nothing was built, uploaded or bumped.`);
|
|
@@ -165811,11 +165811,11 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165811
165811
|
stderr: r2.stderr.split("\n").slice(-20).join("\n")
|
|
165812
165812
|
});
|
|
165813
165813
|
}
|
|
165814
|
-
if (!
|
|
165814
|
+
if (!json8) io2.log(` \u2713 ${pad2(step)}ok`);
|
|
165815
165815
|
}
|
|
165816
165816
|
if (on3(flags["no-wait"])) {
|
|
165817
165817
|
const out2 = { ok: true, app, build: uploaded.build, uploaded: true, processed: null, note: "upload accepted; processing not awaited. `himi store status " + app + "` tells you whether it landed." };
|
|
165818
|
-
if (
|
|
165818
|
+
if (json8) print(out2);
|
|
165819
165819
|
else io2.log(`
|
|
165820
165820
|
\u2713 uploaded build ${uploaded.build} \u2014 processing not awaited.`);
|
|
165821
165821
|
return 0;
|
|
@@ -165836,7 +165836,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165836
165836
|
const mine = findBuild(s2.builds, uploaded.build);
|
|
165837
165837
|
if (mine && mine.processingState === "VALID") {
|
|
165838
165838
|
const url = `https://appstoreconnect.apple.com/apps/${s2.appStoreId}/testflight/ios`;
|
|
165839
|
-
if (
|
|
165839
|
+
if (json8) print({ ok: true, app, build: uploaded.build, processingState: mine.processingState, url });
|
|
165840
165840
|
else io2.log(`
|
|
165841
165841
|
\u2713 TestFlight ${uploaded.marketing} (${uploaded.build}) \u2014 Processing complete
|
|
165842
165842
|
${url}`);
|
|
@@ -165856,7 +165856,7 @@ async function runStore(pos, flags, io2, deps) {
|
|
|
165856
165856
|
{ app, build: uploaded.build, uploaded: true, processed: false }
|
|
165857
165857
|
);
|
|
165858
165858
|
}
|
|
165859
|
-
if (!
|
|
165859
|
+
if (!json8) io2.log(` \u2026 processing (${Math.round(waited / 1e3)}s)`);
|
|
165860
165860
|
await deps.sleep(PROCESSING_POLL_MS);
|
|
165861
165861
|
waited += PROCESSING_POLL_MS;
|
|
165862
165862
|
}
|
|
@@ -167284,7 +167284,7 @@ function parseDataFlag(raw) {
|
|
|
167284
167284
|
async function runNotify(pos, flags, io2, deps = {}) {
|
|
167285
167285
|
const doFetch = deps.fetchImpl ?? fetch;
|
|
167286
167286
|
const str11 = (v2) => typeof v2 === "string" ? v2 : void 0;
|
|
167287
|
-
const
|
|
167287
|
+
const json8 = flags.json === true;
|
|
167288
167288
|
const print = (v2) => io2.log(JSON.stringify(v2, null, 2));
|
|
167289
167289
|
const sub = pos[1];
|
|
167290
167290
|
const USAGE2 = "himi notify send --app <app> (--token <t> | --device <id> | --all) --title <s> [--body <s>] [--link <url>]\n [--platform ios|android] [--category <c>] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]\n [--data k=v ...]\nhimi notify tokens --app <app> [--platform ios|android] [--include-disabled] [--json]\nhimi notify doctor [--json]";
|
|
@@ -167329,7 +167329,7 @@ async function runNotify(pos, flags, io2, deps = {}) {
|
|
|
167329
167329
|
...session ? {} : { hint: "no admin session \u2014 pass --admin-session or set HIMALAYA_ADMIN_SESSION" },
|
|
167330
167330
|
...reachable && authed && !senders ? { hint: "this admin-server predates /v1/admin/push-doctor \u2014 upgrade it to see sender readiness" } : {}
|
|
167331
167331
|
};
|
|
167332
|
-
if (
|
|
167332
|
+
if (json8) {
|
|
167333
167333
|
print(report3);
|
|
167334
167334
|
return report3.ok ? 0 : 1;
|
|
167335
167335
|
}
|
|
@@ -167377,7 +167377,7 @@ async function runNotify(pos, flags, io2, deps = {}) {
|
|
|
167377
167377
|
return 1;
|
|
167378
167378
|
}
|
|
167379
167379
|
const body = await res2.json();
|
|
167380
|
-
if (
|
|
167380
|
+
if (json8) {
|
|
167381
167381
|
print({ ok: true, app, count: body.tokens.length, tokens: body.tokens });
|
|
167382
167382
|
return 0;
|
|
167383
167383
|
}
|
|
@@ -167467,7 +167467,7 @@ async function runNotify(pos, flags, io2, deps = {}) {
|
|
|
167467
167467
|
io2.error(JSON.stringify({ error: out2.error ?? `send failed: ${res.status}` }));
|
|
167468
167468
|
return 1;
|
|
167469
167469
|
}
|
|
167470
|
-
if (
|
|
167470
|
+
if (json8) {
|
|
167471
167471
|
print(out2);
|
|
167472
167472
|
return out2.ok ? 0 : 1;
|
|
167473
167473
|
}
|
|
@@ -167679,7 +167679,7 @@ function adoptFromBook(book, opts = {}) {
|
|
|
167679
167679
|
return { entities, functions, skipped };
|
|
167680
167680
|
}
|
|
167681
167681
|
function renderAdoptModule(r2, source = ".himi/base44-book/book.json") {
|
|
167682
|
-
const
|
|
167682
|
+
const json8 = (v2) => JSON.stringify(v2, null, 2);
|
|
167683
167683
|
return [
|
|
167684
167684
|
`// Generated by \`himi base44 adopt\` from ${source}. Every entry is ADOPTED: the Base44 app's`,
|
|
167685
167685
|
`// own entity or function, read-only to himi. Review it, then wire it into config.ts:`,
|
|
@@ -167687,9 +167687,9 @@ function renderAdoptModule(r2, source = ".himi/base44-book/book.json") {
|
|
|
167687
167687
|
`// See docs/base44-entities.md.`,
|
|
167688
167688
|
`import type { Base44EntitySpec, Base44FunctionSpec } from "@wix/himalaya/core";`,
|
|
167689
167689
|
``,
|
|
167690
|
-
`export const base44Entities = ${
|
|
167690
|
+
`export const base44Entities = ${json8(r2.entities)} satisfies Base44EntitySpec[];`,
|
|
167691
167691
|
``,
|
|
167692
|
-
`export const base44Functions = ${
|
|
167692
|
+
`export const base44Functions = ${json8(r2.functions)} satisfies Base44FunctionSpec[];`,
|
|
167693
167693
|
``
|
|
167694
167694
|
].join("\n");
|
|
167695
167695
|
}
|
|
@@ -167738,6 +167738,380 @@ var init_base44_adopt = __esm({
|
|
|
167738
167738
|
}
|
|
167739
167739
|
});
|
|
167740
167740
|
|
|
167741
|
+
// src/base44-screens/plan.ts
|
|
167742
|
+
var plan_exports = {};
|
|
167743
|
+
__export(plan_exports, {
|
|
167744
|
+
ENTITY_TAB_SLOTS: () => ENTITY_TAB_SLOTS,
|
|
167745
|
+
MORE_SCREEN_ID: () => MORE_SCREEN_ID,
|
|
167746
|
+
PlanError: () => PlanError,
|
|
167747
|
+
RESERVED_SCREEN_IDS: () => RESERVED_SCREEN_IDS,
|
|
167748
|
+
displayName: () => displayName2,
|
|
167749
|
+
gateFor: () => gateFor,
|
|
167750
|
+
humanize: () => humanize,
|
|
167751
|
+
planEntity: () => planEntity,
|
|
167752
|
+
planEntityScreens: () => planEntityScreens,
|
|
167753
|
+
pluralize: () => pluralize,
|
|
167754
|
+
rowTitleField: () => rowTitleField,
|
|
167755
|
+
snake: () => snake
|
|
167756
|
+
});
|
|
167757
|
+
function ownerKeyOf(rule) {
|
|
167758
|
+
if (!rule || typeof rule !== "object" || Array.isArray(rule)) return void 0;
|
|
167759
|
+
const entries = Object.entries(rule);
|
|
167760
|
+
if (entries.length !== 1) return void 0;
|
|
167761
|
+
const [k2, v2] = entries[0];
|
|
167762
|
+
return OWNER_RULES.find(([key3, tpl]) => key3 === k2 && v2 === tpl)?.[0];
|
|
167763
|
+
}
|
|
167764
|
+
function gateFor(rule) {
|
|
167765
|
+
if (rule === void 0 || rule === null || rule === false) return "never";
|
|
167766
|
+
if (rule === true) return "always";
|
|
167767
|
+
return ownerKeyOf(rule) ? "owner" : "signed-in";
|
|
167768
|
+
}
|
|
167769
|
+
function pluralize(word) {
|
|
167770
|
+
if (/[^aeiou]y$/i.test(word)) return `${word.slice(0, -1)}ies`;
|
|
167771
|
+
if (/(s|x|z|ch|sh)$/i.test(word)) return `${word}es`;
|
|
167772
|
+
return `${word}s`;
|
|
167773
|
+
}
|
|
167774
|
+
function snake(name) {
|
|
167775
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
167776
|
+
}
|
|
167777
|
+
function humanize(key3) {
|
|
167778
|
+
const words = snake(key3).replace(/_/g, " ").trim();
|
|
167779
|
+
return words ? words.charAt(0).toUpperCase() + words.slice(1) : key3;
|
|
167780
|
+
}
|
|
167781
|
+
function displayName2(name) {
|
|
167782
|
+
const words = name.match(/[A-Z]+(?![a-z])|[A-Z][a-z0-9]*|[a-z0-9]+/g) ?? [name];
|
|
167783
|
+
return words.map((w2, i2) => w2.length > 1 && w2 === w2.toUpperCase() ? w2 : i2 === 0 ? w2.charAt(0).toUpperCase() + w2.slice(1).toLowerCase() : w2.toLowerCase()).join(" ");
|
|
167784
|
+
}
|
|
167785
|
+
function rowTitleField(spec) {
|
|
167786
|
+
const fields = Array.isArray(spec.fields) ? spec.fields : [];
|
|
167787
|
+
if (spec.displayField) return spec.displayField;
|
|
167788
|
+
const strings = fields.filter((f2) => isPlainString(f2) && !isLongText(f2) && !isImage(f2));
|
|
167789
|
+
const required3 = new Set(spec.required ?? []);
|
|
167790
|
+
const req = strings.filter((f2) => required3.has(f2.key));
|
|
167791
|
+
const preferred = (pool2) => PREFERRED_TITLES.map((k2) => pool2.find((f2) => f2.key === k2)).find(Boolean);
|
|
167792
|
+
return (preferred(req) ?? req[0] ?? preferred(strings) ?? strings[0])?.key ?? "id";
|
|
167793
|
+
}
|
|
167794
|
+
function rowSubtitle(spec, title) {
|
|
167795
|
+
const short = (f2) => f2.key !== title && (isEnum(f2) || isDate(f2) || f2.type === "number" || f2.type === "integer");
|
|
167796
|
+
return (spec.fields ?? []).filter(short).slice(0, 2).map((f2) => f2.key);
|
|
167797
|
+
}
|
|
167798
|
+
function detailShow(f2) {
|
|
167799
|
+
if (f2.type === "object" || f2.type === "array" && f2.items?.type !== "string") return "section";
|
|
167800
|
+
if (f2.type === "array") return "chips";
|
|
167801
|
+
if (f2.type === "boolean") return "badge";
|
|
167802
|
+
if (isEnum(f2)) return "badge";
|
|
167803
|
+
if (isDate(f2)) return "date";
|
|
167804
|
+
if (isImage(f2)) return "image";
|
|
167805
|
+
if (f2.type === "string" && (f2.format === "email" || f2.format === "uri")) return "link";
|
|
167806
|
+
if (isLongText(f2)) return "longText";
|
|
167807
|
+
return "text";
|
|
167808
|
+
}
|
|
167809
|
+
function formControl(f2) {
|
|
167810
|
+
if (f2.type === "object" || f2.type === "array" && f2.items?.type !== "string") return null;
|
|
167811
|
+
if (f2.type === "array") return { control: "ChipsInput" };
|
|
167812
|
+
if (f2.type === "boolean") return { control: "Toggle" };
|
|
167813
|
+
if (isEnum(f2)) {
|
|
167814
|
+
const options = (f2.enum ?? []).map(String);
|
|
167815
|
+
return { control: options.length <= SEGMENTED_MAX ? "SegmentedControl" : "Picker", options, optionLabels: options.map(humanize) };
|
|
167816
|
+
}
|
|
167817
|
+
if (f2.type === "number" || f2.type === "integer") return { control: "NumberField", keyboard: "number" };
|
|
167818
|
+
if (isDate(f2)) return { control: "DatePicker" };
|
|
167819
|
+
if (isImage(f2)) return { control: "TextField", keyboard: "url", forcedReadOnly: true };
|
|
167820
|
+
if (f2.type === "string" && f2.format === "email") return { control: "TextField", keyboard: "email" };
|
|
167821
|
+
if (f2.type === "string" && f2.format === "uri") return { control: "TextField", keyboard: "url" };
|
|
167822
|
+
if (isLongText(f2)) return { control: "MultilineTextField" };
|
|
167823
|
+
return { control: "TextField" };
|
|
167824
|
+
}
|
|
167825
|
+
function fieldReadOnly(f2) {
|
|
167826
|
+
const rls = f2.rls;
|
|
167827
|
+
return !!rls && typeof rls === "object" && "write" in rls && rls.write !== true;
|
|
167828
|
+
}
|
|
167829
|
+
function ruleFor(spec, op) {
|
|
167830
|
+
const rls = spec.rls;
|
|
167831
|
+
if (!rls || typeof rls !== "object") return void 0;
|
|
167832
|
+
return op in rls ? rls[op] : rls.write;
|
|
167833
|
+
}
|
|
167834
|
+
function planEntity(spec, app = "") {
|
|
167835
|
+
const name = String(isAdoptedEntity(spec) ? spec.base44Name : spec.name);
|
|
167836
|
+
const singularSlug = snake(name);
|
|
167837
|
+
const pluralSlug = pluralize(singularSlug);
|
|
167838
|
+
const kebab2 = singularSlug.replace(/_/g, "-");
|
|
167839
|
+
const title = spec.title?.trim() || displayName2(name);
|
|
167840
|
+
const listTitle = pluralize(title);
|
|
167841
|
+
const titleField = rowTitleField(spec);
|
|
167842
|
+
const fields = (spec.fields ?? []).filter((f2) => f2 && typeof f2.key === "string");
|
|
167843
|
+
const titleSpec = fields.find((f2) => f2.key === titleField);
|
|
167844
|
+
const composable = !!titleSpec && isPlainString(titleSpec) && !fieldReadOnly(titleSpec);
|
|
167845
|
+
const gates = { create: composable ? gateFor(ruleFor(spec, "create")) : "never", update: gateFor(ruleFor(spec, "update")), delete: gateFor(ruleFor(spec, "delete")) };
|
|
167846
|
+
const owner = {};
|
|
167847
|
+
for (const op of ["update", "delete"]) {
|
|
167848
|
+
if (gates[op] === "owner") owner[op] = ownerKeyOf(ruleFor(spec, op));
|
|
167849
|
+
}
|
|
167850
|
+
const createDefaults = {};
|
|
167851
|
+
for (const f2 of fields) if (f2.default !== void 0) createDefaults[f2.key] = f2.default;
|
|
167852
|
+
return {
|
|
167853
|
+
entity: physicalEntityName(spec, app),
|
|
167854
|
+
name,
|
|
167855
|
+
service: { list: `b44${pascal(pluralSlug)}`, detail: `b44${pascal(singularSlug)}` },
|
|
167856
|
+
ids: { list: `b44_${pluralSlug}`, detail: `b44_${singularSlug}`, bundleList: `b44-${kebab2}-list`, bundleDetail: `b44-${kebab2}` },
|
|
167857
|
+
title,
|
|
167858
|
+
listTitle,
|
|
167859
|
+
countNoun: [nounOf(title), nounOf(listTitle)],
|
|
167860
|
+
row: { title: titleField, subtitle: rowSubtitle(spec, titleField) },
|
|
167861
|
+
detail: fields.filter((f2) => f2.key !== titleField).map((f2) => ({
|
|
167862
|
+
key: f2.key,
|
|
167863
|
+
label: humanize(f2.key),
|
|
167864
|
+
show: detailShow(f2),
|
|
167865
|
+
type: f2.type,
|
|
167866
|
+
...f2.format ? { format: f2.format } : {}
|
|
167867
|
+
})),
|
|
167868
|
+
form: fields.flatMap((f2) => {
|
|
167869
|
+
const c2 = formControl(f2);
|
|
167870
|
+
if (!c2) return [];
|
|
167871
|
+
const { forcedReadOnly, ...control } = c2;
|
|
167872
|
+
return [{
|
|
167873
|
+
key: f2.key,
|
|
167874
|
+
label: humanize(f2.key),
|
|
167875
|
+
type: f2.type,
|
|
167876
|
+
...f2.format ? { format: f2.format } : {},
|
|
167877
|
+
...control,
|
|
167878
|
+
readOnly: forcedReadOnly === true || fieldReadOnly(f2)
|
|
167879
|
+
}];
|
|
167880
|
+
}),
|
|
167881
|
+
gates,
|
|
167882
|
+
owner,
|
|
167883
|
+
createDefaults
|
|
167884
|
+
};
|
|
167885
|
+
}
|
|
167886
|
+
function planEntityScreens(specs, app = "") {
|
|
167887
|
+
const plans = specs.map((s2) => planEntity(s2, app));
|
|
167888
|
+
const owners = new Map(RESERVED_SCREEN_IDS.map((id) => [`screen id "${id}"`, "the base44-starter template"]));
|
|
167889
|
+
for (const p2 of plans) {
|
|
167890
|
+
const claims = [
|
|
167891
|
+
...[p2.ids.list, p2.ids.detail].map((id) => [`screen id "${id}"`, id]),
|
|
167892
|
+
...[p2.ids.bundleList, p2.ids.bundleDetail].map((b2) => [`worker bundle "${b2}"`, b2]),
|
|
167893
|
+
...[p2.service.list, p2.service.detail].map((svc) => [`service "${svc}"`, svc])
|
|
167894
|
+
];
|
|
167895
|
+
for (const [what, id] of claims) {
|
|
167896
|
+
const other = owners.get(what);
|
|
167897
|
+
if (other !== void 0) {
|
|
167898
|
+
throw new PlanError("entity_id_collision", `entity "${p2.name}" would generate ${what}, which ${other} already uses \u2014 rename one of them`, { entity: p2.name, screenId: id, with: other });
|
|
167899
|
+
}
|
|
167900
|
+
owners.set(what, `entity "${p2.name}"`);
|
|
167901
|
+
}
|
|
167902
|
+
}
|
|
167903
|
+
const names = plans.map((p2) => p2.name);
|
|
167904
|
+
if (names.length <= ENTITY_TAB_SLOTS) return { plans, tabs: names, more: [] };
|
|
167905
|
+
return { plans, tabs: names.slice(0, ENTITY_TAB_SLOTS - 1), more: names.slice(ENTITY_TAB_SLOTS - 1) };
|
|
167906
|
+
}
|
|
167907
|
+
var PlanError, RESERVED_SCREEN_IDS, MORE_SCREEN_ID, ENTITY_TAB_SLOTS, OWNER_RULES, pascal, PREFERRED_TITLES, LONG_TEXT, IMAGE_KEY, SEGMENTED_MAX, isPlainString, isEnum, isDate, isImage, isLongText, nounOf;
|
|
167908
|
+
var init_plan4 = __esm({
|
|
167909
|
+
"src/base44-screens/plan.ts"() {
|
|
167910
|
+
init_base44_schema();
|
|
167911
|
+
PlanError = class extends Error {
|
|
167912
|
+
constructor(code, message, extra = {}) {
|
|
167913
|
+
super(message);
|
|
167914
|
+
this.code = code;
|
|
167915
|
+
this.extra = extra;
|
|
167916
|
+
this.name = "PlanError";
|
|
167917
|
+
}
|
|
167918
|
+
};
|
|
167919
|
+
RESERVED_SCREEN_IDS = ["b44_functions", "b44_account", "b44_more"];
|
|
167920
|
+
MORE_SCREEN_ID = "b44_more";
|
|
167921
|
+
ENTITY_TAB_SLOTS = 3;
|
|
167922
|
+
OWNER_RULES = [["created_by", "{{user.email}}"], ["created_by_id", "{{user.id}}"]];
|
|
167923
|
+
pascal = (slug) => slug.split("_").filter(Boolean).map((p2) => p2.charAt(0).toUpperCase() + p2.slice(1)).join("");
|
|
167924
|
+
PREFERRED_TITLES = ["title", "name", "label"];
|
|
167925
|
+
LONG_TEXT = /^(description|notes?|body|content|summary|details?|bio|comments?|message|text)$|_(description|notes?|body|summary)$/i;
|
|
167926
|
+
IMAGE_KEY = /^(image|photo|avatar|picture|thumbnail|logo|cover)$|_url$/i;
|
|
167927
|
+
SEGMENTED_MAX = 4;
|
|
167928
|
+
isPlainString = (f2) => f2.type === "string" && !f2.enum && (f2.format === void 0 || f2.format === "richtext");
|
|
167929
|
+
isEnum = (f2) => Array.isArray(f2.enum) && f2.enum.length > 0;
|
|
167930
|
+
isDate = (f2) => f2.type === "string" && (f2.format === "date" || f2.format === "date-time");
|
|
167931
|
+
isImage = (f2) => f2.type === "string" && !isEnum(f2) && (f2.format === "file" || IMAGE_KEY.test(f2.key));
|
|
167932
|
+
isLongText = (f2) => f2.type === "string" && !isEnum(f2) && (f2.format === "richtext" || LONG_TEXT.test(f2.key));
|
|
167933
|
+
nounOf = (display) => display.split(" ").map((w2) => /^[A-Z]{2,}s?$/.test(w2) ? w2 : w2.toLowerCase()).join(" ");
|
|
167934
|
+
}
|
|
167935
|
+
});
|
|
167936
|
+
|
|
167937
|
+
// src/base44-screens/generate.ts
|
|
167938
|
+
var generate_exports = {};
|
|
167939
|
+
__export(generate_exports, {
|
|
167940
|
+
ENGINE_FILES: () => ENGINE_FILES,
|
|
167941
|
+
GENERATED_HEADER: () => GENERATED_HEADER,
|
|
167942
|
+
isEdited: () => isEdited,
|
|
167943
|
+
orphanedFiles: () => orphanedFiles,
|
|
167944
|
+
renderAll: () => renderAll,
|
|
167945
|
+
renderDetailEntry: () => renderDetailEntry,
|
|
167946
|
+
renderDevRegistrations: () => renderDevRegistrations,
|
|
167947
|
+
renderListEntry: () => renderListEntry,
|
|
167948
|
+
renderNav: () => renderNav,
|
|
167949
|
+
renderPlanModule: () => renderPlanModule,
|
|
167950
|
+
withHeader: () => withHeader,
|
|
167951
|
+
writeGenerated: () => writeGenerated
|
|
167952
|
+
});
|
|
167953
|
+
import { createHash as createHash43 } from "node:crypto";
|
|
167954
|
+
import { existsSync as existsSync79, mkdirSync as mkdirSync37, readdirSync as readdirSync35, readFileSync as readFileSync100, writeFileSync as writeFileSync34 } from "node:fs";
|
|
167955
|
+
import { dirname as dirname46, join as join84 } from "node:path";
|
|
167956
|
+
function withHeader(body) {
|
|
167957
|
+
return `${GENERATED_HEADER}${sha2566(body)}
|
|
167958
|
+
${body}`;
|
|
167959
|
+
}
|
|
167960
|
+
function isEdited(content) {
|
|
167961
|
+
const m2 = HEADER_RE.exec(content);
|
|
167962
|
+
return !m2 || sha2566(content.slice(m2[0].length)) !== m2[1];
|
|
167963
|
+
}
|
|
167964
|
+
function renderPlanModule(p2) {
|
|
167965
|
+
return `// The ${p2.name} screens' plan, derived from config.ts \`base44.entities\` by \`himi base44 screens\`
|
|
167966
|
+
// (himi docs base44-app-to-himi-app): the list (../${p2.ids.bundleList}), the detail
|
|
167967
|
+
// (../${p2.ids.bundleDetail}) and dev/entities.generated.ts all read it. Edit it to customise the
|
|
167968
|
+
// screens \u2014 the generator then leaves this file alone (skipped-edited) unless --force.
|
|
167969
|
+
import type { EntityScreenPlan } from "./entity-plan.js";
|
|
167970
|
+
|
|
167971
|
+
export const PLAN: EntityScreenPlan = ${json7(p2)};
|
|
167972
|
+
`;
|
|
167973
|
+
}
|
|
167974
|
+
function renderListEntry(p2) {
|
|
167975
|
+
return `// The ${p2.name} list (${p2.ids.list}) \u2014 generated by \`himi base44 screens\`. The behaviour lives in the
|
|
167976
|
+
// shared engine (../_shared/entity-list.ts); this file only names the entity's plan.
|
|
167977
|
+
import { defineEntityList } from "../_shared/entity-list.js";
|
|
167978
|
+
import { PLAN } from "../_shared/${planFile(p2)}.js";
|
|
167979
|
+
|
|
167980
|
+
export default defineEntityList(PLAN);
|
|
167981
|
+
`;
|
|
167982
|
+
}
|
|
167983
|
+
function renderDetailEntry(p2) {
|
|
167984
|
+
return `// One ${p2.name} (${p2.ids.detail}), pushed from ${p2.ids.list} with its id \u2014 generated by \`himi base44 screens\`.
|
|
167985
|
+
// The behaviour lives in the shared engine (../_shared/entity-detail.ts); this file only names the
|
|
167986
|
+
// entity's plan.
|
|
167987
|
+
import { defineEntityDetail } from "../_shared/entity-detail.js";
|
|
167988
|
+
import { PLAN } from "../_shared/${planFile(p2)}.js";
|
|
167989
|
+
|
|
167990
|
+
export default defineEntityDetail(PLAN);
|
|
167991
|
+
`;
|
|
167992
|
+
}
|
|
167993
|
+
function renderDevRegistrations(sp) {
|
|
167994
|
+
const plans = byName2(sp);
|
|
167995
|
+
const imports = sp.plans.map((p2) => `import { PLAN as ${ident(p2)} } from "../tier5-src/_shared/${planFile(p2)}.ts";`);
|
|
167996
|
+
const exact = sp.plans.flatMap((p2) => [
|
|
167997
|
+
` ${p2.ids.list}: (c?: BuildCtx) => entityListScreen(${ident(p2)}, c),`,
|
|
167998
|
+
` ${p2.ids.detail}: (c?: BuildCtx) => entityDetailScreen(${ident(p2)}, c),`
|
|
167999
|
+
]);
|
|
168000
|
+
const more = sp.more.map((n2) => ident(plans.get(n2)));
|
|
168001
|
+
if (more.length) exact.push(` ${MORE_SCREEN_ID}: () => entityMoreScreen([${more.join(", ")}]),`);
|
|
168002
|
+
const seed2 = sp.tabs.map((n2) => ` ${plans.get(n2).ids.list}: entityListScreen(${ident(plans.get(n2))}),`);
|
|
168003
|
+
if (more.length) seed2.push(` ${MORE_SCREEN_ID}: entityMoreScreen([${more.join(", ")}]),`);
|
|
168004
|
+
const home = sp.tabs.length ? JSON.stringify(plans.get(sp.tabs[0]).ids.list) : "undefined";
|
|
168005
|
+
return `// The generated entity screens' registrations \u2014 written by \`himi base44 screens\` from config.ts
|
|
168006
|
+
// \`base44.entities\`; dev/index.ts spreads them into screens.exact and seed.screens. The builders
|
|
168007
|
+
// are dev/entity-screens.ts.
|
|
168008
|
+
import type { BuildCtx } from "./dsl.ts";
|
|
168009
|
+
import { ${more.length ? "entityDetailScreen, entityListScreen, entityMoreScreen" : "entityDetailScreen, entityListScreen"} } from "./entity-screens.ts";
|
|
168010
|
+
${imports.join("\n")}${imports.length ? "\n" : ""}
|
|
168011
|
+
/** Every generated screen, by id. */
|
|
168012
|
+
export const entityScreens = {
|
|
168013
|
+
${exact.join("\n")}${exact.length ? "\n" : ""}};
|
|
168014
|
+
|
|
168015
|
+
/** The entity tab roots, seeded so the tab bar paints on a cold offline start. */
|
|
168016
|
+
export const entitySeedScreens = () => ({
|
|
168017
|
+
${seed2.join("\n")}${seed2.length ? "\n" : ""}});
|
|
168018
|
+
|
|
168019
|
+
/** The first entity tab \u2014 the app's home \u2014 or undefined when no entity is declared. */
|
|
168020
|
+
export const entityHomeScreenId: string | undefined = ${home};
|
|
168021
|
+
`;
|
|
168022
|
+
}
|
|
168023
|
+
function renderNav(sp) {
|
|
168024
|
+
const plans = byName2(sp);
|
|
168025
|
+
const tabbed = new Set(sp.tabs);
|
|
168026
|
+
const linkable = [];
|
|
168027
|
+
const tabs = [];
|
|
168028
|
+
for (const p2 of sp.plans) {
|
|
168029
|
+
const tabId = tabbed.has(p2.name) ? p2.ids.list.replace(/^b44_/, "") : "more";
|
|
168030
|
+
linkable.push({ screenId: p2.ids.list, isPublic: true, paramKeys: [], parentScreenId: tabbed.has(p2.name) ? "" : MORE_SCREEN_ID, tabId });
|
|
168031
|
+
linkable.push({ screenId: p2.ids.detail, isPublic: true, paramKeys: ["id"], parentScreenId: p2.ids.list, tabId });
|
|
168032
|
+
}
|
|
168033
|
+
for (const n2 of sp.tabs) {
|
|
168034
|
+
const p2 = plans.get(n2);
|
|
168035
|
+
tabs.push({ id: p2.ids.list.replace(/^b44_/, ""), screenId: p2.ids.list, label: p2.listTitle, icon: "list", selectedIcon: "list" });
|
|
168036
|
+
}
|
|
168037
|
+
if (sp.more.length) {
|
|
168038
|
+
linkable.push({ screenId: MORE_SCREEN_ID, isPublic: true, paramKeys: [], parentScreenId: "", tabId: "more" });
|
|
168039
|
+
tabs.push({ id: "more", screenId: MORE_SCREEN_ID, label: "More", icon: "grid", selectedIcon: "grid" });
|
|
168040
|
+
}
|
|
168041
|
+
const lines = (items) => items.map((i2) => ` ${JSON.stringify(i2)},`).join("\n");
|
|
168042
|
+
return `// The generated entity screens' navigation \u2014 written by \`himi base44 screens\` from config.ts
|
|
168043
|
+
// \`base44.entities\`. config.ts spreads these in front of the Functions and Account entries; tab
|
|
168044
|
+
// labels go through its copyOf("tab.<id>", \u2026) there, so copy overrides keep working.
|
|
168045
|
+
export const entityLinkableScreens = [
|
|
168046
|
+
${lines(linkable)}${linkable.length ? "\n" : ""}];
|
|
168047
|
+
|
|
168048
|
+
export const entityTabItems = [
|
|
168049
|
+
${lines(tabs)}${tabs.length ? "\n" : ""}];
|
|
168050
|
+
`;
|
|
168051
|
+
}
|
|
168052
|
+
function renderAll(sp) {
|
|
168053
|
+
const files = [];
|
|
168054
|
+
for (const p2 of sp.plans) {
|
|
168055
|
+
files.push({ path: `tier5-src/_shared/${planFile(p2)}.ts`, body: renderPlanModule(p2) });
|
|
168056
|
+
files.push({ path: `tier5-src/${p2.ids.bundleList}/index.ts`, body: renderListEntry(p2) });
|
|
168057
|
+
files.push({ path: `tier5-src/${p2.ids.bundleDetail}/index.ts`, body: renderDetailEntry(p2) });
|
|
168058
|
+
}
|
|
168059
|
+
files.push({ path: "dev/entities.generated.ts", body: renderDevRegistrations(sp) });
|
|
168060
|
+
files.push({ path: "config.entities.generated.ts", body: renderNav(sp) });
|
|
168061
|
+
return files;
|
|
168062
|
+
}
|
|
168063
|
+
function writeGenerated(dir, files, opts = {}) {
|
|
168064
|
+
const out2 = [];
|
|
168065
|
+
for (const f2 of files) {
|
|
168066
|
+
const abs = join84(dir, f2.path);
|
|
168067
|
+
const next = withHeader(f2.body);
|
|
168068
|
+
let outcome;
|
|
168069
|
+
if (!existsSync79(abs)) outcome = "written";
|
|
168070
|
+
else {
|
|
168071
|
+
const cur = readFileSync100(abs, "utf8");
|
|
168072
|
+
if (cur === next) outcome = "unchanged";
|
|
168073
|
+
else if (isEdited(cur) && !opts.force) outcome = "skipped-edited";
|
|
168074
|
+
else outcome = "written";
|
|
168075
|
+
}
|
|
168076
|
+
if (outcome === "written" && !opts.dryRun) {
|
|
168077
|
+
mkdirSync37(dirname46(abs), { recursive: true });
|
|
168078
|
+
writeFileSync34(abs, next);
|
|
168079
|
+
}
|
|
168080
|
+
out2.push({ path: f2.path, outcome });
|
|
168081
|
+
}
|
|
168082
|
+
return { files: out2 };
|
|
168083
|
+
}
|
|
168084
|
+
function orphanedFiles(dir, current) {
|
|
168085
|
+
const keep = new Set(current.map((f2) => f2.path));
|
|
168086
|
+
const found = [];
|
|
168087
|
+
const t5 = join84(dir, "tier5-src");
|
|
168088
|
+
if (!existsSync79(t5)) return found;
|
|
168089
|
+
const candidates = readdirSync35(t5).filter((d2) => d2.startsWith("b44-")).map((d2) => `tier5-src/${d2}/index.ts`);
|
|
168090
|
+
const shared = join84(t5, "_shared");
|
|
168091
|
+
if (existsSync79(shared)) {
|
|
168092
|
+
for (const f2 of readdirSync35(shared)) if (/^b44-.*-plan\.ts$/.test(f2)) candidates.push(`tier5-src/_shared/${f2}`);
|
|
168093
|
+
}
|
|
168094
|
+
for (const rel of candidates.sort()) {
|
|
168095
|
+
if (keep.has(rel) || !existsSync79(join84(dir, rel))) continue;
|
|
168096
|
+
if (readFileSync100(join84(dir, rel), "utf8").startsWith(GENERATED_HEADER)) found.push(rel);
|
|
168097
|
+
}
|
|
168098
|
+
return found;
|
|
168099
|
+
}
|
|
168100
|
+
var GENERATED_HEADER, HEADER_RE, ENGINE_FILES, sha2566, planFile, ident, json7, byName2;
|
|
168101
|
+
var init_generate = __esm({
|
|
168102
|
+
"src/base44-screens/generate.ts"() {
|
|
168103
|
+
init_plan4();
|
|
168104
|
+
GENERATED_HEADER = "// @generated by himi base44 screens \u2014 sha256:";
|
|
168105
|
+
HEADER_RE = /^\/\/ @generated by himi base44 screens — sha256:([0-9a-f]{64})\n/;
|
|
168106
|
+
ENGINE_FILES = ["tier5-src/_shared/entity-list.ts", "tier5-src/_shared/entity-detail.ts", "tier5-src/_shared/entity-plan.ts", "dev/entity-screens.ts"];
|
|
168107
|
+
sha2566 = (s2) => createHash43("sha256").update(s2).digest("hex");
|
|
168108
|
+
planFile = (p2) => `${p2.ids.bundleDetail}-plan`;
|
|
168109
|
+
ident = (p2) => `plan_${p2.ids.detail.replace(/^b44_/, "")}`;
|
|
168110
|
+
json7 = (v2) => JSON.stringify(v2, null, 2);
|
|
168111
|
+
byName2 = (sp) => new Map(sp.plans.map((p2) => [p2.name, p2]));
|
|
168112
|
+
}
|
|
168113
|
+
});
|
|
168114
|
+
|
|
167741
168115
|
// src/base44-auth.ts
|
|
167742
168116
|
var base44_auth_exports = {};
|
|
167743
168117
|
__export(base44_auth_exports, {
|
|
@@ -167755,20 +168129,20 @@ __export(base44_auth_exports, {
|
|
|
167755
168129
|
usableBase44Auth: () => usableBase44Auth,
|
|
167756
168130
|
writeBase44Session: () => writeBase44Session
|
|
167757
168131
|
});
|
|
167758
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
168132
|
+
import { chmodSync as chmodSync4, existsSync as existsSync80, mkdirSync as mkdirSync38, readFileSync as readFileSync101, rmSync as rmSync20, writeFileSync as writeFileSync35 } from "node:fs";
|
|
167759
168133
|
import { homedir as homedir13 } from "node:os";
|
|
167760
|
-
import { dirname as
|
|
168134
|
+
import { dirname as dirname47, join as join85 } from "node:path";
|
|
167761
168135
|
function base44ApiBase(env = process.env) {
|
|
167762
168136
|
return (env.BASE44_API_URL?.trim() || "https://app.base44.com").replace(/\/+$/, "");
|
|
167763
168137
|
}
|
|
167764
168138
|
function base44SessionPath(home = homedir13()) {
|
|
167765
|
-
return
|
|
168139
|
+
return join85(home, ".himi", "base44", "session.json");
|
|
167766
168140
|
}
|
|
167767
168141
|
function readBase44Session(home) {
|
|
167768
168142
|
const p2 = base44SessionPath(home);
|
|
167769
|
-
if (!
|
|
168143
|
+
if (!existsSync80(p2)) return void 0;
|
|
167770
168144
|
try {
|
|
167771
|
-
const s2 = JSON.parse(
|
|
168145
|
+
const s2 = JSON.parse(readFileSync101(p2, "utf8"));
|
|
167772
168146
|
return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
|
|
167773
168147
|
} catch {
|
|
167774
168148
|
return void 0;
|
|
@@ -167776,15 +168150,15 @@ function readBase44Session(home) {
|
|
|
167776
168150
|
}
|
|
167777
168151
|
function writeBase44Session(session, home) {
|
|
167778
168152
|
const p2 = base44SessionPath(home);
|
|
167779
|
-
|
|
167780
|
-
|
|
168153
|
+
mkdirSync38(dirname47(p2), { recursive: true, mode: 448 });
|
|
168154
|
+
writeFileSync35(p2, `${JSON.stringify(session, null, 2)}
|
|
167781
168155
|
`, { mode: 384 });
|
|
167782
168156
|
chmodSync4(p2, 384);
|
|
167783
168157
|
return p2;
|
|
167784
168158
|
}
|
|
167785
168159
|
function deleteBase44Session(home) {
|
|
167786
168160
|
const p2 = base44SessionPath(home);
|
|
167787
|
-
if (!
|
|
168161
|
+
if (!existsSync80(p2)) return false;
|
|
167788
168162
|
rmSync20(p2, { force: true });
|
|
167789
168163
|
return true;
|
|
167790
168164
|
}
|
|
@@ -167879,9 +168253,9 @@ async function base44DeviceLogin(opts) {
|
|
|
167879
168253
|
throw new Error("the Base44 sign-in code expired before it was approved \u2014 run `himi base44 login` again");
|
|
167880
168254
|
}
|
|
167881
168255
|
function importBase44CliSession(home = homedir13(), env = process.env) {
|
|
167882
|
-
const src =
|
|
167883
|
-
if (!
|
|
167884
|
-
const a2 = JSON.parse(
|
|
168256
|
+
const src = join85(home, ".base44", "auth", "auth.json");
|
|
168257
|
+
if (!existsSync80(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
|
|
168258
|
+
const a2 = JSON.parse(readFileSync101(src, "utf8"));
|
|
167885
168259
|
if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
|
|
167886
168260
|
const session = {
|
|
167887
168261
|
accessToken: a2.accessToken,
|
|
@@ -168671,9 +169045,9 @@ function asObj(x2) {
|
|
|
168671
169045
|
return x2 && typeof x2 === "object" && !Array.isArray(x2) ? x2 : void 0;
|
|
168672
169046
|
}
|
|
168673
169047
|
function invokeFlag(identities, key3) {
|
|
168674
|
-
const
|
|
168675
|
-
if (!
|
|
168676
|
-
return
|
|
169048
|
+
const ident2 = asObj(asObj(identities)?.[key3]);
|
|
169049
|
+
if (!ident2 || typeof ident2.invoke !== "boolean") return void 0;
|
|
169050
|
+
return ident2.invoke;
|
|
168677
169051
|
}
|
|
168678
169052
|
function methodStar(entry) {
|
|
168679
169053
|
return asObj(asObj(entry)?.["*"]);
|
|
@@ -170174,8 +170548,8 @@ var init_brand_font = __esm({
|
|
|
170174
170548
|
});
|
|
170175
170549
|
|
|
170176
170550
|
// src/site-analyze/write-artifacts.ts
|
|
170177
|
-
import { mkdirSync as
|
|
170178
|
-
import { join as
|
|
170551
|
+
import { mkdirSync as mkdirSync39, rmSync as rmSync21, writeFileSync as writeFileSync36 } from "node:fs";
|
|
170552
|
+
import { join as join86 } from "node:path";
|
|
170179
170553
|
function attachVeloSources(book, sources, put) {
|
|
170180
170554
|
const byPath = new Map((sources ?? []).map((s2) => [s2.path, s2.text]));
|
|
170181
170555
|
for (const f2 of book.velo.files) {
|
|
@@ -170330,13 +170704,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
170330
170704
|
}
|
|
170331
170705
|
async function writeBusinessBook(result, opts) {
|
|
170332
170706
|
const out2 = opts.outDir;
|
|
170333
|
-
|
|
170334
|
-
|
|
170707
|
+
mkdirSync39(join86(out2, "evidence/pages"), { recursive: true });
|
|
170708
|
+
mkdirSync39(join86(out2, "media/catalog"), { recursive: true });
|
|
170335
170709
|
const files = [];
|
|
170336
170710
|
const put = (rel, body) => {
|
|
170337
|
-
const p2 =
|
|
170338
|
-
|
|
170339
|
-
|
|
170711
|
+
const p2 = join86(out2, rel);
|
|
170712
|
+
mkdirSync39(join86(p2, ".."), { recursive: true });
|
|
170713
|
+
writeFileSync36(p2, body);
|
|
170340
170714
|
files.push(rel);
|
|
170341
170715
|
};
|
|
170342
170716
|
const book = result.book;
|
|
@@ -170378,7 +170752,7 @@ async function writeBusinessBook(result, opts) {
|
|
|
170378
170752
|
const allGated = shots.length > 0 && gatedPages.length > 0 && usablePages.length === 0;
|
|
170379
170753
|
put("README.md", folderReadme(shots.length > 0 && !allGated, book.look.unavailable, allGated));
|
|
170380
170754
|
put("evidence/probes.json", JSON.stringify(book.probes, null, 2) + "\n");
|
|
170381
|
-
rmSync21(
|
|
170755
|
+
rmSync21(join86(out2, "evidence/mobile-app"), { recursive: true, force: true });
|
|
170382
170756
|
for (const [name, value] of Object.entries(result.mobileAppEvidence ?? {})) {
|
|
170383
170757
|
if (/^[a-z-]+\.json$/.test(name)) put(`evidence/mobile-app/${name}`, JSON.stringify(value, null, 2) + "\n");
|
|
170384
170758
|
}
|
|
@@ -170609,7 +170983,7 @@ function readConnectors(files, dirs) {
|
|
|
170609
170983
|
return out2;
|
|
170610
170984
|
}
|
|
170611
170985
|
function providersOf(cfg) {
|
|
170612
|
-
const on4 = (camel2,
|
|
170986
|
+
const on4 = (camel2, snake2) => cfg[camel2] === true || cfg[snake2] === true;
|
|
170613
170987
|
const out2 = [];
|
|
170614
170988
|
if (on4("enableUsernamePassword", "enable_username_password")) out2.push("email-password");
|
|
170615
170989
|
if (on4("enableGoogleLogin", "enable_google_login")) out2.push("google");
|
|
@@ -171243,11 +171617,11 @@ var init_analyze = __esm({
|
|
|
171243
171617
|
});
|
|
171244
171618
|
|
|
171245
171619
|
// src/base44-analyze/write-artifacts.ts
|
|
171246
|
-
import { existsSync as
|
|
171247
|
-
import { dirname as
|
|
171620
|
+
import { existsSync as existsSync81, mkdirSync as mkdirSync40, readFileSync as readFileSync102, rmSync as rmSync22, writeFileSync as writeFileSync37 } from "node:fs";
|
|
171621
|
+
import { dirname as dirname48, join as join87, resolve as resolve60, sep as sep19 } from "node:path";
|
|
171248
171622
|
function isBookFolder(dir) {
|
|
171249
171623
|
try {
|
|
171250
|
-
return JSON.parse(
|
|
171624
|
+
return JSON.parse(readFileSync102(join87(dir, "book.json"), "utf8")).kind === "base44-app-book";
|
|
171251
171625
|
} catch {
|
|
171252
171626
|
return false;
|
|
171253
171627
|
}
|
|
@@ -171329,32 +171703,32 @@ function writeBase44Book(result, outDir, opts = {}) {
|
|
|
171329
171703
|
const shot = shots.find((s2) => page.screenshotLocal?.endsWith(s2.filename));
|
|
171330
171704
|
if (shot) page.screenshotLocal = `screenshots/${shot.filename}`;
|
|
171331
171705
|
}
|
|
171332
|
-
const
|
|
171706
|
+
const json8 = `${JSON.stringify(book, null, 2)}
|
|
171333
171707
|
`;
|
|
171334
171708
|
const md = renderBookMd(book);
|
|
171335
|
-
assertNoSecrets(
|
|
171709
|
+
assertNoSecrets(json8);
|
|
171336
171710
|
assertNoSecrets(md);
|
|
171337
|
-
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) =>
|
|
171711
|
+
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync81(join87(out2, n2)));
|
|
171338
171712
|
if (owned.length) {
|
|
171339
171713
|
if (!isBookFolder(out2)) throw new Error(`refusing to write the app book into ${out2}: it already has ${owned.join(", ")} that ${owned.length === 1 ? "is" : "are"} not from an app book \u2014 pick an empty --out`);
|
|
171340
|
-
for (const d2 of ["source", "screenshots"]) rmSync22(
|
|
171714
|
+
for (const d2 of ["source", "screenshots"]) rmSync22(join87(out2, d2), { recursive: true, force: true });
|
|
171341
171715
|
}
|
|
171342
|
-
|
|
171343
|
-
|
|
171344
|
-
|
|
171716
|
+
mkdirSync40(out2, { recursive: true });
|
|
171717
|
+
writeFileSync37(join87(out2, "book.json"), json8);
|
|
171718
|
+
writeFileSync37(join87(out2, "BOOK.md"), md);
|
|
171345
171719
|
files.push("book.json", "BOOK.md");
|
|
171346
171720
|
for (const s2 of shots) {
|
|
171347
|
-
|
|
171348
|
-
|
|
171721
|
+
mkdirSync40(join87(out2, "screenshots"), { recursive: true });
|
|
171722
|
+
writeFileSync37(join87(out2, "screenshots", s2.filename), s2.bytes);
|
|
171349
171723
|
files.push(`screenshots/${s2.filename}`);
|
|
171350
171724
|
}
|
|
171351
|
-
const sourceRoot =
|
|
171725
|
+
const sourceRoot = join87(out2, "source");
|
|
171352
171726
|
for (const f2 of result.sourceFiles) {
|
|
171353
171727
|
if (!safeRel(f2.path)) continue;
|
|
171354
|
-
const dest =
|
|
171728
|
+
const dest = join87(sourceRoot, ...f2.path.split("/"));
|
|
171355
171729
|
if (!dest.startsWith(sourceRoot + sep19)) continue;
|
|
171356
|
-
|
|
171357
|
-
|
|
171730
|
+
mkdirSync40(dirname48(dest), { recursive: true });
|
|
171731
|
+
writeFileSync37(dest, f2.bytes);
|
|
171358
171732
|
}
|
|
171359
171733
|
if (result.sourceFiles.length) files.push(`source/ (${result.sourceFiles.length} files)`);
|
|
171360
171734
|
return { outDir: out2, files };
|
|
@@ -174895,9 +175269,9 @@ __export(cli_exports, {
|
|
|
174895
175269
|
systemTar: () => systemTar
|
|
174896
175270
|
});
|
|
174897
175271
|
import { execFile } from "node:child_process";
|
|
174898
|
-
import { mkdirSync as
|
|
175272
|
+
import { mkdirSync as mkdirSync41, mkdtempSync as mkdtempSync5, rmSync as rmSync23, writeFileSync as writeFileSync38 } from "node:fs";
|
|
174899
175273
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
174900
|
-
import { join as
|
|
175274
|
+
import { join as join88, resolve as resolve61 } from "node:path";
|
|
174901
175275
|
import { promisify } from "node:util";
|
|
174902
175276
|
function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
174903
175277
|
return async (appId2) => {
|
|
@@ -174910,13 +175284,13 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
|
174910
175284
|
}
|
|
174911
175285
|
const bytes2 = await readCapped(res, MAX_TARBALL_BYTES);
|
|
174912
175286
|
if (!bytes2) throw new Error(`project download is over the ${MAX_TARBALL_BYTES}-byte cap`);
|
|
174913
|
-
const root = mkdtempSync5(
|
|
175287
|
+
const root = mkdtempSync5(join88(tmpdir6(), "himi-base44-"));
|
|
174914
175288
|
const cleanup = () => rmSync23(root, { recursive: true, force: true });
|
|
174915
175289
|
try {
|
|
174916
|
-
const archive =
|
|
174917
|
-
const dir =
|
|
174918
|
-
|
|
174919
|
-
|
|
175290
|
+
const archive = join88(root, "project.tar");
|
|
175291
|
+
const dir = join88(root, "project");
|
|
175292
|
+
writeFileSync38(archive, bytes2);
|
|
175293
|
+
mkdirSync41(dir);
|
|
174920
175294
|
await extract(archive, dir);
|
|
174921
175295
|
return { dir, cleanup };
|
|
174922
175296
|
} catch (e2) {
|
|
@@ -175135,7 +175509,7 @@ var init_errors2 = __esm({
|
|
|
175135
175509
|
});
|
|
175136
175510
|
|
|
175137
175511
|
// src/one-app/collect.ts
|
|
175138
|
-
import { createHash as
|
|
175512
|
+
import { createHash as createHash44 } from "node:crypto";
|
|
175139
175513
|
function isObject2(value) {
|
|
175140
175514
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
175141
175515
|
}
|
|
@@ -175207,7 +175581,7 @@ function semanticFingerprint(structure) {
|
|
|
175207
175581
|
}
|
|
175208
175582
|
return JSON.stringify(value);
|
|
175209
175583
|
};
|
|
175210
|
-
return
|
|
175584
|
+
return createHash44("sha256").update(canonical5(structure, true)).digest("hex");
|
|
175211
175585
|
}
|
|
175212
175586
|
async function collectOneApp(input, deps = {}) {
|
|
175213
175587
|
if (typeof input.metaSiteId !== "string" || !UUID.test(input.metaSiteId)) {
|
|
@@ -175831,9 +176205,9 @@ __export(cli_exports2, {
|
|
|
175831
176205
|
ONE_APP_WORKFLOW: () => ONE_APP_WORKFLOW,
|
|
175832
176206
|
runOneAppCommand: () => runOneAppCommand
|
|
175833
176207
|
});
|
|
175834
|
-
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as
|
|
175835
|
-
import { createHash as
|
|
175836
|
-
import { dirname as
|
|
176208
|
+
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync42, openSync as openSync6, readFileSync as readFileSync103, realpathSync as realpathSync14, writeFileSync as writeFileSync39 } from "node:fs";
|
|
176209
|
+
import { createHash as createHash45 } from "node:crypto";
|
|
176210
|
+
import { dirname as dirname49, join as join89, parse as parse3, resolve as resolve62 } from "node:path";
|
|
175837
176211
|
function readOptions(argv, cwd, commandIncluded) {
|
|
175838
176212
|
let cursor = 0;
|
|
175839
176213
|
const skipGlobalSwitches = () => {
|
|
@@ -175881,7 +176255,7 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
175881
176255
|
const file2 = resolve62(cwd, flags["prompt-file"]);
|
|
175882
176256
|
const stat2 = lstatSync21(file2);
|
|
175883
176257
|
if (!stat2.isFile() || stat2.size > MAX_PROMPT_BYTES) throw new Error("invalid prompt file");
|
|
175884
|
-
prompt =
|
|
176258
|
+
prompt = readFileSync103(file2, "utf8");
|
|
175885
176259
|
} catch {
|
|
175886
176260
|
throw new OneAppError("invalid_prompt", "Use a readable text file of at most 64 KiB for --prompt-file.");
|
|
175887
176261
|
}
|
|
@@ -175897,7 +176271,7 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
175897
176271
|
throw new OneAppError("invalid_output_path", "Pass a parent directory with --dir.");
|
|
175898
176272
|
}
|
|
175899
176273
|
const parentDir = resolve62(cwd, flags.dir ?? ".");
|
|
175900
|
-
const workspace =
|
|
176274
|
+
const workspace = join89(parentDir, name);
|
|
175901
176275
|
assertSafeParents(parentDir);
|
|
175902
176276
|
if (pathExists(workspace)) throw new OneAppError("output_exists", "The destination already exists. Choose a new --name or --dir.");
|
|
175903
176277
|
return { metaSiteId, appInstance, prompt, name, parentDir, workspace, target, topTabs };
|
|
@@ -175926,13 +176300,13 @@ function assertSafeParents(path2) {
|
|
|
175926
176300
|
throw new OneAppError("invalid_output_path", "The output parent cannot be inspected.");
|
|
175927
176301
|
}
|
|
175928
176302
|
}
|
|
175929
|
-
current =
|
|
176303
|
+
current = dirname49(current);
|
|
175930
176304
|
}
|
|
175931
176305
|
}
|
|
175932
176306
|
function writePrivate(path2, contents, append) {
|
|
175933
176307
|
const fd = openSync6(path2, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_NOFOLLOW | (append ? constants4.O_APPEND : constants4.O_EXCL), 384);
|
|
175934
176308
|
try {
|
|
175935
|
-
|
|
176309
|
+
writeFileSync39(fd, contents, { encoding: "utf8" });
|
|
175936
176310
|
} finally {
|
|
175937
176311
|
closeSync7(fd);
|
|
175938
176312
|
}
|
|
@@ -175954,7 +176328,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
175954
176328
|
const hashes = {};
|
|
175955
176329
|
const diskWrite = deps.writeFile ?? writePrivate;
|
|
175956
176330
|
const put = (name, content) => {
|
|
175957
|
-
const path2 =
|
|
176331
|
+
const path2 = join89(evidenceDir, name);
|
|
175958
176332
|
try {
|
|
175959
176333
|
assertSafeParents(evidenceDir);
|
|
175960
176334
|
diskWrite(path2, content, false);
|
|
@@ -175962,7 +176336,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
175962
176336
|
throw new OneAppError("artifact_write_failed", "Could not save the migration evidence. Existing files were kept.", { stage });
|
|
175963
176337
|
}
|
|
175964
176338
|
artifacts[name] = path2;
|
|
175965
|
-
hashes[name] =
|
|
176339
|
+
hashes[name] = createHash45("sha256").update(content).digest("hex");
|
|
175966
176340
|
return path2;
|
|
175967
176341
|
};
|
|
175968
176342
|
const progress = (nextStage) => {
|
|
@@ -175970,7 +176344,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
175970
176344
|
if (!evidenceDir) return;
|
|
175971
176345
|
try {
|
|
175972
176346
|
assertSafeParents(evidenceDir);
|
|
175973
|
-
diskWrite(
|
|
176347
|
+
diskWrite(join89(evidenceDir, "progress.jsonl"), JSON.stringify({ stage, at: now() }) + "\n", true);
|
|
175974
176348
|
} catch {
|
|
175975
176349
|
throw new OneAppError("artifact_write_failed", "Could not record migration progress. Existing files were kept.", { stage });
|
|
175976
176350
|
}
|
|
@@ -175982,12 +176356,12 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
175982
176356
|
try {
|
|
175983
176357
|
options = readOptions(argv, deps.cwd ?? process.cwd(), commandIncluded);
|
|
175984
176358
|
try {
|
|
175985
|
-
|
|
176359
|
+
mkdirSync42(options.parentDir, { recursive: true, mode: 448 });
|
|
175986
176360
|
assertSafeParents(options.parentDir);
|
|
175987
|
-
|
|
176361
|
+
mkdirSync42(options.workspace, { mode: 448 });
|
|
175988
176362
|
if (realpathSync14(options.workspace) !== options.workspace) throw new Error("destination changed");
|
|
175989
|
-
evidenceDir =
|
|
175990
|
-
|
|
176363
|
+
evidenceDir = join89(options.workspace, ".himi", "one-app");
|
|
176364
|
+
mkdirSync42(evidenceDir, { recursive: true, mode: 448 });
|
|
175991
176365
|
} catch (error) {
|
|
175992
176366
|
if (error.code === "EEXIST") {
|
|
175993
176367
|
throw new OneAppError("output_exists", "The destination already exists. Choose a new --name or --dir.");
|
|
@@ -177715,7 +178089,7 @@ var init_mobile_app = __esm({
|
|
|
177715
178089
|
return s2 || void 0;
|
|
177716
178090
|
};
|
|
177717
178091
|
strs2 = (v2) => arr(v2).filter((x2) => typeof x2 === "string");
|
|
177718
|
-
pick2 = (o2, camel2,
|
|
178092
|
+
pick2 = (o2, camel2, snake2) => o2[camel2] ?? o2[snake2];
|
|
177719
178093
|
outOfScope = (definitionId) => !!definitionId?.startsWith("ntt.");
|
|
177720
178094
|
empty = () => ({
|
|
177721
178095
|
tabs: [],
|
|
@@ -178123,8 +178497,8 @@ var init_customer_build = __esm({
|
|
|
178123
178497
|
});
|
|
178124
178498
|
|
|
178125
178499
|
// src/site-analyze/apply.ts
|
|
178126
|
-
import { existsSync as
|
|
178127
|
-
import { dirname as
|
|
178500
|
+
import { existsSync as existsSync82, readFileSync as readFileSync104, writeFileSync as writeFileSync40, copyFileSync as copyFileSync2, mkdirSync as mkdirSync43, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
|
|
178501
|
+
import { dirname as dirname50, isAbsolute as isAbsolute8, join as join90, resolve as resolve63, sep as sep20 } from "node:path";
|
|
178128
178502
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
178129
178503
|
function unpairedRedirectNote(overlay) {
|
|
178130
178504
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -178139,8 +178513,8 @@ function committedShellProvisioning(path2) {
|
|
|
178139
178513
|
function findRepoRoot(cwd) {
|
|
178140
178514
|
let dir = cwd;
|
|
178141
178515
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
178142
|
-
if (SHELL_NAMES2.some((name) =>
|
|
178143
|
-
const next =
|
|
178516
|
+
if (SHELL_NAMES2.some((name) => existsSync82(join90(dir, shellAppDir(name), "package.json")))) return dir;
|
|
178517
|
+
const next = dirname50(dir);
|
|
178144
178518
|
if (next === dir) break;
|
|
178145
178519
|
dir = next;
|
|
178146
178520
|
}
|
|
@@ -178242,11 +178616,11 @@ function sameKnownSite(previous, next) {
|
|
|
178242
178616
|
}
|
|
178243
178617
|
function buildMergedContract(options) {
|
|
178244
178618
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
178245
|
-
const committedPath =
|
|
178246
|
-
if (!
|
|
178619
|
+
const committedPath = join90(appDir3, "provisioning.json");
|
|
178620
|
+
if (!existsSync82(committedPath)) {
|
|
178247
178621
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
178248
178622
|
}
|
|
178249
|
-
const committed = JSON.parse(
|
|
178623
|
+
const committed = JSON.parse(readFileSync104(committedPath, "utf8"));
|
|
178250
178624
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
178251
178625
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
178252
178626
|
const branding = merged.branding ?? {};
|
|
@@ -178258,8 +178632,8 @@ function buildMergedContract(options) {
|
|
|
178258
178632
|
};
|
|
178259
178633
|
const stage = (fromRel, toRel) => {
|
|
178260
178634
|
const from = contained(packageDir, fromRel);
|
|
178261
|
-
const to2 = contained(
|
|
178262
|
-
if (!from || !to2 || !
|
|
178635
|
+
const to2 = contained(join90(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
178636
|
+
if (!from || !to2 || !existsSync82(from)) return void 0;
|
|
178263
178637
|
let real;
|
|
178264
178638
|
let realRoot;
|
|
178265
178639
|
try {
|
|
@@ -178271,7 +178645,7 @@ function buildMergedContract(options) {
|
|
|
178271
178645
|
if (!real.startsWith(realRoot + sep20)) return void 0;
|
|
178272
178646
|
try {
|
|
178273
178647
|
if (!statSync22(real).isFile()) return void 0;
|
|
178274
|
-
|
|
178648
|
+
mkdirSync43(dirname50(to2), { recursive: true });
|
|
178275
178649
|
copyFileSync2(real, to2);
|
|
178276
178650
|
} catch {
|
|
178277
178651
|
return void 0;
|
|
@@ -178281,11 +178655,11 @@ function buildMergedContract(options) {
|
|
|
178281
178655
|
};
|
|
178282
178656
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
178283
178657
|
if (icon) branding.appIconPath = icon;
|
|
178284
|
-
const facesPath =
|
|
178285
|
-
if (
|
|
178658
|
+
const facesPath = join90(packageDir, "media/fonts/faces.json");
|
|
178659
|
+
if (existsSync82(facesPath)) {
|
|
178286
178660
|
let faces = [];
|
|
178287
178661
|
try {
|
|
178288
|
-
const parsed = JSON.parse(
|
|
178662
|
+
const parsed = JSON.parse(readFileSync104(facesPath, "utf8"));
|
|
178289
178663
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
178290
178664
|
} catch {
|
|
178291
178665
|
faces = [];
|
|
@@ -178306,11 +178680,11 @@ function buildMergedContract(options) {
|
|
|
178306
178680
|
merged.branding = branding;
|
|
178307
178681
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
178308
178682
|
`;
|
|
178309
|
-
const path2 =
|
|
178310
|
-
|
|
178311
|
-
const localPath2 =
|
|
178312
|
-
|
|
178313
|
-
|
|
178683
|
+
const path2 = join90(packageDir, "provisioning.contract.json");
|
|
178684
|
+
writeFileSync40(path2, body);
|
|
178685
|
+
const localPath2 = join90(appDir3, LOCAL_CONTRACT_REL);
|
|
178686
|
+
mkdirSync43(dirname50(localPath2), { recursive: true });
|
|
178687
|
+
writeFileSync40(localPath2, body);
|
|
178314
178688
|
staged.push(localPath2);
|
|
178315
178689
|
return { path: path2, staged };
|
|
178316
178690
|
}
|
|
@@ -178343,10 +178717,10 @@ function catalogTypography(overlay, template) {
|
|
|
178343
178717
|
function staticFaqFor(overlay, overlayPath) {
|
|
178344
178718
|
const own5 = overlay.faq;
|
|
178345
178719
|
if (own5 !== void 0) return deriveStaticFaq(own5);
|
|
178346
|
-
const bookPath =
|
|
178347
|
-
if (!
|
|
178720
|
+
const bookPath = join90(dirname50(resolve63(overlayPath)), "book.json");
|
|
178721
|
+
if (!existsSync82(bookPath)) return void 0;
|
|
178348
178722
|
try {
|
|
178349
|
-
const book = JSON.parse(
|
|
178723
|
+
const book = JSON.parse(readFileSync104(bookPath, "utf8"));
|
|
178350
178724
|
const copy = book?.copy;
|
|
178351
178725
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
178352
178726
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -178360,10 +178734,10 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
178360
178734
|
if (overlay.galleries !== void 0) return deriveStaticGalleries(
|
|
178361
178735
|
overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
|
|
178362
178736
|
);
|
|
178363
|
-
const bookPath =
|
|
178364
|
-
if (!
|
|
178737
|
+
const bookPath = join90(dirname50(resolve63(overlayPath)), "book.json");
|
|
178738
|
+
if (!existsSync82(bookPath)) return void 0;
|
|
178365
178739
|
try {
|
|
178366
|
-
const book = JSON.parse(
|
|
178740
|
+
const book = JSON.parse(readFileSync104(bookPath, "utf8"));
|
|
178367
178741
|
if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
|
|
178368
178742
|
const galleries = deriveStaticGalleries(book.look.pages);
|
|
178369
178743
|
return galleries.length || book.look.complete === true ? galleries : void 0;
|
|
@@ -178375,8 +178749,8 @@ async function applyOverlays(input) {
|
|
|
178375
178749
|
const cwd = resolve63(input.cwd);
|
|
178376
178750
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
178377
178751
|
assertKnownShell(shell);
|
|
178378
|
-
const overlay = JSON.parse(
|
|
178379
|
-
const tokens2 = JSON.parse(
|
|
178752
|
+
const overlay = JSON.parse(readFileSync104(input.overlayPath, "utf8"));
|
|
178753
|
+
const tokens2 = JSON.parse(readFileSync104(input.tokensPath, "utf8"));
|
|
178380
178754
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
178381
178755
|
if (faq !== void 0) overlay.faq = faq;
|
|
178382
178756
|
const galleries = staticGalleriesFor(overlay, input.overlayPath);
|
|
@@ -178393,15 +178767,15 @@ async function applyOverlays(input) {
|
|
|
178393
178767
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
178394
178768
|
);
|
|
178395
178769
|
}
|
|
178396
|
-
const appDir3 =
|
|
178397
|
-
const committedPath =
|
|
178398
|
-
const committedSite =
|
|
178770
|
+
const appDir3 = join90(repoRoot2, shellAppDir(shell));
|
|
178771
|
+
const committedPath = join90(appDir3, "provisioning.json");
|
|
178772
|
+
const committedSite = existsSync82(committedPath) ? JSON.parse(readFileSync104(committedPath, "utf8")).site : void 0;
|
|
178399
178773
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
178400
178774
|
throw new Error(
|
|
178401
178775
|
`shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
|
|
178402
178776
|
);
|
|
178403
178777
|
}
|
|
178404
|
-
const packageDir =
|
|
178778
|
+
const packageDir = dirname50(resolve63(input.overlayPath));
|
|
178405
178779
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
178406
178780
|
wrote.push(...staged);
|
|
178407
178781
|
const r2 = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -178422,9 +178796,9 @@ async function applyOverlays(input) {
|
|
|
178422
178796
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
178423
178797
|
};
|
|
178424
178798
|
}
|
|
178425
|
-
const pkgProv =
|
|
178799
|
+
const pkgProv = join90(cwd, "provisioning.json");
|
|
178426
178800
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
178427
|
-
const contentPath =
|
|
178801
|
+
const contentPath = join90(cwd, "himalaya.content.json");
|
|
178428
178802
|
const syncViewNames = (before, after) => {
|
|
178429
178803
|
const content = readContentManifest(cwd);
|
|
178430
178804
|
if (!content) return;
|
|
@@ -178436,26 +178810,26 @@ async function applyOverlays(input) {
|
|
|
178436
178810
|
};
|
|
178437
178811
|
let packageFaq = faq;
|
|
178438
178812
|
let packageGalleries = galleries;
|
|
178439
|
-
if (
|
|
178440
|
-
const cur = JSON.parse(
|
|
178813
|
+
if (existsSync82(pkgProv)) {
|
|
178814
|
+
const cur = JSON.parse(readFileSync104(pkgProv, "utf8"));
|
|
178441
178815
|
if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
|
|
178442
178816
|
const merged = deepMerge4(cur, overlay);
|
|
178443
178817
|
packageFaq = merged.faq;
|
|
178444
178818
|
packageGalleries = merged.galleries;
|
|
178445
178819
|
syncViewNames(cur.site, merged.site);
|
|
178446
|
-
|
|
178820
|
+
writeFileSync40(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
178447
178821
|
wrote.push(pkgProv);
|
|
178448
178822
|
} else {
|
|
178449
178823
|
syncViewNames(void 0, overlay.site);
|
|
178450
|
-
|
|
178824
|
+
writeFileSync40(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
178451
178825
|
wrote.push(pkgProv);
|
|
178452
178826
|
}
|
|
178453
178827
|
if (Array.isArray(packageGalleries) && packageGalleries.length && !overlay.installedVerticals.includes("galleries")) {
|
|
178454
178828
|
overlay.installedVerticals.push("galleries");
|
|
178455
178829
|
}
|
|
178456
|
-
const pkgTokens =
|
|
178457
|
-
if (
|
|
178458
|
-
const cur = JSON.parse(
|
|
178830
|
+
const pkgTokens = join90(cwd, "tokens.json");
|
|
178831
|
+
if (existsSync82(pkgTokens) && (tokens2.colors || tokens2.typography)) {
|
|
178832
|
+
const cur = JSON.parse(readFileSync104(pkgTokens, "utf8"));
|
|
178459
178833
|
let tokensIn = tokens2;
|
|
178460
178834
|
if (tokens2.typography) {
|
|
178461
178835
|
const fonts = catalogTypography(tokens2.typography, cur.typography);
|
|
@@ -178476,13 +178850,13 @@ async function applyOverlays(input) {
|
|
|
178476
178850
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
178477
178851
|
stripBrandFromIdiom(merged);
|
|
178478
178852
|
}
|
|
178479
|
-
|
|
178853
|
+
writeFileSync40(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
178480
178854
|
wrote.push(pkgTokens);
|
|
178481
178855
|
}
|
|
178482
178856
|
const homeAction = homeRefreshActionId(shell);
|
|
178483
|
-
const homeSrc =
|
|
178484
|
-
if (homeAction &&
|
|
178485
|
-
const prev =
|
|
178857
|
+
const homeSrc = join90(cwd, "dev/index.ts");
|
|
178858
|
+
if (homeAction && existsSync82(homeSrc)) {
|
|
178859
|
+
const prev = readFileSync104(homeSrc, "utf8");
|
|
178486
178860
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
178487
178861
|
let next = patched.src;
|
|
178488
178862
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -178510,20 +178884,20 @@ async function applyOverlays(input) {
|
|
|
178510
178884
|
}
|
|
178511
178885
|
}
|
|
178512
178886
|
if (next !== prev) {
|
|
178513
|
-
|
|
178887
|
+
writeFileSync40(homeSrc, next);
|
|
178514
178888
|
wrote.push(homeSrc);
|
|
178515
178889
|
}
|
|
178516
178890
|
if (patched.unparsed) {
|
|
178517
178891
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
178518
178892
|
}
|
|
178519
178893
|
}
|
|
178520
|
-
if (!input.iconPath || !
|
|
178521
|
-
const book = input.iconPath ?
|
|
178894
|
+
if (!input.iconPath || !existsSync82(input.iconPath)) {
|
|
178895
|
+
const book = input.iconPath ? dirname50(dirname50(resolve63(input.iconPath))) : void 0;
|
|
178522
178896
|
notes.push(
|
|
178523
178897
|
book ? `no icon installed \u2014 ${siteLogoAbsence(book).hint}` : "no icon installed and no business book to say why \u2014 `himi icon generate` draws one from the accent, or `himi icon set <file.png>` installs the customer's own mark"
|
|
178524
178898
|
);
|
|
178525
178899
|
}
|
|
178526
|
-
if (input.iconPath &&
|
|
178900
|
+
if (input.iconPath && existsSync82(input.iconPath)) {
|
|
178527
178901
|
try {
|
|
178528
178902
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
178529
178903
|
wrote.push(...installed.wrote);
|
|
@@ -178886,13 +179260,13 @@ function parseMethod(raw) {
|
|
|
178886
179260
|
return m2;
|
|
178887
179261
|
}
|
|
178888
179262
|
function jsonFunctionSource(method, name, body) {
|
|
178889
|
-
const
|
|
179263
|
+
const json8 = JSON.stringify(body, null, 2).replace(/\n/g, "\n ");
|
|
178890
179264
|
return `import { ok } from 'wix-http-functions';
|
|
178891
179265
|
|
|
178892
179266
|
export function ${methodPrefix(method)}_${name}(request) {
|
|
178893
179267
|
return ok({
|
|
178894
179268
|
headers: { 'Content-Type': 'application/json' },
|
|
178895
|
-
body: ${
|
|
179269
|
+
body: ${json8},
|
|
178896
179270
|
});
|
|
178897
179271
|
}
|
|
178898
179272
|
`;
|
|
@@ -179218,12 +179592,12 @@ async function veloCall(fetchImpl, method, url, opts = {}) {
|
|
|
179218
179592
|
signal: AbortSignal.timeout(opts.timeoutMs ?? 3e4)
|
|
179219
179593
|
});
|
|
179220
179594
|
const text9 = await res.text();
|
|
179221
|
-
let
|
|
179595
|
+
let json8 = text9;
|
|
179222
179596
|
try {
|
|
179223
|
-
|
|
179597
|
+
json8 = text9 ? JSON.parse(text9) : null;
|
|
179224
179598
|
} catch {
|
|
179225
179599
|
}
|
|
179226
|
-
return { status: res.status, json:
|
|
179600
|
+
return { status: res.status, json: json8, text: text9 };
|
|
179227
179601
|
}
|
|
179228
179602
|
function snippet2(x2, cap = 180) {
|
|
179229
179603
|
const s2 = typeof x2 === "string" ? x2 : JSON.stringify(x2) ?? "";
|
|
@@ -179274,15 +179648,15 @@ async function patchHttpFunctionsFile(fetchImpl, token, msid, gridAppId, layout,
|
|
|
179274
179648
|
else body.filesToUpdate = [{ path: filePath, content }];
|
|
179275
179649
|
return veloCall(fetchImpl, "PATCH", veloUpdateFilesPath(gridAppId), { token, msid, body });
|
|
179276
179650
|
}
|
|
179277
|
-
function revisionFrom(
|
|
179278
|
-
if (!
|
|
179279
|
-
const r2 =
|
|
179651
|
+
function revisionFrom(json8) {
|
|
179652
|
+
if (!json8 || typeof json8 !== "object") return void 0;
|
|
179653
|
+
const r2 = json8;
|
|
179280
179654
|
const v2 = r2.siteRevision?.revision ?? r2.revision;
|
|
179281
179655
|
return v2 == null ? void 0 : String(v2);
|
|
179282
179656
|
}
|
|
179283
|
-
function codeAppIdFromRevision(
|
|
179284
|
-
if (!
|
|
179285
|
-
const actions =
|
|
179657
|
+
function codeAppIdFromRevision(json8) {
|
|
179658
|
+
if (!json8 || typeof json8 !== "object") return void 0;
|
|
179659
|
+
const actions = json8.actions;
|
|
179286
179660
|
if (!Array.isArray(actions)) return void 0;
|
|
179287
179661
|
for (const a2 of actions) {
|
|
179288
179662
|
if (!a2 || typeof a2 !== "object") continue;
|
|
@@ -179482,7 +179856,7 @@ __export(cli_exports3, {
|
|
|
179482
179856
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
179483
179857
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
179484
179858
|
});
|
|
179485
|
-
import { existsSync as
|
|
179859
|
+
import { existsSync as existsSync83, readFileSync as readFileSync105 } from "node:fs";
|
|
179486
179860
|
import { resolve as resolve64 } from "node:path";
|
|
179487
179861
|
function applyNeedsClient(shell) {
|
|
179488
179862
|
if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
|
|
@@ -179550,9 +179924,9 @@ async function runSiteAnalyze(opts) {
|
|
|
179550
179924
|
if (book?.skipped) result.warnings = [...result.warnings ?? [], book.skipped];
|
|
179551
179925
|
const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look, kind, routes });
|
|
179552
179926
|
const prevOverlayPath = resolve64(outDir, "provisioning.overlay.json");
|
|
179553
|
-
const prevSite =
|
|
179927
|
+
const prevSite = existsSync83(prevOverlayPath) ? (() => {
|
|
179554
179928
|
try {
|
|
179555
|
-
return JSON.parse(
|
|
179929
|
+
return JSON.parse(readFileSync105(prevOverlayPath, "utf8")).site;
|
|
179556
179930
|
} catch {
|
|
179557
179931
|
return void 0;
|
|
179558
179932
|
}
|
|
@@ -179571,7 +179945,7 @@ async function runSiteAnalyze(opts) {
|
|
|
179571
179945
|
}
|
|
179572
179946
|
const previousOverlay = resolve64(outDir, "provisioning.overlay.json");
|
|
179573
179947
|
carryOverGoals(
|
|
179574
|
-
|
|
179948
|
+
existsSync83(previousOverlay) ? readFileSync105(previousOverlay, "utf8") : void 0,
|
|
179575
179949
|
result.provisioningOverlay
|
|
179576
179950
|
);
|
|
179577
179951
|
const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
|
|
@@ -179629,7 +180003,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
179629
180003
|
let source;
|
|
179630
180004
|
if (opts.sourcePath) {
|
|
179631
180005
|
const p2 = resolve64(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
179632
|
-
source =
|
|
180006
|
+
source = readFileSync105(p2, "utf8");
|
|
179633
180007
|
}
|
|
179634
180008
|
let body;
|
|
179635
180009
|
if (opts.bodyRaw != null) {
|
|
@@ -179657,9 +180031,9 @@ async function runSiteFunctionCli(opts) {
|
|
|
179657
180031
|
});
|
|
179658
180032
|
}
|
|
179659
180033
|
function base44BookRoutes(bookPath, siteUrl) {
|
|
179660
|
-
if (!
|
|
180034
|
+
if (!existsSync83(bookPath)) return void 0;
|
|
179661
180035
|
try {
|
|
179662
|
-
const book = JSON.parse(
|
|
180036
|
+
const book = JSON.parse(readFileSync105(bookPath, "utf8"));
|
|
179663
180037
|
if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
|
|
179664
180038
|
const host = (u2) => {
|
|
179665
180039
|
try {
|
|
@@ -179914,7 +180288,7 @@ __export(site_create_exports, {
|
|
|
179914
180288
|
runSiteList: () => runSiteList,
|
|
179915
180289
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
179916
180290
|
});
|
|
179917
|
-
import { existsSync as
|
|
180291
|
+
import { existsSync as existsSync84, readFileSync as readFileSync106, writeFileSync as writeFileSync41 } from "node:fs";
|
|
179918
180292
|
import { resolve as resolvePath2 } from "node:path";
|
|
179919
180293
|
function oauthClientName(projectName) {
|
|
179920
180294
|
return `${projectName} client`;
|
|
@@ -180063,7 +180437,7 @@ async function runSiteCreate(opts) {
|
|
|
180063
180437
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
180064
180438
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
180065
180439
|
}
|
|
180066
|
-
function writeProvisioningBinding(target, binding2, fs2 = { existsSync:
|
|
180440
|
+
function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync84, readFileSync: readFileSync106, writeFileSync: writeFileSync41 }) {
|
|
180067
180441
|
const msid = binding2.siteId;
|
|
180068
180442
|
const path2 = resolvePath2(target);
|
|
180069
180443
|
const committed = committedShellProvisioning(path2);
|
|
@@ -180760,12 +181134,12 @@ var init_context = __esm({
|
|
|
180760
181134
|
});
|
|
180761
181135
|
|
|
180762
181136
|
// src/cli.ts
|
|
180763
|
-
import { mkdtempSync as mkdtempSync6, readFileSync as
|
|
181137
|
+
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync107, mkdirSync as mkdirSync44, writeFileSync as writeFileSync42, existsSync as existsSync85, rmSync as rmSync24, readdirSync as readdirSync36, statSync as statSync23, lstatSync as lstatSync22, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
|
|
180764
181138
|
import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
180765
181139
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
180766
|
-
import { createHash as
|
|
181140
|
+
import { createHash as createHash46, randomUUID as randomUUID11 } from "node:crypto";
|
|
180767
181141
|
import { tmpdir as tmpdir7, homedir as homedir14, hostname as hostname2 } from "node:os";
|
|
180768
|
-
import { join as
|
|
181142
|
+
import { join as join91, resolve as resolve65, relative as relative16, basename as basename21, dirname as dirname51 } from "node:path";
|
|
180769
181143
|
import { fileURLToPath as fileURLToPath29 } from "node:url";
|
|
180770
181144
|
|
|
180771
181145
|
// ../serve-cli/src/client.ts
|
|
@@ -180819,17 +181193,17 @@ var ServeCliClient = class {
|
|
|
180819
181193
|
body: opts.rawBody !== void 0 ? new Uint8Array(opts.rawBody) : opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
|
|
180820
181194
|
});
|
|
180821
181195
|
const text9 = await res.text();
|
|
180822
|
-
let
|
|
181196
|
+
let json8 = null;
|
|
180823
181197
|
try {
|
|
180824
|
-
|
|
181198
|
+
json8 = text9 ? JSON.parse(text9) : null;
|
|
180825
181199
|
} catch {
|
|
180826
|
-
|
|
181200
|
+
json8 = null;
|
|
180827
181201
|
}
|
|
180828
181202
|
const h2 = {};
|
|
180829
181203
|
res.headers.forEach((v2, k2) => {
|
|
180830
181204
|
h2[k2] = v2;
|
|
180831
181205
|
});
|
|
180832
|
-
return { status: res.status, ok: res.ok, json:
|
|
181206
|
+
return { status: res.status, ok: res.ok, json: json8, text: text9, headers: h2 };
|
|
180833
181207
|
}
|
|
180834
181208
|
// ---- serve (device-facing reads) ----
|
|
180835
181209
|
health(plane) {
|
|
@@ -181065,14 +181439,14 @@ var ServeCliClient = class {
|
|
|
181065
181439
|
const refusal = res.json;
|
|
181066
181440
|
const decodedOverPlainCap = res.status === 413 && refusal?.error === "payload_too_large" && refusal.limit === MAX_PUBLISH_BODY_BYTES && bytes2.byteLength <= MAX_PUBLISH_BODY_BYTES;
|
|
181067
181441
|
if (gzip && (res.status === 400 && refusal?.error === "bad_json" || decodedOverPlainCap)) {
|
|
181068
|
-
const
|
|
181442
|
+
const json8 = {
|
|
181069
181443
|
code: "compressed_publish_unsupported",
|
|
181070
181444
|
error: "compressed_publish_unsupported",
|
|
181071
181445
|
hint: "this body is over the plain publish cap, and the plane did not accept it compressed: either the plane predates compressed publish bodies (it needs a serve deploy), or this is a self-serve credential, which keeps the plain 8 MB cap",
|
|
181072
181446
|
sentBytes: bytes2.byteLength,
|
|
181073
181447
|
...typeof refusal?.bytes === "number" ? { planeCountedBytes: refusal.bytes } : {}
|
|
181074
181448
|
};
|
|
181075
|
-
return { ...res, json:
|
|
181449
|
+
return { ...res, json: json8, text: JSON.stringify(json8) };
|
|
181076
181450
|
}
|
|
181077
181451
|
return res;
|
|
181078
181452
|
}
|
|
@@ -181451,8 +181825,8 @@ var BO_WEWIX_COOKIE = "WixBoAuthentication-wewix";
|
|
|
181451
181825
|
function dpxCookieHeader(raw) {
|
|
181452
181826
|
const trimmed = raw.trim();
|
|
181453
181827
|
try {
|
|
181454
|
-
const
|
|
181455
|
-
const obj4 = JSON.parse(
|
|
181828
|
+
const json8 = Buffer.from(trimmed, "base64url").toString("utf8");
|
|
181829
|
+
const obj4 = JSON.parse(json8);
|
|
181456
181830
|
if (obj4 && typeof obj4 === "object") {
|
|
181457
181831
|
const pairs = [
|
|
181458
181832
|
typeof obj4.wewix === "string" ? `${BO_WEWIX_COOKIE}=${obj4.wewix}` : void 0,
|
|
@@ -182851,8 +183225,8 @@ var str10 = (v2) => typeof v2 === "string" ? v2 : void 0;
|
|
|
182851
183225
|
var num3 = (v2) => typeof v2 === "string" && v2 !== "" && Number.isFinite(Number(v2)) ? Number(v2) : void 0;
|
|
182852
183226
|
function embeddedTemplateCatalog() {
|
|
182853
183227
|
return availableTemplates().map((name) => {
|
|
182854
|
-
const path2 =
|
|
182855
|
-
const meta = JSON.parse(
|
|
183228
|
+
const path2 = join91(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
183229
|
+
const meta = JSON.parse(readFileSync107(path2, "utf8"));
|
|
182856
183230
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
182857
183231
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
182858
183232
|
}
|
|
@@ -183572,6 +183946,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
183572
183946
|
write tier5-src/_shared/base44-entities.ts: a row type and
|
|
183573
183947
|
a typed entities<Row>() handle per declared entity.
|
|
183574
183948
|
himi validate flags it base44-types-stale when stale.
|
|
183949
|
+
himi base44 screens [--content <dir>] [--force] [--dry-run] [--json]
|
|
183950
|
+
generate one list + detail screen per declared
|
|
183951
|
+
base44.entities entity (base44-starter packages), write
|
|
183952
|
+
controls gated by each entity's rls. Re-running is a
|
|
183953
|
+
no-op; a hand-edited generated file is skipped-edited
|
|
183954
|
+
unless --force. Never calls Base44.
|
|
183575
183955
|
himi base44 login [--from-base44-cli] | whoami | logout
|
|
183576
183956
|
the Base44 session, in ~/.himi/base44/ (never the repo).
|
|
183577
183957
|
BASE44_ACCESS_TOKEN wins, for CI.
|
|
@@ -183719,7 +184099,7 @@ var COMMANDS2 = [
|
|
|
183719
184099
|
{ name: "notify", summary: "Hosted --all-members requires --yes for a live send; --dry-run checks ownership/readiness and counts approved recipients without sending. `setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. `send --provider ping` is the hosted alternative: the serve plane sends to one site member (--member-email) or all approved members (--all-members) through Ping as Himalaya, with owner login instead of provider keys, and reports acceptance, never delivery. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send --provider ping [--content <dir>] [--app <a>] [--site <msid>] (--member-email <email> | --all-members (--dry-run | --yes)) --title <s> [--body <s>] --link <url> [--request-id <uuid>] [--dry-run] [--json] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
|
|
183720
184100
|
{ name: "signing", summary: "READ-ONLY App Store Connect inventory for customer BYO TestFlight readiness. `inspect` lists whether the bundle id, distribution certificate, IOS_APP_STORE profile, and ASC app record exist for --bundle-id / --team-id using a local ASC .p8 (flags or ASC_KEY_* env). Never uploads or mutates Apple resources. Optional --cert-file/--profile-file classify on-disk material.", required: "inspect --bundle-id <id> --team-id <id> --asc-key-file <path> --asc-key-id <id> --asc-issuer-id <id> [--cert-file <p12> --cert-password <pw> --profile-file <mobileprovision>] [--json]" },
|
|
183721
184101
|
{ name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no browser and never uploads or applies anything. A URL is optional there: `--url` lets it read the published page's Velo code-app ids (credential-free, pinned transport) so the backend source is found on sites where the owner code-app probe 404s. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell (a site shell needs no `--client-id`: it is visitor-only and binds no client); `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json. `member-app set|clear|show <msid>` is the site's member app in Spaces (#4091): the himi app the site's members open in Spaces Lite instead of Branded Lite. `set --app <id>` takes the site's own app or one your account owns (an owned app not yet tied to the site is linked first; another account's app is refused, 403); `clear` returns the site to Branded Lite; `show` prints the pick plus the COMPUTED verdict \u2014 the picked release's requirements judged against the Spaces host manifest (checkHostCompatibility, `--platform` to judge one phone platform) \u2014 and `reason` when it falls back to Branded Lite. Auth is your `himi login` control token plus the account `wix token`, which the plane uses to verify you own the site.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--url <https>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke] | member-app set|clear|show <msid> [--app <id>] [--platform ios|android]" },
|
|
183722
|
-
{ name: "base44", summary: "read a BASE44 app into an app book (book.json + BOOK.md) for the agent building a Himi app from it \u2014 the Base44 counterpart of `site analyze`, READ-ONLY. `analyze --url <published app>` is the VISITOR pass: the app id, name, favicon and colours from the published SPA, its router paths, and screenshots + look tokens from the Playwright crawl. `analyze --app-id <id>` adds the OWNER pass and needs a session: the project source under <out>/source/ (the read half of `base44 eject` \u2014 GET api/apps/<id>/eject \u2014 through the same deny-list and secret scan `himi push` uses, widened by the book's token shapes; `eject` itself is never run because it CREATES a copy of the app), every entity's JSON schema, required fields and RLS rules with up to --sample redacted rows (default 5, 0 = off), backend functions, agents, connectors (names and scopes only, never tokens), secret NAMES (never values), auth visibility + providers, and the route \u2192 component \u2192 entities map from the source router. Every chapter it could not read is listed in `gaps` rather than failing the run. `login` runs Base44's device sign-in and stores the session in ~/.himi/base44/session.json (never the repo; --from-base44-cli imports `npx base44 login`'s session instead); BASE44_ACCESS_TOKEN in the environment wins, for CI. `whoami` prints who is signed in (never the token); `logout` removes the stored session. `auth-check --url <tenant> --ios-app-id <PREFIX.bundle.id>` and/or `--android-package <package> --android-sha256 <fingerprint>` checks public native-login associations and prints missing entries; it never reads an owner token. --json prints the book itself. himi docs base44-app-context. `adopt` turns the book into a reviewable base44-entities.ts of ADOPTED entity + function declarations for config.ts (never edits config.ts, never overwrites); `entities query` is READ-ONLY and reports, per declared entity, ownership, row count and schema drift against the live app, plus foreign entities. `types` writes tier5-src/_shared/base44-entities.ts \u2014 a row type and a typed `entities<Row>()` handle per declared entity, byte-stable \u2014 and `himi validate` reports base44-types-stale when that file falls behind the block (nothing when it is absent). himi docs base44-entities", required: "analyze (--url <https://\u2026> | --app-id <id>) [--out .himi/base44-book] [--sample <n>] [--json] | adopt [--book .himi/base44-book] [--entities A,B] [--write [path]] [--json] | entities query [--content <dir>] [--all] [--json] | types [--content <dir>] [--json] | login [--from-base44-cli] | whoami | logout | auth-check --url <https://tenant> [--ios-app-id <PREFIX.bundle.id>] [--android-package <package> --android-sha256 <fingerprint>]" },
|
|
184102
|
+
{ name: "base44", summary: "read a BASE44 app into an app book (book.json + BOOK.md) for the agent building a Himi app from it \u2014 the Base44 counterpart of `site analyze`, READ-ONLY. `analyze --url <published app>` is the VISITOR pass: the app id, name, favicon and colours from the published SPA, its router paths, and screenshots + look tokens from the Playwright crawl. `analyze --app-id <id>` adds the OWNER pass and needs a session: the project source under <out>/source/ (the read half of `base44 eject` \u2014 GET api/apps/<id>/eject \u2014 through the same deny-list and secret scan `himi push` uses, widened by the book's token shapes; `eject` itself is never run because it CREATES a copy of the app), every entity's JSON schema, required fields and RLS rules with up to --sample redacted rows (default 5, 0 = off), backend functions, agents, connectors (names and scopes only, never tokens), secret NAMES (never values), auth visibility + providers, and the route \u2192 component \u2192 entities map from the source router. Every chapter it could not read is listed in `gaps` rather than failing the run. `login` runs Base44's device sign-in and stores the session in ~/.himi/base44/session.json (never the repo; --from-base44-cli imports `npx base44 login`'s session instead); BASE44_ACCESS_TOKEN in the environment wins, for CI. `whoami` prints who is signed in (never the token); `logout` removes the stored session. `auth-check --url <tenant> --ios-app-id <PREFIX.bundle.id>` and/or `--android-package <package> --android-sha256 <fingerprint>` checks public native-login associations and prints missing entries; it never reads an owner token. --json prints the book itself. himi docs base44-app-context. `adopt` turns the book into a reviewable base44-entities.ts of ADOPTED entity + function declarations for config.ts (never edits config.ts, never overwrites); `entities query` is READ-ONLY and reports, per declared entity, ownership, row count and schema drift against the live app, plus foreign entities. `types` writes tier5-src/_shared/base44-entities.ts \u2014 a row type and a typed `entities<Row>()` handle per declared entity, byte-stable \u2014 and `himi validate` reports base44-types-stale when that file falls behind the block (nothing when it is absent). himi docs base44-entities. `screens` (base44-starter packages) writes one generated list + detail screen per declared entity over the template's shared engine, with write controls gated by the entity's rls; an unchanged config reports every file `unchanged`, a hand-edited generated file is `skipped-edited` unless --force; never calls Base44. himi docs base44-app-to-himi-app", required: "analyze (--url <https://\u2026> | --app-id <id>) [--out .himi/base44-book] [--sample <n>] [--json] | adopt [--book .himi/base44-book] [--entities A,B] [--write [path]] [--json] | entities query [--content <dir>] [--all] [--json] | types [--content <dir>] [--json] | screens [--content <dir>] [--force] [--dry-run] [--json] | login [--from-base44-cli] | whoami | logout | auth-check --url <https://tenant> [--ios-app-id <PREFIX.bundle.id>] [--android-package <package> --android-sha256 <fingerprint>]" },
|
|
183723
184103
|
{ name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
|
|
183724
184104
|
{ name: "upgrade", summary: "install the newest published CLI (`npm i -g @wix/himalaya-cli@latest`) and report what moved. This is the explicit door: himi also updates itself when the running build is more than a week old \u2014 unattended it just does it and re-runs your command, at a terminal it asks first \u2014 and `HIMI_NO_UPDATE_CHECK=1` turns that off, leaving this command as the way to catch up. Reports `unchanged` rather than claiming success when npm exits 0 without moving the version, which is what a registry mirror serving its own pinned copy looks like.", required: "[--json]" },
|
|
183725
184105
|
{ name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. A successful draft push also rebuilds the making-of (.himi/making-of.html, local and offline) and names it as `reel` \u2014 the file to hand the owner beside the preview link. Its postcard carries the home shot only when that shot is newer than the last source edit; a repeat draft's postcard adds what changed since the last one (\"Since the last draft: the home screen changed.\", from the release manifests' screen hashes, remembered in .himi/last-draft.json); otherwise the postcard says why and names `himi render <home> --png`, and the envelope's `postcardPicture: {skipped, render}` leads next[] with that render (the push never renders it itself). The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one). An unforced push of a release that carries SCREENS also refuses when `.himi/ux-audit.json` holds no mobile-UX drive recorded against that release id, or holds one that FAILED (#2955) \u2014 a published draft IS the owner-private preview a customer is handed; `himi ux record` clears it and `--force` overrides it, which the success envelope then says out loud. `--only <selector>` publishes ONLY the named items as a release derived from the app's live release (or `--from-release <id>`), running the identical build + lint gate and simply publishing less; it requires an explicit `--draft` or `--live` because a partial publish has no safe default, never claims a slug, and carries neither attestation nor a source archive (both named in the output). Selectors are comma-separated in ONE `--only`: `changed` (every item whose bytes differ from the base), `screen:<id|glob>`, `bundle:<name>`, `tokens`, `app-config` \u2014 a selected screen drags its logic bundle and a selected bundle drags the screens that reference it, or the bytes land under a key nothing reads. The plane REFUSES (409 binary_capability_gap) a release declaring a PERMISSION-BEARING capability (iOS usage string or entitlement, Android permission \u2014 camera, location, push, \u2026) that the app's last successful `himi dist` was not built with: an OTA push cannot add an OS permission, and on iOS asking for one whose purpose string is missing kills the app. Run `himi dist` first, or pass `--allow-binary-gap` when every installed binary already carries it \u2014 recorded on the release as `allowedBinaryGap`. A gap in a permission-free capability (share, clipboard, \u2026) stays the `needsBinary` advice.", required: "[--content <dir>] [--draft] [--live] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--allow-binary-gap] [--no-claim] [--account-id <id>] [--only <selector>] [--from-release <id>] [--accept-regressions] [--accept-partial] [--app <slug>] (--control-token)" },
|
|
@@ -183761,7 +184141,7 @@ var COMMANDS2 = [
|
|
|
183761
184141
|
];
|
|
183762
184142
|
function cliVersion() {
|
|
183763
184143
|
try {
|
|
183764
|
-
return JSON.parse(
|
|
184144
|
+
return JSON.parse(readFileSync107(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
183765
184145
|
} catch {
|
|
183766
184146
|
return "unknown";
|
|
183767
184147
|
}
|
|
@@ -183852,10 +184232,10 @@ async function fetchPackumentFrom(registry2, fetchImpl, timeoutMs) {
|
|
|
183852
184232
|
signal: controller.signal
|
|
183853
184233
|
});
|
|
183854
184234
|
if (!response.ok) return void 0;
|
|
183855
|
-
const
|
|
183856
|
-
const latest = typeof
|
|
184235
|
+
const json8 = await response.json();
|
|
184236
|
+
const latest = typeof json8?.["dist-tags"]?.latest === "string" ? json8["dist-tags"].latest : void 0;
|
|
183857
184237
|
const time = {};
|
|
183858
|
-
for (const [version4, when] of Object.entries(
|
|
184238
|
+
for (const [version4, when] of Object.entries(json8?.time ?? {})) if (typeof when === "string") time[version4] = when;
|
|
183859
184239
|
return latest ? { latest, time, registry: normalizeRegistry(registry2) ?? registry2 } : void 0;
|
|
183860
184240
|
} catch {
|
|
183861
184241
|
return void 0;
|
|
@@ -183886,7 +184266,7 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
183886
184266
|
}
|
|
183887
184267
|
function packageVersion(path2) {
|
|
183888
184268
|
try {
|
|
183889
|
-
const version4 = JSON.parse(
|
|
184269
|
+
const version4 = JSON.parse(readFileSync107(path2, "utf8")).version;
|
|
183890
184270
|
return typeof version4 === "string" && version4 ? version4 : void 0;
|
|
183891
184271
|
} catch {
|
|
183892
184272
|
return void 0;
|
|
@@ -183895,9 +184275,9 @@ function packageVersion(path2) {
|
|
|
183895
184275
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
183896
184276
|
let dir = resolve65(fromDir);
|
|
183897
184277
|
for (; ; ) {
|
|
183898
|
-
const version4 = packageVersion(
|
|
184278
|
+
const version4 = packageVersion(join91(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
183899
184279
|
if (version4) return { version: version4, source: "local" };
|
|
183900
|
-
const parent =
|
|
184280
|
+
const parent = dirname51(dir);
|
|
183901
184281
|
if (parent === dir) break;
|
|
183902
184282
|
dir = parent;
|
|
183903
184283
|
}
|
|
@@ -183905,7 +184285,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
183905
184285
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
183906
184286
|
try {
|
|
183907
184287
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
183908
|
-
const version4 = root ? packageVersion(
|
|
184288
|
+
const version4 = root ? packageVersion(join91(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
183909
184289
|
return version4 ? { version: version4, source: "global" } : {};
|
|
183910
184290
|
} catch {
|
|
183911
184291
|
return {};
|
|
@@ -183952,11 +184332,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
183952
184332
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
183953
184333
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
183954
184334
|
function updateCachePath(env = process.env) {
|
|
183955
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
184335
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join91(homedir14(), ".himalaya", "update-check.json");
|
|
183956
184336
|
}
|
|
183957
184337
|
function readUpdateCache(path2) {
|
|
183958
184338
|
try {
|
|
183959
|
-
const parsed = JSON.parse(
|
|
184339
|
+
const parsed = JSON.parse(readFileSync107(path2, "utf8"));
|
|
183960
184340
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
183961
184341
|
} catch {
|
|
183962
184342
|
return {};
|
|
@@ -183964,8 +184344,8 @@ function readUpdateCache(path2) {
|
|
|
183964
184344
|
}
|
|
183965
184345
|
function writeUpdateCache(path2, cache) {
|
|
183966
184346
|
try {
|
|
183967
|
-
|
|
183968
|
-
|
|
184347
|
+
mkdirSync44(dirname51(path2), { recursive: true, mode: 448 });
|
|
184348
|
+
writeFileSync42(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
183969
184349
|
} catch {
|
|
183970
184350
|
}
|
|
183971
184351
|
}
|
|
@@ -184025,12 +184405,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
184025
184405
|
},
|
|
184026
184406
|
installedVersion: () => {
|
|
184027
184407
|
const root = globalNodeModulesRoot();
|
|
184028
|
-
return root ? packageVersion(
|
|
184408
|
+
return root ? packageVersion(join91(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
184029
184409
|
},
|
|
184030
184410
|
reexec: (argv) => {
|
|
184031
184411
|
const root = globalNodeModulesRoot();
|
|
184032
|
-
const entry = root ?
|
|
184033
|
-
if (!entry || !
|
|
184412
|
+
const entry = root ? join91(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
184413
|
+
if (!entry || !existsSync85(entry)) return void 0;
|
|
184034
184414
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
184035
184415
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
184036
184416
|
stdio: "inherit",
|
|
@@ -184077,7 +184457,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
184077
184457
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
184078
184458
|
let content;
|
|
184079
184459
|
try {
|
|
184080
|
-
content =
|
|
184460
|
+
content = readFileSync107(path2, "utf8");
|
|
184081
184461
|
} catch {
|
|
184082
184462
|
continue;
|
|
184083
184463
|
}
|
|
@@ -184100,14 +184480,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
184100
184480
|
const mine = lockStamp(now);
|
|
184101
184481
|
const readLock = (path2) => {
|
|
184102
184482
|
try {
|
|
184103
|
-
return
|
|
184483
|
+
return readFileSync107(path2, "utf8");
|
|
184104
184484
|
} catch {
|
|
184105
184485
|
return void 0;
|
|
184106
184486
|
}
|
|
184107
184487
|
};
|
|
184108
184488
|
const tryCreate = (path2) => {
|
|
184109
184489
|
try {
|
|
184110
|
-
|
|
184490
|
+
writeFileSync42(path2, mine, { flag: "wx", mode: 384 });
|
|
184111
184491
|
return true;
|
|
184112
184492
|
} catch {
|
|
184113
184493
|
return false;
|
|
@@ -184121,7 +184501,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
184121
184501
|
};
|
|
184122
184502
|
const release2 = () => removeIfMine(lockPath);
|
|
184123
184503
|
try {
|
|
184124
|
-
|
|
184504
|
+
mkdirSync44(dirname51(lockPath), { recursive: true, mode: 448 });
|
|
184125
184505
|
} catch {
|
|
184126
184506
|
return () => {
|
|
184127
184507
|
};
|
|
@@ -184692,7 +185072,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
184692
185072
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
184693
185073
|
for (const dir of entries) {
|
|
184694
185074
|
for (const suffix of suffixes) {
|
|
184695
|
-
const candidate =
|
|
185075
|
+
const candidate = join91(dir, `${name}${suffix}`);
|
|
184696
185076
|
try {
|
|
184697
185077
|
if (!statSync23(candidate).isFile()) continue;
|
|
184698
185078
|
if (process.platform !== "win32") accessSync(candidate, constants5.X_OK);
|
|
@@ -184801,7 +185181,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
184801
185181
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
184802
185182
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
184803
185183
|
const iosYmlPath = iosProjectYml2(app);
|
|
184804
|
-
const iosYml =
|
|
185184
|
+
const iosYml = existsSync85(iosYmlPath) ? readFileSync107(iosYmlPath, "utf8") : "";
|
|
184805
185185
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
184806
185186
|
if (!optedIn) {
|
|
184807
185187
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -184815,14 +185195,14 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
184815
185195
|
}
|
|
184816
185196
|
function readConfigSource(dir) {
|
|
184817
185197
|
try {
|
|
184818
|
-
return
|
|
185198
|
+
return readFileSync107(join91(dir, "config.ts"), "utf8");
|
|
184819
185199
|
} catch {
|
|
184820
185200
|
return null;
|
|
184821
185201
|
}
|
|
184822
185202
|
}
|
|
184823
185203
|
function writePngFile(path2, base64) {
|
|
184824
|
-
|
|
184825
|
-
|
|
185204
|
+
mkdirSync44(dirname51(path2), { recursive: true });
|
|
185205
|
+
writeFileSync42(path2, Buffer.from(base64, "base64"));
|
|
184826
185206
|
return path2;
|
|
184827
185207
|
}
|
|
184828
185208
|
async function seedAgentFilesFor(dir, flags, mode = "init") {
|
|
@@ -184869,7 +185249,7 @@ var NoBase44SlotError = class extends Error {
|
|
|
184869
185249
|
};
|
|
184870
185250
|
async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
|
|
184871
185251
|
const dir = resolve65(parentDir, name);
|
|
184872
|
-
if (
|
|
185252
|
+
if (existsSync85(join91(dir, "himalaya.content.json"))) {
|
|
184873
185253
|
throw new Error(`content package already exists at ${dir}`);
|
|
184874
185254
|
}
|
|
184875
185255
|
const r2 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -184915,11 +185295,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
184915
185295
|
function restoreDestinationIssue(dest, force) {
|
|
184916
185296
|
const link = symlinkDestinationIssue(dest);
|
|
184917
185297
|
if (link) return link;
|
|
184918
|
-
if (!
|
|
185298
|
+
if (!existsSync85(dest)) return null;
|
|
184919
185299
|
if (!statSync23(dest).isDirectory()) {
|
|
184920
185300
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
184921
185301
|
}
|
|
184922
|
-
if (
|
|
185302
|
+
if (readdirSync36(dest).length > 0 && !force) {
|
|
184923
185303
|
return {
|
|
184924
185304
|
error: `${dest} already exists and is not empty`,
|
|
184925
185305
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -184930,8 +185310,8 @@ function restoreDestinationIssue(dest, force) {
|
|
|
184930
185310
|
function isHimalayaMonorepoCheckout(start) {
|
|
184931
185311
|
let dir = resolve65(start);
|
|
184932
185312
|
for (; ; ) {
|
|
184933
|
-
if (
|
|
184934
|
-
const parent =
|
|
185313
|
+
if (existsSync85(join91(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync85(join91(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
185314
|
+
const parent = dirname51(dir);
|
|
184935
185315
|
if (parent === dir) return false;
|
|
184936
185316
|
dir = parent;
|
|
184937
185317
|
}
|
|
@@ -184982,7 +185362,7 @@ function templateNameError(name, from) {
|
|
|
184982
185362
|
const composed2 = TEMPLATE_APP_PREFIX + name;
|
|
184983
185363
|
return isValidAppId(composed2) ? null : `template name "${name}" (${from}) makes app id "${composed2}", which is over the serve plane's app-id length limit; pass a shorter --name`;
|
|
184984
185364
|
}
|
|
184985
|
-
function materializeForPreview(appDir3, slug,
|
|
185365
|
+
function materializeForPreview(appDir3, slug, displayName3) {
|
|
184986
185366
|
if (!isTemplateSourceTree(appDir3)) return appDir3;
|
|
184987
185367
|
const slugError = templateNameError(slug, "preview slug");
|
|
184988
185368
|
if (slugError) throw Object.assign(new Error(slugError), { exitCode: 2 });
|
|
@@ -184991,7 +185371,7 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
184991
185371
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
184992
185372
|
);
|
|
184993
185373
|
const repoRoot2 = resolve65(fileURLToPath29(new URL("../../..", import.meta.url)));
|
|
184994
|
-
const root =
|
|
185374
|
+
const root = join91(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
184995
185375
|
const stillRunning = (pid) => {
|
|
184996
185376
|
try {
|
|
184997
185377
|
process.kill(pid, 0);
|
|
@@ -185001,20 +185381,20 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
185001
185381
|
}
|
|
185002
185382
|
};
|
|
185003
185383
|
try {
|
|
185004
|
-
for (const entry of
|
|
185384
|
+
for (const entry of readdirSync36(root, { withFileTypes: true })) {
|
|
185005
185385
|
if (!entry.isDirectory()) continue;
|
|
185006
185386
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
185007
185387
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
185008
|
-
rmSync24(
|
|
185388
|
+
rmSync24(join91(root, entry.name), { recursive: true, force: true });
|
|
185009
185389
|
}
|
|
185010
185390
|
}
|
|
185011
185391
|
} catch {
|
|
185012
185392
|
}
|
|
185013
|
-
const dest =
|
|
185393
|
+
const dest = join91(root, `${slug}-${process.pid}`);
|
|
185014
185394
|
rmSync24(dest, { recursive: true, force: true });
|
|
185015
|
-
|
|
185395
|
+
mkdirSync44(dest, { recursive: true });
|
|
185016
185396
|
try {
|
|
185017
|
-
materializeSource(forBuild,
|
|
185397
|
+
materializeSource(forBuild, displayName3, dest, slug);
|
|
185018
185398
|
} catch (e2) {
|
|
185019
185399
|
rmSync24(dest, { recursive: true, force: true });
|
|
185020
185400
|
throw e2;
|
|
@@ -185023,8 +185403,8 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
185023
185403
|
}
|
|
185024
185404
|
async function appId(dir) {
|
|
185025
185405
|
try {
|
|
185026
|
-
const { readFileSync:
|
|
185027
|
-
const m2 = JSON.parse(
|
|
185406
|
+
const { readFileSync: readFileSync108 } = await import("node:fs");
|
|
185407
|
+
const m2 = JSON.parse(readFileSync108(join91(dir, "himalaya.content.json"), "utf8"));
|
|
185028
185408
|
if (m2.name) return m2.name;
|
|
185029
185409
|
} catch {
|
|
185030
185410
|
}
|
|
@@ -185032,8 +185412,8 @@ async function appId(dir) {
|
|
|
185032
185412
|
}
|
|
185033
185413
|
async function contentVisibility(dir) {
|
|
185034
185414
|
try {
|
|
185035
|
-
const { readFileSync:
|
|
185036
|
-
const m2 = JSON.parse(
|
|
185415
|
+
const { readFileSync: readFileSync108 } = await import("node:fs");
|
|
185416
|
+
const m2 = JSON.parse(readFileSync108(join91(dir, "himalaya.content.json"), "utf8"));
|
|
185037
185417
|
if (m2.visibility === "public" || m2.visibility === "unlisted") return m2.visibility;
|
|
185038
185418
|
} catch {
|
|
185039
185419
|
}
|
|
@@ -185325,7 +185705,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
185325
185705
|
...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
|
|
185326
185706
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
185327
185707
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
185328
|
-
...
|
|
185708
|
+
...existsSync85(join91(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
|
|
185329
185709
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
185330
185710
|
portalUrl: idx.portalUrl
|
|
185331
185711
|
});
|
|
@@ -185348,7 +185728,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
185348
185728
|
try {
|
|
185349
185729
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
185350
185730
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
185351
|
-
out2 = mkdtempSync6(
|
|
185731
|
+
out2 = mkdtempSync6(join91(tmpdir7(), "himi-ux-record-"));
|
|
185352
185732
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
185353
185733
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
185354
185734
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -185516,7 +185896,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
185516
185896
|
}
|
|
185517
185897
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
185518
185898
|
try {
|
|
185519
|
-
|
|
185899
|
+
readdirSync36(outDir);
|
|
185520
185900
|
} catch {
|
|
185521
185901
|
return { families: void 0, source: "unbuilt" };
|
|
185522
185902
|
}
|
|
@@ -185527,7 +185907,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
185527
185907
|
let js2;
|
|
185528
185908
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
185529
185909
|
try {
|
|
185530
|
-
js2 =
|
|
185910
|
+
js2 = readFileSync107(join91(outDir, candidate), "utf8");
|
|
185531
185911
|
break;
|
|
185532
185912
|
} catch {
|
|
185533
185913
|
}
|
|
@@ -185558,7 +185938,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
185558
185938
|
}
|
|
185559
185939
|
return { families, source: "dist/bundles" };
|
|
185560
185940
|
}
|
|
185561
|
-
var boardOpen = (dir) =>
|
|
185941
|
+
var boardOpen = (dir) => existsSync85(join91(dir, ".himi", "studio", "index.html"));
|
|
185562
185942
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
185563
185943
|
async function leaveForBoard(dir, record2, value) {
|
|
185564
185944
|
if (!boardOpen(dir)) return;
|
|
@@ -185582,7 +185962,7 @@ async function liveMapFor(dir) {
|
|
|
185582
185962
|
}
|
|
185583
185963
|
var commandScratch = new AsyncLocalStorage2();
|
|
185584
185964
|
function commandScratchDir(prefix) {
|
|
185585
|
-
const dir = mkdtempSync6(
|
|
185965
|
+
const dir = mkdtempSync6(join91(tmpdir7(), prefix));
|
|
185586
185966
|
commandScratch.getStore()?.push(dir);
|
|
185587
185967
|
return dir;
|
|
185588
185968
|
}
|
|
@@ -185936,7 +186316,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
185936
186316
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
185937
186317
|
next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
|
|
185938
186318
|
}
|
|
185939
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) =>
|
|
186319
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync85(join91(parentDir, f2)));
|
|
185940
186320
|
if (planInParent.length) {
|
|
185941
186321
|
next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
|
|
185942
186322
|
}
|
|
@@ -186097,13 +186477,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186097
186477
|
if (adding) {
|
|
186098
186478
|
const from = str10(flags.from);
|
|
186099
186479
|
if (!from) throw new TrimRefusal2('--add <id> needs --from <file> holding the whole new SCREENS entry (` "<id>": { "screenId": "<id>", \u2026 },`)');
|
|
186100
|
-
print(adopt.addScreen(dir, adding,
|
|
186480
|
+
print(adopt.addScreen(dir, adding, readFileSync107(from, "utf8"), { parent: str10(flags.parent), tab: str10(flags.tab), displayName: str10(flags["display-name"]) }));
|
|
186101
186481
|
return 0;
|
|
186102
186482
|
}
|
|
186103
186483
|
if (target) {
|
|
186104
186484
|
const from = str10(flags.from);
|
|
186105
186485
|
if (!from) throw new TrimRefusal2("--write <id> needs --from <file> holding the whole entry, as --show prints it");
|
|
186106
|
-
print(adopt.replaceScreen(dir, target,
|
|
186486
|
+
print(adopt.replaceScreen(dir, target, readFileSync107(from, "utf8")));
|
|
186107
186487
|
return 0;
|
|
186108
186488
|
}
|
|
186109
186489
|
if (show) {
|
|
@@ -186158,9 +186538,9 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186158
186538
|
try {
|
|
186159
186539
|
const r2 = await client2().templates();
|
|
186160
186540
|
const remote = (r2.json?.templates ?? []).filter((t2) => typeof t2.name === "string").map((t2) => ({ ...t2, source: "remote" }));
|
|
186161
|
-
const
|
|
186162
|
-
for (const t2 of remote)
|
|
186163
|
-
catalog3 = [...
|
|
186541
|
+
const byName3 = new Map(catalog3.map((c2) => [c2.name, c2]));
|
|
186542
|
+
for (const t2 of remote) byName3.set(t2.name, t2);
|
|
186543
|
+
catalog3 = [...byName3.values()];
|
|
186164
186544
|
} catch (e2) {
|
|
186165
186545
|
note = `remote catalog unreachable (${e2.message}); ranked the embedded templates only`;
|
|
186166
186546
|
}
|
|
@@ -186185,7 +186565,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186185
186565
|
const { keepFromSpec: keepFromSpec2 } = await Promise.resolve().then(() => (init_template_adopt(), template_adopt_exports));
|
|
186186
186566
|
const dir = contentDir(flags);
|
|
186187
186567
|
try {
|
|
186188
|
-
const spec = keepFromSpec2(dir, str10(flags["from-spec"]) ??
|
|
186568
|
+
const spec = keepFromSpec2(dir, str10(flags["from-spec"]) ?? join91(dir, "SPEC.md"));
|
|
186189
186569
|
const own5 = typeof keep === "string" ? keep.split(",").map((k2) => k2.trim()).filter(Boolean) : [];
|
|
186190
186570
|
keep = [.../* @__PURE__ */ new Set([...spec.keep, ...own5])].join(",");
|
|
186191
186571
|
fromSpec = { fromSpec: {
|
|
@@ -186226,7 +186606,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186226
186606
|
const result = { ...outcome.result, ...fromSpec };
|
|
186227
186607
|
const adoptDir = contentDir(flags);
|
|
186228
186608
|
const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
|
|
186229
|
-
if (kept &&
|
|
186609
|
+
if (kept && existsSync85(join91(adoptDir, adoptBits.ADOPT_FILE))) {
|
|
186230
186610
|
try {
|
|
186231
186611
|
const inv = adoptBits.inspectApp(adoptDir);
|
|
186232
186612
|
adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
|
|
@@ -186255,7 +186635,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186255
186635
|
const sourceDir = resolve65(str10(flags["source-dir"]) ?? appDir3);
|
|
186256
186636
|
let meta;
|
|
186257
186637
|
try {
|
|
186258
|
-
meta = JSON.parse(
|
|
186638
|
+
meta = JSON.parse(readFileSync107(join91(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
186259
186639
|
} catch {
|
|
186260
186640
|
io2.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
|
|
186261
186641
|
return 2;
|
|
@@ -186265,7 +186645,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186265
186645
|
return 2;
|
|
186266
186646
|
}
|
|
186267
186647
|
try {
|
|
186268
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
186648
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync107(join91(sourceDir, "tokens.json"), "utf8")));
|
|
186269
186649
|
meta = { ...appearance, ...meta };
|
|
186270
186650
|
} catch {
|
|
186271
186651
|
}
|
|
@@ -186287,7 +186667,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186287
186667
|
const force = flags.force === true;
|
|
186288
186668
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
186289
186669
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
186290
|
-
const out2 = mkdtempSync6(
|
|
186670
|
+
const out2 = mkdtempSync6(join91(tmpdir7(), "himi-template-"));
|
|
186291
186671
|
publishScratch.push(out2);
|
|
186292
186672
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
186293
186673
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
@@ -186349,9 +186729,9 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186349
186729
|
let iconHash;
|
|
186350
186730
|
if (iconPath) {
|
|
186351
186731
|
try {
|
|
186352
|
-
const bytes2 =
|
|
186732
|
+
const bytes2 = readFileSync107(iconPath);
|
|
186353
186733
|
payload.icon = bytes2.toString("base64");
|
|
186354
|
-
iconHash =
|
|
186734
|
+
iconHash = createHash46("sha256").update(bytes2).digest("hex");
|
|
186355
186735
|
} catch {
|
|
186356
186736
|
}
|
|
186357
186737
|
}
|
|
@@ -186561,12 +186941,12 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186561
186941
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
186562
186942
|
return 2;
|
|
186563
186943
|
}
|
|
186564
|
-
const { readdirSync:
|
|
186944
|
+
const { readdirSync: readdirSync37, existsSync: fileExists } = await import("node:fs");
|
|
186565
186945
|
const { join: pathJoin3 } = await import("node:path");
|
|
186566
186946
|
const targets = [];
|
|
186567
186947
|
const t5 = pathJoin3(dir, "tier5-src");
|
|
186568
186948
|
if (fileExists(t5)) {
|
|
186569
|
-
for (const d2 of
|
|
186949
|
+
for (const d2 of readdirSync37(t5, { withFileTypes: true })) {
|
|
186570
186950
|
if (d2.isDirectory()) targets.push(pathJoin3(t5, d2.name, "index.ts"));
|
|
186571
186951
|
}
|
|
186572
186952
|
}
|
|
@@ -186654,7 +187034,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186654
187034
|
const path2 = dpxSessionTokenPath();
|
|
186655
187035
|
let raw;
|
|
186656
187036
|
try {
|
|
186657
|
-
raw =
|
|
187037
|
+
raw = readFileSync107(path2, "utf8");
|
|
186658
187038
|
} catch {
|
|
186659
187039
|
throw new Error(`no DPX BO session at ${path2}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
|
|
186660
187040
|
}
|
|
@@ -186788,8 +187168,8 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186788
187168
|
const dir = resolve65(out2);
|
|
186789
187169
|
const files = himiPluginFiles2(skills.skillMd);
|
|
186790
187170
|
for (const f2 of files) {
|
|
186791
|
-
|
|
186792
|
-
|
|
187171
|
+
mkdirSync44(dirname51(join91(dir, f2.path)), { recursive: true });
|
|
187172
|
+
writeFileSync42(join91(dir, f2.path), f2.text);
|
|
186793
187173
|
}
|
|
186794
187174
|
print({ ok: true, dir, files: files.map((f2) => f2.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
186795
187175
|
return 0;
|
|
@@ -186806,16 +187186,16 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
186806
187186
|
case "studio": {
|
|
186807
187187
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
186808
187188
|
const dir = contentDir(flags);
|
|
186809
|
-
if (!
|
|
187189
|
+
if (!existsSync85(join91(dir, "himalaya.content.json"))) {
|
|
186810
187190
|
io2.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
|
|
186811
187191
|
return 2;
|
|
186812
187192
|
}
|
|
186813
187193
|
if (pos[1] === "reel") {
|
|
186814
187194
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
186815
|
-
const out2 = resolve65(str10(flags.out) ??
|
|
187195
|
+
const out2 = resolve65(str10(flags.out) ?? join91(dir, ".himi", "making-of.html"));
|
|
186816
187196
|
const { html, plan } = buildReel2(dir);
|
|
186817
|
-
|
|
186818
|
-
|
|
187197
|
+
mkdirSync44(dirname51(out2), { recursive: true });
|
|
187198
|
+
writeFileSync42(out2, html);
|
|
186819
187199
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
186820
187200
|
const url2 = pathToFileURL9(out2).href;
|
|
186821
187201
|
const open2 = flags["no-open"] !== true;
|
|
@@ -186884,7 +187264,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
186884
187264
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
186885
187265
|
const dir = contentDir(flags);
|
|
186886
187266
|
const journal2 = journalPath2(dir);
|
|
186887
|
-
const isContentPackage =
|
|
187267
|
+
const isContentPackage = existsSync85(join91(dir, "himalaya.content.json"));
|
|
186888
187268
|
const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
|
|
186889
187269
|
const message = pos.slice(1).join(" ").trim();
|
|
186890
187270
|
const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
|
|
@@ -187036,7 +187416,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
187036
187416
|
case "test": {
|
|
187037
187417
|
const dir = contentDir(flags);
|
|
187038
187418
|
const structuredOutput = flags.json === true || io2.isTTY !== true;
|
|
187039
|
-
if (
|
|
187419
|
+
if (existsSync85(join91(dir, "functions"))) {
|
|
187040
187420
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
187041
187421
|
const loaded = await loadFunctionsApp2(dir);
|
|
187042
187422
|
const results = [];
|
|
@@ -187168,7 +187548,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
187168
187548
|
io2.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
187169
187549
|
return 2;
|
|
187170
187550
|
}
|
|
187171
|
-
const sources = collectWorkerSources2(
|
|
187551
|
+
const sources = collectWorkerSources2(join91(dir, "tier5-src"), screen.bundleName);
|
|
187172
187552
|
if (!sources) {
|
|
187173
187553
|
io2.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
187174
187554
|
return 2;
|
|
@@ -187348,7 +187728,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
187348
187728
|
const sp = await runShotsPass2({
|
|
187349
187729
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
187350
187730
|
tokens: outcome.tokens,
|
|
187351
|
-
outDir:
|
|
187731
|
+
outDir: join91(dir, ".himi", "shots"),
|
|
187352
187732
|
width: 390,
|
|
187353
187733
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {}, ...base44Data ? { base44Data } : {} },
|
|
187354
187734
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -187388,7 +187768,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
187388
187768
|
releaseId: result.releaseId,
|
|
187389
187769
|
releasePayload: release2,
|
|
187390
187770
|
descriptors: attestedDescriptors,
|
|
187391
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
187771
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join91(dir, ".himi", "shots", name)])),
|
|
187392
187772
|
coverage: {
|
|
187393
187773
|
screens: crawledScreens.size,
|
|
187394
187774
|
actionsDispatched: result.actions.exercised,
|
|
@@ -187513,7 +187893,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
187513
187893
|
return 2;
|
|
187514
187894
|
}
|
|
187515
187895
|
try {
|
|
187516
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
187896
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync107(stateArg.replace(/^@/, ""), "utf8");
|
|
187517
187897
|
injectedState = JSON.parse(raw);
|
|
187518
187898
|
} catch (e2) {
|
|
187519
187899
|
io2.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e2.message}` }));
|
|
@@ -187528,7 +187908,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
187528
187908
|
return 2;
|
|
187529
187909
|
}
|
|
187530
187910
|
try {
|
|
187531
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
187911
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync107(inputArg.replace(/^@/, ""), "utf8");
|
|
187532
187912
|
const parsed = JSON.parse(raw);
|
|
187533
187913
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
187534
187914
|
injectedInput = parsed;
|
|
@@ -187611,7 +187991,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
187611
187991
|
const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
|
|
187612
187992
|
let pngFile;
|
|
187613
187993
|
let attestationPngFile;
|
|
187614
|
-
const shotPath =
|
|
187994
|
+
const shotPath = join91(dir, ".himi", "shots", `${screenId}.png`);
|
|
187615
187995
|
const pngTarget = typeof flags.png === "string" ? str10(flags.png) : flags.png === true ? shotPath : void 0;
|
|
187616
187996
|
if (pngTarget && r2.pngBase64) {
|
|
187617
187997
|
pngFile = writePngFile(pngTarget, r2.pngBase64);
|
|
@@ -187970,7 +188350,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
187970
188350
|
io2.error(JSON.stringify(linked));
|
|
187971
188351
|
return 1;
|
|
187972
188352
|
}
|
|
187973
|
-
if (
|
|
188353
|
+
if (existsSync85(dest)) {
|
|
187974
188354
|
if (!statSync23(dest).isDirectory()) {
|
|
187975
188355
|
io2.error(JSON.stringify({
|
|
187976
188356
|
error: `${dest} exists and is not a directory`,
|
|
@@ -187978,12 +188358,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
187978
188358
|
}));
|
|
187979
188359
|
return 1;
|
|
187980
188360
|
}
|
|
187981
|
-
const occupied =
|
|
188361
|
+
const occupied = readdirSync36(dest).length > 0;
|
|
187982
188362
|
if (occupied && !force) {
|
|
187983
188363
|
io2.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
|
|
187984
188364
|
return 1;
|
|
187985
188365
|
}
|
|
187986
|
-
if (replace && occupied && !
|
|
188366
|
+
if (replace && occupied && !existsSync85(join91(dest, "himalaya.content.json"))) {
|
|
187987
188367
|
io2.error(JSON.stringify({
|
|
187988
188368
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
187989
188369
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -188219,7 +188599,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188219
188599
|
let localSourceHash;
|
|
188220
188600
|
try {
|
|
188221
188601
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
188222
|
-
localSourceHash =
|
|
188602
|
+
localSourceHash = createHash46("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
188223
188603
|
} catch {
|
|
188224
188604
|
}
|
|
188225
188605
|
return runReleasePatch({
|
|
@@ -188628,9 +189008,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188628
189008
|
return 2;
|
|
188629
189009
|
}
|
|
188630
189010
|
const { packRelease: packRelease2, packReleaseToDir: packReleaseToDir2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
188631
|
-
const
|
|
189011
|
+
const displayName3 = str10(flags.name);
|
|
188632
189012
|
const launchMode = flags.snapshot === true ? "snapshot" : "live";
|
|
188633
|
-
const packOpts = { createdBy: `himi-cli ${cliVersion()}`, launchMode, ...
|
|
189013
|
+
const packOpts = { createdBy: `himi-cli ${cliVersion()}`, launchMode, ...displayName3 ? { displayName: displayName3 } : {} };
|
|
188634
189014
|
const writePack = (root, appName2, out2, source) => format === "dir" ? packReleaseToDir2(root, appName2, out2, packOpts) : packRelease2(root, appName2, out2, { ...packOpts, ...source ? { source } : {} });
|
|
188635
189015
|
const releaseDir = str10(flags["release-dir"]);
|
|
188636
189016
|
if (releaseDir) {
|
|
@@ -188696,7 +189076,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188696
189076
|
}
|
|
188697
189077
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
188698
189078
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
188699
|
-
const built = mkdtempSync6(
|
|
189079
|
+
const built = mkdtempSync6(join91(tmpdir7(), "himi-pack-"));
|
|
188700
189080
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
188701
189081
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
188702
189082
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -188909,7 +189289,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188909
189289
|
}));
|
|
188910
189290
|
return 1;
|
|
188911
189291
|
}
|
|
188912
|
-
const archive =
|
|
189292
|
+
const archive = readFileSync107(resolve65(file2));
|
|
188913
189293
|
const result = await client2().createPackageShare({
|
|
188914
189294
|
app: opened.header.app,
|
|
188915
189295
|
releaseId: opened.header.releaseId,
|
|
@@ -189006,11 +189386,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189006
189386
|
const app = await appId(dir2);
|
|
189007
189387
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
189008
189388
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
189009
|
-
temp = mkdtempSync6(
|
|
189389
|
+
temp = mkdtempSync6(join91(tmpdir7(), "himi-run-build-"));
|
|
189010
189390
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
189011
189391
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
189012
189392
|
servedMissing = initial.missingBundles;
|
|
189013
|
-
source =
|
|
189393
|
+
source = join91(temp, app);
|
|
189014
189394
|
}
|
|
189015
189395
|
const chromeArg = str10(flags.chrome) ?? "preview";
|
|
189016
189396
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -189049,7 +189429,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189049
189429
|
if (!recordKit) return;
|
|
189050
189430
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
189051
189431
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
189052
|
-
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
189432
|
+
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join91(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
189053
189433
|
await refreshBoard();
|
|
189054
189434
|
};
|
|
189055
189435
|
const retract = async () => {
|
|
@@ -189085,7 +189465,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189085
189465
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
189086
189466
|
const hhpPreviewRoute = watch2 ? (await Promise.resolve().then(() => (init_hhp_preview(), hhp_preview_exports))).hhpPreviewResponse : null;
|
|
189087
189467
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
189088
|
-
if (watch2) served = mkdtempSync6(
|
|
189468
|
+
if (watch2) served = mkdtempSync6(join91(tmpdir7(), "himi-run-served-"));
|
|
189089
189469
|
const running = await runPackage2(source, {
|
|
189090
189470
|
port,
|
|
189091
189471
|
chrome: chromeArg,
|
|
@@ -189114,8 +189494,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189114
189494
|
await announce(running);
|
|
189115
189495
|
if (watchKit && bus) {
|
|
189116
189496
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
189117
|
-
const live3 =
|
|
189118
|
-
const manifestOf = (tree) => JSON.parse(
|
|
189497
|
+
const live3 = join91(running.releaseRoot, running.app);
|
|
189498
|
+
const manifestOf = (tree) => JSON.parse(readFileSync107(join91(tree, "release-manifest.json"), "utf8"));
|
|
189119
189499
|
let current = manifestOf(live3);
|
|
189120
189500
|
const failed3 = async (message) => {
|
|
189121
189501
|
if (stopping) return;
|
|
@@ -189126,7 +189506,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189126
189506
|
};
|
|
189127
189507
|
rebuild = watchKit.serialize(async () => {
|
|
189128
189508
|
const t0 = Date.now();
|
|
189129
|
-
const next = mkdtempSync6(
|
|
189509
|
+
const next = mkdtempSync6(join91(tmpdir7(), "himi-run-build-"));
|
|
189130
189510
|
try {
|
|
189131
189511
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
189132
189512
|
if (bres.compileErrors.length) {
|
|
@@ -189143,16 +189523,16 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189143
189523
|
return;
|
|
189144
189524
|
}
|
|
189145
189525
|
if (stopping) return;
|
|
189146
|
-
const fresh = manifestOf(
|
|
189526
|
+
const fresh = manifestOf(join91(next, running.app));
|
|
189147
189527
|
const diff = watchKit.diffReleases(current, fresh);
|
|
189148
189528
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
189149
|
-
const changes = describeChanges2(live3,
|
|
189529
|
+
const changes = describeChanges2(live3, join91(next, running.app), diff);
|
|
189150
189530
|
const retired = `${live3}.retired-${Date.now()}`;
|
|
189151
189531
|
renameSync13(live3, retired);
|
|
189152
189532
|
try {
|
|
189153
|
-
renameSync13(
|
|
189533
|
+
renameSync13(join91(next, running.app), live3);
|
|
189154
189534
|
} catch {
|
|
189155
|
-
cpSync3(
|
|
189535
|
+
cpSync3(join91(next, running.app), live3, { recursive: true });
|
|
189156
189536
|
}
|
|
189157
189537
|
rmSync24(retired, { recursive: true, force: true });
|
|
189158
189538
|
current = fresh;
|
|
@@ -189779,7 +190159,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189779
190159
|
io2.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
189780
190160
|
return 2;
|
|
189781
190161
|
}
|
|
189782
|
-
if (!
|
|
190162
|
+
if (!existsSync85(file2)) {
|
|
189783
190163
|
io2.error(JSON.stringify({ error: `no such file: ${file2}` }));
|
|
189784
190164
|
return 2;
|
|
189785
190165
|
}
|
|
@@ -189835,7 +190215,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189835
190215
|
lintNote: "`himi patch` sends a raw file. Nothing here built or linted your app \u2014 `himi push --only <selector>` is the same edit with the full lint gate in front of it."
|
|
189836
190216
|
};
|
|
189837
190217
|
if (kind === "tokens" || kind === "app-config") {
|
|
189838
|
-
const body =
|
|
190218
|
+
const body = readFileSync107(file2, "utf8");
|
|
189839
190219
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
189840
190220
|
return runReleasePatch({
|
|
189841
190221
|
...common,
|
|
@@ -189850,7 +190230,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189850
190230
|
io2.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
189851
190231
|
return 2;
|
|
189852
190232
|
}
|
|
189853
|
-
const descriptor =
|
|
190233
|
+
const descriptor = readFileSync107(file2, "utf8");
|
|
189854
190234
|
let parsed;
|
|
189855
190235
|
try {
|
|
189856
190236
|
parsed = JSON.parse(descriptor);
|
|
@@ -189907,8 +190287,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
189907
190287
|
extra: { kind, screen: id, file: { path: file2, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
189908
190288
|
});
|
|
189909
190289
|
}
|
|
189910
|
-
const bytes2 =
|
|
189911
|
-
const sha2 =
|
|
190290
|
+
const bytes2 = readFileSync107(file2);
|
|
190291
|
+
const sha2 = createHash46("sha256").update(bytes2).digest("hex");
|
|
189912
190292
|
const forScreens = (str10(flags["for-screen"]) ?? "").split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
189913
190293
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
189914
190294
|
io2.error(JSON.stringify({ ok: false, error: "no_rebind_takes_no_value", message: "--no-rebind is a switch and takes no value; pass it bare.", usage: PATCH_USAGE }));
|
|
@@ -190051,7 +190431,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
190051
190431
|
}
|
|
190052
190432
|
let def;
|
|
190053
190433
|
try {
|
|
190054
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
190434
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync107(arg.slice(1), "utf8") : arg);
|
|
190055
190435
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
190056
190436
|
io2.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
|
|
190057
190437
|
return 2;
|
|
@@ -190333,7 +190713,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
190333
190713
|
const rememberLastDist = async (jobs2) => {
|
|
190334
190714
|
try {
|
|
190335
190715
|
const dir = contentDir(flags);
|
|
190336
|
-
if (!
|
|
190716
|
+
if (!existsSync85(join91(dir, "himalaya.content.json"))) return;
|
|
190337
190717
|
const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
|
|
190338
190718
|
const own5 = await appId(dir);
|
|
190339
190719
|
for (const job of jobs2) {
|
|
@@ -190573,7 +190953,7 @@ ${label3}`);
|
|
|
190573
190953
|
const platform = str10(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
190574
190954
|
{
|
|
190575
190955
|
const distDir = contentDir(flags);
|
|
190576
|
-
if (
|
|
190956
|
+
if (existsSync85(join91(distDir, "himalaya.content.json"))) {
|
|
190577
190957
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
190578
190958
|
const errors = issues.filter((i2) => i2.severity === "error");
|
|
190579
190959
|
for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
|
|
@@ -190913,7 +191293,7 @@ ${label3}`);
|
|
|
190913
191293
|
const dpxPath = dpxSessionTokenPath();
|
|
190914
191294
|
let dpx;
|
|
190915
191295
|
try {
|
|
190916
|
-
dpx =
|
|
191296
|
+
dpx = readFileSync107(dpxPath, "utf8").trim();
|
|
190917
191297
|
} catch {
|
|
190918
191298
|
io2.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
|
|
190919
191299
|
return 1;
|
|
@@ -191376,7 +191756,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
191376
191756
|
const path2 = dpxSessionTokenPath();
|
|
191377
191757
|
let raw;
|
|
191378
191758
|
try {
|
|
191379
|
-
raw =
|
|
191759
|
+
raw = readFileSync107(path2, "utf8");
|
|
191380
191760
|
} catch {
|
|
191381
191761
|
io2.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
191382
191762
|
return 1;
|
|
@@ -191570,7 +191950,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
191570
191950
|
}
|
|
191571
191951
|
}
|
|
191572
191952
|
const sub = pos[1];
|
|
191573
|
-
const b44Usage = "himi base44 analyze (--url <https://\u2026> | --app-id <id>) [--out .himi/base44-book] [--sample <n>] [--json] | himi base44 adopt [--book .himi/base44-book] [--entities A,B] [--write [path]] [--json] | himi base44 entities query [--content <dir>] [--all] [--json] | himi base44 types [--content <dir>] [--json] | himi base44 login [--from-base44-cli] | himi base44 whoami | himi base44 logout";
|
|
191953
|
+
const b44Usage = "himi base44 analyze (--url <https://\u2026> | --app-id <id>) [--out .himi/base44-book] [--sample <n>] [--json] | himi base44 adopt [--book .himi/base44-book] [--entities A,B] [--write [path]] [--json] | himi base44 entities query [--content <dir>] [--all] [--json] | himi base44 types [--content <dir>] [--json] | himi base44 screens [--content <dir>] [--force] [--dry-run] [--json] | himi base44 login [--from-base44-cli] | himi base44 whoami | himi base44 logout";
|
|
191574
191954
|
if (sub === "adopt") {
|
|
191575
191955
|
const { runBase44Adopt: runBase44Adopt2, AdoptError: AdoptError2 } = await Promise.resolve().then(() => (init_base44_adopt(), base44_adopt_exports));
|
|
191576
191956
|
const dir = contentDir(flags);
|
|
@@ -191617,6 +191997,65 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
191617
191997
|
return 1;
|
|
191618
191998
|
}
|
|
191619
191999
|
}
|
|
192000
|
+
if (sub === "screens") {
|
|
192001
|
+
const dir = contentDir(flags);
|
|
192002
|
+
const fail6 = (code, error, extra = {}) => {
|
|
192003
|
+
io2.error(JSON.stringify({ ok: false, code, error, ...extra }));
|
|
192004
|
+
return 1;
|
|
192005
|
+
};
|
|
192006
|
+
const gen = await Promise.resolve().then(() => (init_generate(), generate_exports));
|
|
192007
|
+
const missing = gen.ENGINE_FILES.filter((f2) => !existsSync85(join91(dir, f2)));
|
|
192008
|
+
if (missing.length) {
|
|
192009
|
+
return fail6("content_dir_not_base44_starter", `${dir} is not a base44-starter content package: the generated screens import a shared engine it does not have (${missing.join(", ")})`, { missing, hint: "scaffold one with `himi init <name> --template base44-starter --base44-app-id <id>`" });
|
|
192010
|
+
}
|
|
192011
|
+
const app = await appId(dir);
|
|
192012
|
+
let base44;
|
|
192013
|
+
try {
|
|
192014
|
+
const { loadAppConfigModule: loadAppConfigModule2 } = await Promise.resolve().then(() => (init_app_config_loader(), app_config_loader_exports));
|
|
192015
|
+
base44 = (await loadAppConfigModule2(dir))?.base44;
|
|
192016
|
+
} catch (e2) {
|
|
192017
|
+
const finding = (await Promise.resolve().then(() => (init_base44_lint(), base44_lint_exports))).base44DefineAppFinding(e2);
|
|
192018
|
+
if (finding) {
|
|
192019
|
+
io2.error(JSON.stringify({ ok: false, code: "invalid_config", app, issues: [{ severity: "error", ...finding }], hint: '`himi validate` reports these with pass: "base44"' }));
|
|
192020
|
+
return 1;
|
|
192021
|
+
}
|
|
192022
|
+
return fail6("config_unloadable", e2.message, { app, hint: "fix the config so it imports cleanly, then re-run. `himi validate` shows the underlying error." });
|
|
192023
|
+
}
|
|
192024
|
+
const specs = base44 && typeof base44 === "object" && Array.isArray(base44.entities) ? base44.entities : [];
|
|
192025
|
+
if (!specs.length) {
|
|
192026
|
+
return fail6("no_entities_block", "config.ts declares no `base44.entities` \u2014 nothing to generate", { app, hint: "declare the entities first (`himi base44 adopt --write`, himi docs base44-entities), then re-run" });
|
|
192027
|
+
}
|
|
192028
|
+
const { validateBase44Entities: validateBase44Entities2 } = await Promise.resolve().then(() => (init_base44_schema(), base44_schema_exports));
|
|
192029
|
+
const errors = validateBase44Entities2(base44, app).filter((i2) => i2.severity === "error");
|
|
192030
|
+
if (errors.length) {
|
|
192031
|
+
io2.error(JSON.stringify({ ok: false, code: "invalid_config", app, issues: errors, hint: '`himi validate` reports these with pass: "base44"' }));
|
|
192032
|
+
return 1;
|
|
192033
|
+
}
|
|
192034
|
+
const { planEntityScreens: planEntityScreens2, PlanError: PlanError2 } = await Promise.resolve().then(() => (init_plan4(), plan_exports));
|
|
192035
|
+
let sp;
|
|
192036
|
+
try {
|
|
192037
|
+
sp = planEntityScreens2(specs, app);
|
|
192038
|
+
} catch (e2) {
|
|
192039
|
+
if (e2 instanceof PlanError2) return fail6(e2.code, e2.message, { app, ...e2.extra });
|
|
192040
|
+
throw e2;
|
|
192041
|
+
}
|
|
192042
|
+
const rendered = gen.renderAll(sp);
|
|
192043
|
+
const dryRun = flags["dry-run"] === true;
|
|
192044
|
+
const { files } = gen.writeGenerated(dir, rendered, { force: flags.force === true, dryRun });
|
|
192045
|
+
const orphaned = gen.orphanedFiles(dir, rendered);
|
|
192046
|
+
print({
|
|
192047
|
+
ok: true,
|
|
192048
|
+
app,
|
|
192049
|
+
...dryRun ? { dryRun: true } : {},
|
|
192050
|
+
files,
|
|
192051
|
+
plans: sp.plans.map((p2) => ({ entity: p2.name, physical: p2.entity, list: p2.ids.list, detail: p2.ids.detail, gates: p2.gates })),
|
|
192052
|
+
tabs: sp.tabs,
|
|
192053
|
+
more: sp.more,
|
|
192054
|
+
...orphaned.length ? { orphaned, note: "generated files for entities no longer declared \u2014 never deleted; remove them by hand if the screens should go" } : {},
|
|
192055
|
+
...files.some((f2) => f2.outcome === "skipped-edited") ? { hint: "skipped-edited files were changed by hand and are left alone; --force overwrites them" } : {}
|
|
192056
|
+
});
|
|
192057
|
+
return 0;
|
|
192058
|
+
}
|
|
191620
192059
|
if (sub === "entities") {
|
|
191621
192060
|
if (pos[2] !== "query") {
|
|
191622
192061
|
io2.error(JSON.stringify({ ok: false, code: "unknown_subcommand", error: pos[2] ? `unknown base44 entities subcommand "${pos[2]}" \u2014 use query` : "base44 entities needs a subcommand: query", usage: b44Usage }));
|