@wix/himalaya-cli 0.1133.0 → 0.1135.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +42 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +50 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -1
- package/dist/cli.mjs +89 -34
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/headless-loop.md +2 -1
- package/guides/himi-test.md +7 -5
- package/guides/sdk-reference.json +56 -2
- package/package.json +2 -2
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts
CHANGED
|
@@ -90,5 +90,45 @@ export declare function entitlements(): Promise<Entitlement[]>;
|
|
|
90
90
|
* No-op for subscriptions / non-consumables. Resolves true on success.
|
|
91
91
|
*/
|
|
92
92
|
export declare function consume(transactionId: string): Promise<boolean>;
|
|
93
|
-
/**
|
|
94
|
-
export declare const version =
|
|
93
|
+
/** SDK contract version; not native support detection. Set the bundle min_binary_version at rollout. */
|
|
94
|
+
export declare const version = 2;
|
|
95
|
+
/** StoreKit-verified convenience fields; the server must independently verify the JWS. */
|
|
96
|
+
export interface AppleTransaction {
|
|
97
|
+
store: "apple";
|
|
98
|
+
signedTransaction: string;
|
|
99
|
+
transactionId: string;
|
|
100
|
+
originalTransactionId: string;
|
|
101
|
+
productId: string;
|
|
102
|
+
appAccountToken: string | null;
|
|
103
|
+
environment: "production" | "sandbox" | "xcode" | "unknown";
|
|
104
|
+
}
|
|
105
|
+
export type TransactionErrorCode = "unsupported" | "unavailable" | "invalidArgument" | "invalidResponse" | "notEnabled" | "unsupportedProductType" | "unknownProduct" | "verificationFailed" | "persistenceFailed" | "ownershipConflict" | "storeError" | "busy";
|
|
106
|
+
export type TransactionFailure = {
|
|
107
|
+
status: "failed";
|
|
108
|
+
code: TransactionErrorCode;
|
|
109
|
+
};
|
|
110
|
+
export type VerificationPurchaseResult = {
|
|
111
|
+
status: "purchased";
|
|
112
|
+
transaction: AppleTransaction;
|
|
113
|
+
} | {
|
|
114
|
+
status: "pending" | "cancelled";
|
|
115
|
+
} | TransactionFailure;
|
|
116
|
+
export type UnfinishedTransactionsResult = {
|
|
117
|
+
status: "ok";
|
|
118
|
+
transactions: AppleTransaction[];
|
|
119
|
+
} | TransactionFailure;
|
|
120
|
+
export type FinishTransactionResult = {
|
|
121
|
+
status: "finished" | "notFound";
|
|
122
|
+
} | TransactionFailure;
|
|
123
|
+
/** Apple non-consumables only. The token comes from authenticated backend context.
|
|
124
|
+
* Leaves the transaction unfinished. Never falls back to legacy purchase on old binaries. */
|
|
125
|
+
export declare function purchaseForVerification(input: {
|
|
126
|
+
productId: string;
|
|
127
|
+
appAccountToken: string;
|
|
128
|
+
}): Promise<VerificationPurchaseResult>;
|
|
129
|
+
/** Same-install recovery; does not restore finished purchases or override ownership. */
|
|
130
|
+
export declare function getUnfinishedTransactions(): Promise<UnfinishedTransactionsResult>;
|
|
131
|
+
/** Trusted callers must first obtain durable backend processing acknowledgement. */
|
|
132
|
+
export declare function finishTransaction(input: {
|
|
133
|
+
transactionId: string;
|
|
134
|
+
}): Promise<FinishTransactionResult>;
|
|
@@ -14,7 +14,7 @@ export declare const CAPABILITY_REGISTRY: {
|
|
|
14
14
|
readonly godot: readonly ["loadPack", "release", "send"];
|
|
15
15
|
readonly haptic: readonly ["play"];
|
|
16
16
|
readonly himi_apps: readonly ["canOpen", "current", "hostInfo", "open"];
|
|
17
|
-
readonly iap: readonly ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"];
|
|
17
|
+
readonly iap: readonly ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"];
|
|
18
18
|
readonly keyboard: readonly ["dismiss"];
|
|
19
19
|
readonly live_activity: readonly ["end", "start", "update"];
|
|
20
20
|
readonly local_database: readonly ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"];
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -58,13 +58,62 @@ async function consume(transactionId) {
|
|
|
58
58
|
function normalizeStatus(s) {
|
|
59
59
|
return s === "purchased" || s === "pending" || s === "cancelled" || s === "failed" ? s : "failed";
|
|
60
60
|
}
|
|
61
|
-
var version =
|
|
61
|
+
var version = 2;
|
|
62
|
+
async function purchaseForVerification(input) {
|
|
63
|
+
if (!nonempty(input?.productId) || !isUUID(input?.appAccountToken)) return failure("invalidArgument");
|
|
64
|
+
const result = await managedDispatch(() => dispatch("capability.iap.purchaseForVerification", input));
|
|
65
|
+
if (result?.status === "purchased" && isAppleTransaction(result.transaction)) {
|
|
66
|
+
return { status: "purchased", transaction: decodeTransaction(result.transaction) };
|
|
67
|
+
}
|
|
68
|
+
if (result?.status === "pending" || result?.status === "cancelled") return { status: result.status };
|
|
69
|
+
return decodeFailure(result);
|
|
70
|
+
}
|
|
71
|
+
async function getUnfinishedTransactions() {
|
|
72
|
+
const result = await managedDispatch(() => dispatch("capability.iap.getUnfinishedTransactions"));
|
|
73
|
+
if (result?.status === "ok" && Array.isArray(result.transactions) && result.transactions.every(isAppleTransaction)) {
|
|
74
|
+
return { status: "ok", transactions: result.transactions.map(decodeTransaction) };
|
|
75
|
+
}
|
|
76
|
+
return decodeFailure(result);
|
|
77
|
+
}
|
|
78
|
+
async function finishTransaction(input) {
|
|
79
|
+
if (!nonempty(input?.transactionId)) return failure("invalidArgument");
|
|
80
|
+
const result = await managedDispatch(() => dispatch("capability.iap.finishTransaction", input));
|
|
81
|
+
if (result?.status === "finished" || result?.status === "notFound") return { status: result.status };
|
|
82
|
+
return decodeFailure(result);
|
|
83
|
+
}
|
|
84
|
+
var transactionErrors = /* @__PURE__ */ new Set(["unsupported", "unavailable", "invalidArgument", "invalidResponse", "notEnabled", "unsupportedProductType", "unknownProduct", "verificationFailed", "persistenceFailed", "ownershipConflict", "storeError", "busy"]);
|
|
85
|
+
var failure = (code) => ({ status: "failed", code });
|
|
86
|
+
var nonempty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
87
|
+
var isUUID = (value) => typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value) && value.length === 36;
|
|
88
|
+
var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
89
|
+
async function managedDispatch(invoke) {
|
|
90
|
+
try {
|
|
91
|
+
const value = await invoke();
|
|
92
|
+
return isObject(value) ? value : null;
|
|
93
|
+
} catch {
|
|
94
|
+
return failure("unavailable");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function decodeFailure(value) {
|
|
98
|
+
return value?.status === "failed" && transactionErrors.has(value.code) ? failure(value.code) : failure("invalidResponse");
|
|
99
|
+
}
|
|
100
|
+
function isAppleTransaction(value) {
|
|
101
|
+
if (!isObject(value)) return false;
|
|
102
|
+
return value.store === "apple" && typeof value.signedTransaction === "string" && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.signedTransaction) && nonempty(value.transactionId) && nonempty(value.originalTransactionId) && nonempty(value.productId) && (value.appAccountToken === null || isUUID(value.appAccountToken)) && ["production", "sandbox", "xcode", "unknown"].includes(value.environment);
|
|
103
|
+
}
|
|
104
|
+
function decodeTransaction(value) {
|
|
105
|
+
const { store, signedTransaction, transactionId, originalTransactionId, productId, appAccountToken, environment } = value;
|
|
106
|
+
return { store, signedTransaction, transactionId, originalTransactionId, productId, appAccountToken, environment };
|
|
107
|
+
}
|
|
62
108
|
export {
|
|
63
109
|
consume,
|
|
64
110
|
entitlements,
|
|
111
|
+
finishTransaction,
|
|
65
112
|
getPaywallConfig,
|
|
66
113
|
getProducts,
|
|
114
|
+
getUnfinishedTransactions,
|
|
67
115
|
purchase,
|
|
116
|
+
purchaseForVerification,
|
|
68
117
|
restore,
|
|
69
118
|
version
|
|
70
119
|
};
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -14,7 +14,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
14
14
|
"godot": ["loadPack", "release", "send"],
|
|
15
15
|
"haptic": ["play"],
|
|
16
16
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
17
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
17
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
18
18
|
"keyboard": ["dismiss"],
|
|
19
19
|
"live_activity": ["end", "start", "update"],
|
|
20
20
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
|
@@ -29,7 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"godot": ["loadPack", "release", "send"],
|
|
30
30
|
"haptic": ["play"],
|
|
31
31
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
32
|
-
"iap": ["consume", "entitlements", "getPaywallConfig", "getProducts", "purchase", "restore"],
|
|
32
|
+
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
33
33
|
"keyboard": ["dismiss"],
|
|
34
34
|
"live_activity": ["end", "start", "update"],
|
|
35
35
|
"local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
|
package/dist/cli.mjs
CHANGED
|
@@ -6762,7 +6762,6 @@ function walk(node, registry, path2, out2) {
|
|
|
6762
6762
|
var SYSTEM_FONT_FAMILY, TONAL_ELEVATION_ALPHA;
|
|
6763
6763
|
var init_tokens = __esm({
|
|
6764
6764
|
"../../core/ts/src/tokens.ts"() {
|
|
6765
|
-
"use strict";
|
|
6766
6765
|
SYSTEM_FONT_FAMILY = "$system";
|
|
6767
6766
|
TONAL_ELEVATION_ALPHA = [0, 0.05, 0.08, 0.11, 0.12, 0.14];
|
|
6768
6767
|
}
|
|
@@ -6789,7 +6788,6 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
6789
6788
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
6790
6789
|
var init_bindings = __esm({
|
|
6791
6790
|
"../../core/ts/src/bindings.ts"() {
|
|
6792
|
-
"use strict";
|
|
6793
6791
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
6794
6792
|
BINDING_SIGIL_RE = new RegExp(
|
|
6795
6793
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -14209,8 +14207,8 @@ async function loadSharp() {
|
|
|
14209
14207
|
const failures = [];
|
|
14210
14208
|
let presentButBroken = false;
|
|
14211
14209
|
try {
|
|
14212
|
-
const { createRequire:
|
|
14213
|
-
cachedSharp =
|
|
14210
|
+
const { createRequire: createRequire4 } = await import("node:module");
|
|
14211
|
+
cachedSharp = createRequire4(import.meta.url)("sharp");
|
|
14214
14212
|
lastProblem = null;
|
|
14215
14213
|
return cachedSharp;
|
|
14216
14214
|
} catch (e) {
|
|
@@ -24749,7 +24747,6 @@ function shouldRevealError(args) {
|
|
|
24749
24747
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
24750
24748
|
var init_validation = __esm({
|
|
24751
24749
|
"../../core/ts/src/validation.ts"() {
|
|
24752
|
-
"use strict";
|
|
24753
24750
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
24754
24751
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
24755
24752
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -29150,7 +29147,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
29150
29147
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
29151
29148
|
var init_worker_subtree = __esm({
|
|
29152
29149
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
29153
|
-
"use strict";
|
|
29154
29150
|
init_worker_subtree_safe_types_generated();
|
|
29155
29151
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
29156
29152
|
maxEncodedBytes: 65536,
|
|
@@ -48375,6 +48371,7 @@ __export(app_source_exports, {
|
|
|
48375
48371
|
newestSourceChangeMs: () => newestSourceChangeMs,
|
|
48376
48372
|
readAppSource: () => readAppSource,
|
|
48377
48373
|
removeStaleSource: () => removeStaleSource,
|
|
48374
|
+
renderInputRootDirs: () => renderInputRootDirs,
|
|
48378
48375
|
secretFindings: () => secretFindings,
|
|
48379
48376
|
sourceFingerprint: () => sourceFingerprint,
|
|
48380
48377
|
staleSourcePaths: () => staleSourcePaths,
|
|
@@ -48385,6 +48382,7 @@ __export(app_source_exports, {
|
|
|
48385
48382
|
import { createHash as createHash24 } from "node:crypto";
|
|
48386
48383
|
import { readdirSync as readdirSync25, lstatSync as lstatSync9, readFileSync as readFileSync50, mkdirSync as mkdirSync22, writeFileSync as writeFileSync17, existsSync as existsSync46, rmSync as rmSync10, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3 } from "node:fs";
|
|
48387
48384
|
import { join as join44, resolve as resolve40, sep as sep11 } from "node:path";
|
|
48385
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
48388
48386
|
import { deflateRawSync as deflateRawSync2 } from "node:zlib";
|
|
48389
48387
|
function walkSourceTree(dir, file, skip, enter = () => {
|
|
48390
48388
|
}) {
|
|
@@ -48423,12 +48421,56 @@ function collectAppSource(dir) {
|
|
|
48423
48421
|
skipped.sort();
|
|
48424
48422
|
return { entries, skipped };
|
|
48425
48423
|
}
|
|
48424
|
+
function renderInputRootDirs(dir) {
|
|
48425
|
+
const entries = [];
|
|
48426
|
+
walkSourceTree(
|
|
48427
|
+
dir,
|
|
48428
|
+
(archivePath, hostRel) => {
|
|
48429
|
+
const segs = archivePath.split("/");
|
|
48430
|
+
if (!CODE_FILE.test(archivePath) || /\.d\.[cm]?ts$/i.test(archivePath)) return;
|
|
48431
|
+
if (segs.length === 1 || segs[0] === "dev" || segs[0] === "tier5-src") entries.push(join44(dir, hostRel));
|
|
48432
|
+
},
|
|
48433
|
+
() => {
|
|
48434
|
+
}
|
|
48435
|
+
);
|
|
48436
|
+
const roots = new Set(RENDER_ROOT_DIRS);
|
|
48437
|
+
if (entries.length === 0) return roots;
|
|
48438
|
+
try {
|
|
48439
|
+
const esbuild = createRequire3(import.meta.url)("esbuild");
|
|
48440
|
+
const empty = Object.fromEntries(
|
|
48441
|
+
[".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".ttf", ".otf", ".woff", ".woff2", ".css", ".txt", ".md", ".html", ".mp3", ".mp4"].map((e) => [e, "empty"])
|
|
48442
|
+
);
|
|
48443
|
+
const result = esbuild.buildSync({
|
|
48444
|
+
entryPoints: entries,
|
|
48445
|
+
absWorkingDir: dir,
|
|
48446
|
+
bundle: true,
|
|
48447
|
+
write: false,
|
|
48448
|
+
metafile: true,
|
|
48449
|
+
packages: "external",
|
|
48450
|
+
platform: "neutral",
|
|
48451
|
+
format: "esm",
|
|
48452
|
+
outdir: join44(dir, ".himi", "render-inputs-out"),
|
|
48453
|
+
loader: empty,
|
|
48454
|
+
logLevel: "silent"
|
|
48455
|
+
});
|
|
48456
|
+
for (const input of Object.keys(result.metafile?.inputs ?? {})) {
|
|
48457
|
+
const segs = input.split("/");
|
|
48458
|
+
if (segs.length > 1 && !input.startsWith("..") && !input.includes(":")) roots.add(segs[0]);
|
|
48459
|
+
}
|
|
48460
|
+
return roots;
|
|
48461
|
+
} catch {
|
|
48462
|
+
return void 0;
|
|
48463
|
+
}
|
|
48464
|
+
}
|
|
48426
48465
|
function newestSourceChangeMs(dir) {
|
|
48466
|
+
const roots = renderInputRootDirs(dir);
|
|
48467
|
+
const inRead = (hostRel) => !roots || roots.has(hostRel.split(sep11)[0]);
|
|
48468
|
+
const counts = (hostRel) => !hostRel.includes(sep11) || inRead(hostRel);
|
|
48427
48469
|
let newest = 0;
|
|
48428
48470
|
walkSourceTree(
|
|
48429
48471
|
dir,
|
|
48430
48472
|
(archivePath, hostRel) => {
|
|
48431
|
-
if (/\.md$/i.test(archivePath)) return;
|
|
48473
|
+
if (/\.md$/i.test(archivePath) || !counts(hostRel)) return;
|
|
48432
48474
|
const m = lstatSync9(join44(dir, hostRel)).mtimeMs;
|
|
48433
48475
|
if (m > newest) newest = m;
|
|
48434
48476
|
},
|
|
@@ -48438,8 +48480,9 @@ function newestSourceChangeMs(dir) {
|
|
|
48438
48480
|
// mtime moves. So every source directory counts too — else removing a screen after the shot
|
|
48439
48481
|
// was taken would date that shot as current. Not the package ROOT: any file created there
|
|
48440
48482
|
// (a plan, a build output) moves its mtime, and the screens live below it (dev/, tier5-src/).
|
|
48483
|
+
// Nor a root directory the render does not read: creating a file in `_qa/` moves `_qa/`.
|
|
48441
48484
|
(hostRel) => {
|
|
48442
|
-
if (hostRel === "") return;
|
|
48485
|
+
if (hostRel === "" || !inRead(hostRel)) return;
|
|
48443
48486
|
const m = lstatSync9(join44(dir, hostRel)).mtimeMs;
|
|
48444
48487
|
if (m > newest) newest = m;
|
|
48445
48488
|
}
|
|
@@ -48600,7 +48643,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
48600
48643
|
}
|
|
48601
48644
|
return empty;
|
|
48602
48645
|
}
|
|
48603
|
-
var MAX_APP_SOURCE_BYTES, SECRET_PATTERNS;
|
|
48646
|
+
var MAX_APP_SOURCE_BYTES, SECRET_PATTERNS, RENDER_ROOT_DIRS, CODE_FILE;
|
|
48604
48647
|
var init_app_source = __esm({
|
|
48605
48648
|
"src/app-source.ts"() {
|
|
48606
48649
|
init_source_deny();
|
|
@@ -48641,6 +48684,8 @@ var init_app_source = __esm({
|
|
|
48641
48684
|
{ re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/, reason: "a GitHub token" },
|
|
48642
48685
|
{ re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/, reason: "a Slack token" }
|
|
48643
48686
|
];
|
|
48687
|
+
RENDER_ROOT_DIRS = /* @__PURE__ */ new Set(["dev", "tier5-src", "assets", "seed", "strings", "l10n", "fonts", "images", "data"]);
|
|
48688
|
+
CODE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/i;
|
|
48644
48689
|
}
|
|
48645
48690
|
});
|
|
48646
48691
|
|
|
@@ -49913,7 +49958,8 @@ function watchReminder(dir, opts = {}) {
|
|
|
49913
49958
|
return `the live preview is running at ${live2.url} (pid ${live2.pid}${live2.by === "init" ? ", started by himi init" : ""}) \u2014 it repaints on every save, and the build board is ${live2.board}; give the owner that link to click around while you work, and do not start another`;
|
|
49914
49959
|
}
|
|
49915
49960
|
const content = opts.content ?? displayPath(dir);
|
|
49916
|
-
|
|
49961
|
+
const remote = readInitSource(dir)?.source === "remote" ? "init did not start it because this template came off the serve plane \u2014 once you have read its code, " : "";
|
|
49962
|
+
return `${remote}start the live preview and leave it running: \`himi run --watch --content ${shellQuote(content)} &\` (the consent preflight first, if a worker or config calls Wix at boot) \u2014 it repaints on every save; the build board is ${shellQuote(join48(content, ".himi", "studio", "index.html"))}, or /__himi/studio/ on the preview`;
|
|
49917
49963
|
} catch {
|
|
49918
49964
|
return void 0;
|
|
49919
49965
|
}
|
|
@@ -58109,21 +58155,21 @@ var init_preview_assets_generated = __esm({
|
|
|
58109
58155
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
58110
58156
|
init_preview_assets_format();
|
|
58111
58157
|
PREVIEW_ASSET_MANIFEST = [
|
|
58112
|
-
{ key: "assets/index-
|
|
58113
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
58114
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
58115
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
58116
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
58117
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
58118
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
58119
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
58120
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
58121
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
58122
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
58123
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
58124
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
58125
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
58126
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
58158
|
+
{ key: "assets/index-B-1B15q7.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1104811, sha256: "bd81d6b74d2a1b72072c1c20303e225dbc620861e50f66e5b7a90a6d64c66ed2" },
|
|
58159
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1104819, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
58160
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1109429, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
58161
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1598013, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
58162
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1688937, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
58163
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1779921, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
58164
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1870901, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
58165
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1961773, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
58166
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2052753, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
58167
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2161389, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
58168
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2270473, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
58169
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2379521, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
58170
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2487221, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
58171
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2575329, length: 4947, sha256: "e6135ff25467aef302a26590c7f740191c93ee3acc0abcfbd4f218780559ff9f" },
|
|
58172
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2580276, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
58127
58173
|
];
|
|
58128
58174
|
}
|
|
58129
58175
|
});
|
|
@@ -72408,7 +72454,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
72408
72454
|
"no-first-look",
|
|
72409
72455
|
"no-image",
|
|
72410
72456
|
"no-watch",
|
|
72411
|
-
"mocks"
|
|
72457
|
+
"mocks",
|
|
72458
|
+
"no-mocks"
|
|
72412
72459
|
]);
|
|
72413
72460
|
var SHELL_ENUM = SHELL_NAMES2.join("|");
|
|
72414
72461
|
var SWITCH_FLAGS = new Set([...BOOLEAN_FLAGS].filter((name) => name !== "deep"));
|
|
@@ -72616,7 +72663,7 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
72616
72663
|
(--ai writes rows for you to review first)
|
|
72617
72664
|
himi secrets set|list|rotate --app <app> --name <name> [--environment preview|production]
|
|
72618
72665
|
encrypted secret metadata; set/rotate read the value from stdin
|
|
72619
|
-
himi render <screenId> [--content <dir>] [--scheme dark] [--png [<file>]] [--tree] [--dump-state] [--static] [--live] [--mocks] [--state <json|file>] [--input <json|file>] [--width <px> | --device <name>] [--rtl] [--load-budget <ms>]
|
|
72666
|
+
himi render <screenId> [--content <dir>] [--scheme dark] [--png [<file>]] [--tree] [--dump-state] [--static] [--live] [--mocks | --no-mocks] [--state <json|file>] [--input <json|file>] [--width <px> | --device <name>] [--rtl] [--load-budget <ms>]
|
|
72620
72667
|
[--remote --app <app> --release <id>]
|
|
72621
72668
|
headless web render + diagnostics (no sim). Default: local content dir.
|
|
72622
72669
|
A bare --png writes .himi/shots/<screenId>.png (what the build board shows).
|
|
@@ -72629,7 +72676,8 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
72629
72676
|
--mocks runs load() against the app's OWN recorded data instead \u2014 dev/net-mocks.json
|
|
72630
72677
|
(what \`himi test --record\` writes) and the config's cms seed rows, as \`himi test\`'s
|
|
72631
72678
|
shots do; no request leaves this machine. With none, it renders the initial state.
|
|
72632
|
-
|
|
72679
|
+
It is the DEFAULT whenever the app has recorded data (mocks.default in the output);
|
|
72680
|
+
--no-mocks renders the offline initial state instead;
|
|
72633
72681
|
--tree adds stable raw structure plus a resolvedRenderTree when hydrated;
|
|
72634
72682
|
--dump-state explicitly includes the full worker snapshot;
|
|
72635
72683
|
--state '{"<svc>":{\u2026}}' injects worker state (render loaded/error states);
|
|
@@ -73192,7 +73240,7 @@ var COMMANDS = [
|
|
|
73192
73240
|
{ name: "ux", summary: "audit or record mobile UX evidence. `audit` checks the public-safe contract, seeded blank acceptance rows, placeholder source copy, app-specific mocks, and iOS/Android audit records. It warns while existing templates migrate; `--strict` promotes missing evidence. `record` stores checks performed on an installed iOS/Android build: `--checks` is required for passed|failed and empty for unavailable, which drove nothing and needs a `--reason` instead. `record` also STAMPS the release it audited (it resolves the id from a build, the same one a push would publish), because an unforced `himi push` of a release with screens refuses when no drive is recorded for THAT release, or when the one that is recorded says `failed` \u2014 the artifact stopped being advice nobody reads (#2955). `unavailable` still satisfies it; only `failed` refuses.", required: "audit [--content <dir>] [--strict] [--json] | record --content <dir> --platform ios|android --status passed|failed|unavailable [--checks back,keyboard,...] [--reason <text>]" },
|
|
73193
73241
|
{ name: "progress", summary: 'the build JOURNAL an agent keeps for the owner while it works. `himi progress "<what changed>" --step <1-8|name> --image <png>` appends one postcard to .himi/progress.jsonl \u2014 the step is one of the customer journey\'s eight (discover, classify, plan, implement, brand, validate, review, download) \u2014 and COPIES each image, content-addressed, into .himi/history/, because .himi/shots/ is overwritten by every render and cleared by every full `himi test`, so a path into it would later show a different picture than the one the owner was sent. --image repeats. With NO --image, the home screen\'s current shot is attached automatically, only when it is no older than the last source change and not the picture the latest journaled postcard already shows \u2014 and never a shot that landed on loading placeholders, an empty or an error state (.himi/shot-states.json): then the newest home picture of the current source that shows content goes on instead (its .himi/history copy, `imageNote` saying so), or none \u2014 except on the HANDOVER card (`--step review`), where a repeat is the point and it attaches anyway; that card\'s output also names the making-of (`makingOf`, .himi/making-of.html, rebuilt when missing or older than the journal so it ends on this card) and its `next` says to hand it to the owner beside the preview link; `imageAttached` in the output says whether the postcard carries a picture (with `imageNote` saying why not, or which picture went on instead), and `--no-image` sends a text-only postcard. --notify also raises a best-effort desktop notification for an owner who stepped away. A bare `himi progress` prints the journal with the current step and elapsed time \u2014 also how an agent recovers its place after its context was compacted. APPROVALS: `--approve <gate> "<what>"` records one the customer just gave (gates: site-create, connect, private-data, draft, promote, push-signing, qa-build) in .himi/approvals.jsonl, and `--done <gate>` / `--drop <gate>` closes it \u2014 an approval is owed until then, and the chat that held it does not survive a new session. `--brief` prints plain text for a session start: the current step, the last postcard, every open approval, and whether this app\'s agent files are stale \u2014 the SessionStart hook `himi agent-init` installs runs exactly this. The CLI also journals milestones by itself \u2014 the first PNG render of the home screen (for an app a current `himi init` started: once as the template\'s "Starting point" while the source is what init wrote, then once as "First look at your app" after it diverges, Markdown edits not counting; once per app otherwise), a `himi test` crawl whose outcome changed since the last one (its counts or its home picture; an identical re-run writes none, and a repeat names what changed: "The home screen changed since the last crawl." or the changed counts, was \u2192 now), every draft push (with the home picture only when that shot is newer than the last source edit \u2014 otherwise the postcard says why and names `himi render <home> --png`), and ONE rule for a long silence: a successful home `render --png` more than ten minutes after the newest postcard of any kind, with a picture the latest postcard does not show, journals "Still building: here\'s the home screen now." with it (never twice within the window). When a crawl\'s or a draft\'s home picture is the first of an app whose source diverged, "First look at your app" is journaled first, from that shot, once. All are marked `"by": "himi"`; they never move the journey step, carry no link or credential, and step aside (folded out of every reader) when the agent journals the same step or picture within five minutes. Local only: nothing is sent anywhere.', required: '["<message>" [--step <1-8|name>] [--image <png>]\u2026 [--no-image] [--notify]] [--content <dir>] | --approve|--done|--drop <gate> ["<note>"] | --brief' },
|
|
73194
73242
|
{ name: "studio", summary: "open the BUILD BOARD \u2014 one local page the owner can leave open while an agent builds their app, which fills itself in: every screen as it renders (NEW/CHANGED badges, and each earlier version kept for a filmstrip), the journey stepper and the latest postcard from `himi progress`, the validate/test/UX/draft checks as they run, the site next to the app's home screen with its palette, and the navigation the test crawl followed. Writes .himi/studio/index.html and opens it; the page re-reads its state every two seconds, so nothing needs to be served. OPT-IN BY EXISTENCE: until this command (or `himi init`, which makes the board for every app it creates, without opening a browser) has run, no other command touches .himi/studio/ \u2014 after it, render/test/validate/push/icon/site/ux/progress each refresh the board as they finish (best-effort; never fails a command). Every image is a content-addressed copy in .himi/history/, never a live path into .himi/shots/. Local only, no secrets: it never reads a preview token, handover code or control token. --no-open prints the path instead (SSH, CI). `himi studio reel` writes the MAKING-OF: one self-contained HTML file (every image inlined, nothing fetched) with a flipbook of the home screen version by version, captioned by the postcard in effect at the time, the final screens, and every postcard \u2014 sized to stay attachable, thinning frames first. Defaults to .himi/making-of.html (never archived by push), which every successful `himi push --draft` also rebuilds and names as `reel` in its output; --out to put it elsewhere. The output names that file as the one to hand the owner (`handover: {file, hint}` in JSON; two plain lines at a terminal) \u2014 beside the preview link, never instead of it.", required: "[--content <dir>] [--no-open] | reel [--out <file>] [--no-open]" },
|
|
73195
|
-
{ name: "render", summary: "headless-render a screen with the web renderer: render-tree + diagnostics, optional --png [<file>] (bare: .himi/shots/<id>.png, what the build board shows), --scheme dark, --tree. Local by default (content dir). Pass --remote --app --release to hit GET /v1/preview/\u2026/render on the serve plane after a push. Boots the worker so $service bindings resolve; --static raw bindings; --live real Wix fetches; --mocks runs load() against the app's own recorded data (dev/net-mocks.json from `himi test --record`, then the config's cms seed rows \u2014 hermetic, never a request; with neither it paints the initial state, and `mocks: {used: false}` says why), which is what the automatic pictures use, so they show the app's content instead of its offline placeholders; --state injects worker state; --input supplies pre-boot navigation params; --width/--device for PNG viewport; --rtl for dir=rtl + $env:isRTL.", required: "<screenId> [--content <dir>] [--scheme dark] [--png [<file>]] [--tree] [--static] [--live] [--mocks] [--state <json|file>] [--input <json|file>] [--width <px> | --device <name>] [--rtl] [--remote --app --release]" },
|
|
73243
|
+
{ name: "render", summary: "headless-render a screen with the web renderer: render-tree + diagnostics, optional --png [<file>] (bare: .himi/shots/<id>.png, what the build board shows), --scheme dark, --tree. Local by default (content dir). Pass --remote --app --release to hit GET /v1/preview/\u2026/render on the serve plane after a push. Boots the worker so $service bindings resolve; --static raw bindings; --live real Wix fetches; --mocks (the DEFAULT whenever the app has recorded data; --no-mocks for the offline initial state) runs load() against the app's own recorded data (dev/net-mocks.json from `himi test --record`, then the config's cms seed rows \u2014 hermetic, never a request; with neither it paints the initial state, and `mocks: {used: false}` says why), which is what the automatic pictures use, so they show the app's content instead of its offline placeholders; --state injects worker state; --input supplies pre-boot navigation params; --width/--device for PNG viewport; --rtl for dir=rtl + $env:isRTL.", required: "<screenId> [--content <dir>] [--scheme dark] [--png [<file>]] [--tree] [--static] [--live] [--mocks | --no-mocks] [--state <json|file>] [--input <json|file>] [--width <px> | --device <name>] [--rtl] [--remote --app --release]" },
|
|
73196
73244
|
{ name: "cms", summary: "inspect, provision, and seed the app's CMS (Wix Data) collections, declared as a `cms` block in config.ts. `query` is READ-ONLY \u2014 by default it fetches ONLY the physical ids `config.ts` declares (item counts + schema drift) and reports `siteScanned: false`; it never lists the site, so an UNDECLARED `himi_<app>_` collection this app owns is not reached without `--all`. `--all` SCANS the site \u2014 every collection it lists is labeled `owned`/`adopted`/`foreign`, and it describes every foreign one \u2014 id, non-system field keys + types, and the site's read role \u2014 so an app with no `cms` block at all can DISCOVER a collection to adopt (`--all` is the one case where a missing `cms` block is not 'nothing to do'). Foreign collections are described up to a cap and are never item-counted (`itemCount: null`), because a row count is one query each; `foreign.count` is how many the scan LISTED \u2014 it follows the list endpoint's pages, and `listingIncomplete: true` says when the walk stopped short of the end, with `unlistedCollections` counting what it left out when Wix gave a paging total \u2014 and `foreign.truncated` says how many of those went undescribed, each still NAMED in `foreign.others` (id + displayName), so a collection the site already has is never hidden behind the cap. The scan is OWNER-scoped \u2014 it needs --site <msid> (or WIX_SITE_ID) plus owner auth via `wix token`; a visitor token can read a public collection's ITEMS but can never enumerate collections, so there is no tokenless discovery path. `create` reconciles declared collections additively and idempotently, and REFUSES any id outside the app's `himi_<app>_` namespace, so it is safe against a production site. It reports declared-vs-site `permissionDrift` but never writes permissions unless asked with --apply-permissions, so a field reconcile can't silently revert access control changed in the dashboard. `seed` inserts the git-tracked `seed:` rows into EMPTY owned collections (--force to add to a non-empty one; --ai writes placeholder rows plus a refinement prompt for you to review). Adopted collections (declared by `wixId`) are read-only and never created, updated, or seeded. Site from --site <msid> or WIX_SITE_ID; owner auth via `wix token`.", required: "query|create|seed [--site <msid>] [--content <dir>] [--all] [--dry-run] [--force] [--allow-destructive] [--apply-permissions] [--only <id>] [--ai] [--count <n>]" },
|
|
73197
73245
|
{ name: "data", summary: "read-only plan or explicitly provision/seed declared KV and Wix Data resources. Preview and production are separate scopes. KV administration uses the operator data plane from --data-url/HIMI_DATA_ADMIN_URL and HIMI_DATA_ADMIN_TOKEN; draft push never calls it.", required: "plan|create|seed [--site <msid>] [--environment preview|production] [--content <dir>] [--data-url <url>] [--dry-run] [--force]" },
|
|
73198
73246
|
{ name: "icons", summary: "list the valid Icon.name vocabulary (an unknown name renders a fallback glyph; validate warns on unknown names) (offline)", required: "[--json]" },
|
|
@@ -75782,7 +75830,8 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
75782
75830
|
loader: loaderArgs(process.execArgv)
|
|
75783
75831
|
});
|
|
75784
75832
|
const { postcard: picturePostcard, ...picture } = homePicture;
|
|
75785
|
-
|
|
75833
|
+
const validateReminder = process.env.HIMI_AUTO_RENDER ? void 0 : (await Promise.resolve().then(() => (init_milestones(), milestones_exports))).watchReminder(dir, { content: str9(flags.content) });
|
|
75834
|
+
print({ ...finalReport, homePicture: picture, ...picturePostcard ? { postcard: picturePostcard } : {}, ...validateReminder ? { reminder: validateReminder } : {} });
|
|
75786
75835
|
return hasErrors ? 1 : 0;
|
|
75787
75836
|
}
|
|
75788
75837
|
case "functions": {
|
|
@@ -76110,7 +76159,8 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
76110
76159
|
const { count: count2 } = summarizeProgress2(readProgress2(dir).entries);
|
|
76111
76160
|
const imageAttached = (entry.images?.length ?? 0) > 0;
|
|
76112
76161
|
const handed = handover && isContentPackage ? (await Promise.resolve().then(() => (init_milestones(), milestones_exports))).afterHandoverPostcard(dir, { content: str9(flags.content) }) : null;
|
|
76113
|
-
|
|
76162
|
+
const progressReminder = isContentPackage ? (await Promise.resolve().then(() => (init_milestones(), milestones_exports))).watchReminder(dir, { content: str9(flags.content) }) : void 0;
|
|
76163
|
+
print({ ok: true, entry, journal: journal2, count: count2, imageAttached, ...imageNote ? { imageNote } : {}, ...notified === void 0 ? {} : { notified }, ...handed ? { makingOf: handed.makingOf, next: handed.next } : {}, ...hint, ...progressReminder ? { reminder: progressReminder } : {} });
|
|
76114
76164
|
return 0;
|
|
76115
76165
|
} catch (e) {
|
|
76116
76166
|
if (e instanceof ProgressError2) {
|
|
@@ -76636,6 +76686,10 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
76636
76686
|
io.error(JSON.stringify({ error: `--mocks and ${live2 ? "--live" : "--static"} are mutually exclusive: --mocks loads the app's recorded data, ${live2 ? "--live real Wix data" : "--static no data at all"}` }));
|
|
76637
76687
|
return 2;
|
|
76638
76688
|
}
|
|
76689
|
+
if (flags.mocks === true && flags["no-mocks"] === true) {
|
|
76690
|
+
io.error(JSON.stringify({ error: "--mocks and --no-mocks are mutually exclusive" }));
|
|
76691
|
+
return 2;
|
|
76692
|
+
}
|
|
76639
76693
|
let injectedState;
|
|
76640
76694
|
if (flags.state !== void 0) {
|
|
76641
76695
|
const stateArg = str9(flags.state);
|
|
@@ -76708,7 +76762,8 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
76708
76762
|
}
|
|
76709
76763
|
let mocks;
|
|
76710
76764
|
let mocksNote;
|
|
76711
|
-
|
|
76765
|
+
const mocksByDefault = flags.mocks !== true && flags["no-mocks"] !== true && !live2 && flags.static !== true && injectedState === void 0;
|
|
76766
|
+
if (flags.mocks === true || mocksByDefault) {
|
|
76712
76767
|
let rules = null;
|
|
76713
76768
|
let bad2;
|
|
76714
76769
|
try {
|
|
@@ -76720,7 +76775,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
76720
76775
|
const seeded = cmsSeed && Object.keys(cmsSeed).length ? cmsSeed : null;
|
|
76721
76776
|
const picked = renderMocksFrom(rules, bad2, seeded);
|
|
76722
76777
|
mocks = picked.mocks;
|
|
76723
|
-
mocksNote = picked.note;
|
|
76778
|
+
if (!mocksByDefault || bad2) mocksNote = picked.note;
|
|
76724
76779
|
}
|
|
76725
76780
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76726
76781
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
@@ -76762,7 +76817,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
76762
76817
|
hydrated: live2 ? "live" : hydrate,
|
|
76763
76818
|
dataSource: renderDataSource({ live: live2, hydrate, liveCalls: r.liveCalls, liveReturned: r.liveReturned, mocked: !!r.mockCalls }),
|
|
76764
76819
|
// What --mocks loaded from, how many requests the load made, and the ones no layer held.
|
|
76765
|
-
...r.mockCalls && mocks ? { mocks: { used: true, from: mocks.from, calls: r.mockCalls.length, ...r.mockUnserved?.length ? { unserved: r.mockUnserved } : {}, ...mocks.ignored ? { ignored: mocks.ignored } : {} } } : mocksNote ? { mocks: mocksNote } : mocks ? { mocks: { used: false, reason: r.mockBootFailed ? "the screen's worker failed to boot against the recorded data, so its initial state was rendered" : "the screen has no worker bundle to load data into", ...mocks.ignored ? { ignored: mocks.ignored } : {} } } : {},
|
|
76820
|
+
...r.mockCalls && mocks ? { mocks: { used: true, from: mocks.from, calls: r.mockCalls.length, ...r.mockUnserved?.length ? { unserved: r.mockUnserved } : {}, ...mocks.ignored ? { ignored: mocks.ignored } : {}, ...mocksByDefault ? { default: true, hint: "the app's recorded data loaded by default; --no-mocks renders the offline initial state, --live the real site" } : {} } } : mocksNote ? { mocks: mocksNote } : mocks ? { mocks: { used: false, reason: r.mockBootFailed ? "the screen's worker failed to boot against the recorded data, so its initial state was rendered" : "the screen has no worker bundle to load data into", ...mocks.ignored ? { ignored: mocks.ignored } : {} } } : {},
|
|
76766
76821
|
...live2 ? {
|
|
76767
76822
|
liveCalls: r.liveCalls?.length ?? 0,
|
|
76768
76823
|
// Beside the attempt count, because the two coming apart IS the signal (#1883).
|
|
Binary file
|
package/guides/headless-loop.md
CHANGED
|
@@ -111,7 +111,8 @@ when that shot is newer than the last source edit, or else the reason and the `h
|
|
|
111
111
|
whose picture is new ("Still building: here's the home screen now."). A passing `himi validate` after a source change
|
|
112
112
|
refreshes the home picture itself (the same offline render, bounded to 30 seconds, never for an unread `--remote`
|
|
113
113
|
template; reported as `homePicture`), and an unchanged `himi test` crawl's home shot counts too, so a long stretch of edits,
|
|
114
|
-
validates and crawls still reaches the owner. Those automatic renders are `himi render <home> --mocks --png
|
|
114
|
+
validates and crawls still reaches the owner. Those automatic renders are `himi render <home> --mocks --png`, and so is
|
|
115
|
+
your own `himi render --png` whenever the app has recorded data (`--no-mocks` for the offline one): the worker's
|
|
115
116
|
load runs against the app's own recorded data — `dev/net-mocks.json` (`himi test --record` writes it), then the config's
|
|
116
117
|
cms seed rows — as `himi test`'s shots do, never a request, so the picture shows content; record the site's data once
|
|
117
118
|
and every automatic picture after it shows the app as it works. When the home picture a postcard carries landed on an error, loading or
|
package/guides/himi-test.md
CHANGED
|
@@ -205,11 +205,13 @@ every write refused at the transport) — then crawls hermetically on what it fr
|
|
|
205
205
|
every run; record against a **QA site**, never production. See
|
|
206
206
|
`docs/dev-network-gateway.md` for the record→freeze machinery.
|
|
207
207
|
|
|
208
|
-
**The pictures use it too.** `himi render <id> --png
|
|
209
|
-
|
|
210
|
-
fixture and never a request — so a data-driven screen paints its content instead
|
|
211
|
-
placeholders.
|
|
212
|
-
|
|
208
|
+
**The pictures use it too.** `himi render <id> --png` runs the worker's load against the same
|
|
209
|
+
recorded data whenever the app has some — `dev/net-mocks.json`, then the config's cms seed rows,
|
|
210
|
+
never the canned fixture and never a request — so a data-driven screen paints its content instead
|
|
211
|
+
of its offline placeholders. It is the default (`mocks.default` in the output); `--mocks` asks for
|
|
212
|
+
it explicitly, `--no-mocks` renders the offline initial state, and `--live`, `--static` and
|
|
213
|
+
`--state` each render the data they name instead. The automatic pictures (`himi init`'s first look,
|
|
214
|
+
`himi validate`'s refresh) are that render. A picture painted without the site's data — the initial state, or a load in which a
|
|
213
215
|
request found no recorded data (a shot's `offline` flag in `.himi/shot-states.json`) — is
|
|
214
216
|
captioned as an offline preview, never as the app failing.
|
|
215
217
|
|
|
@@ -1406,8 +1406,62 @@
|
|
|
1406
1406
|
{
|
|
1407
1407
|
"name": "version",
|
|
1408
1408
|
"kind": "const",
|
|
1409
|
-
"jsdoc": "/**
|
|
1410
|
-
"decl": "export const version =
|
|
1409
|
+
"jsdoc": "/** SDK contract version; not native support detection. Set the bundle min_binary_version at rollout. */",
|
|
1410
|
+
"decl": "export const version = 2;"
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
"name": "AppleTransaction",
|
|
1414
|
+
"kind": "interface",
|
|
1415
|
+
"jsdoc": "/** StoreKit-verified convenience fields; the server must independently verify the JWS. */",
|
|
1416
|
+
"decl": "export interface AppleTransaction {\n store: \"apple\";\n signedTransaction: string;\n transactionId: string;\n originalTransactionId: string;\n productId: string;\n appAccountToken: string | null;\n environment: \"production\" | \"sandbox\" | \"xcode\" | \"unknown\";\n}"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"name": "TransactionErrorCode",
|
|
1420
|
+
"kind": "type",
|
|
1421
|
+
"jsdoc": "",
|
|
1422
|
+
"decl": "export type TransactionErrorCode = \"unsupported\" | \"unavailable\" | \"invalidArgument\" | \"invalidResponse\"\n | \"notEnabled\" | \"unsupportedProductType\" | \"unknownProduct\" | \"verificationFailed\"\n | \"persistenceFailed\" | \"ownershipConflict\" | \"storeError\" | \"busy\";"
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
"name": "TransactionFailure",
|
|
1426
|
+
"kind": "type",
|
|
1427
|
+
"jsdoc": "",
|
|
1428
|
+
"decl": "export type TransactionFailure = { status: \"failed\"; code: TransactionErrorCode };"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"name": "VerificationPurchaseResult",
|
|
1432
|
+
"kind": "type",
|
|
1433
|
+
"jsdoc": "",
|
|
1434
|
+
"decl": "export type VerificationPurchaseResult = { status: \"purchased\"; transaction: AppleTransaction }\n | { status: \"pending\" | \"cancelled\" } | TransactionFailure;"
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
"name": "UnfinishedTransactionsResult",
|
|
1438
|
+
"kind": "type",
|
|
1439
|
+
"jsdoc": "",
|
|
1440
|
+
"decl": "export type UnfinishedTransactionsResult = { status: \"ok\"; transactions: AppleTransaction[] } | TransactionFailure;"
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
"name": "FinishTransactionResult",
|
|
1444
|
+
"kind": "type",
|
|
1445
|
+
"jsdoc": "",
|
|
1446
|
+
"decl": "export type FinishTransactionResult = { status: \"finished\" | \"notFound\" } | TransactionFailure;"
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
"name": "purchaseForVerification",
|
|
1450
|
+
"kind": "function",
|
|
1451
|
+
"jsdoc": "/** Apple non-consumables only. The token comes from authenticated backend context.\n * Leaves the transaction unfinished. Never falls back to legacy purchase on old binaries. */",
|
|
1452
|
+
"decl": "export async function purchaseForVerification(input: { productId: string; appAccountToken: string }): Promise<VerificationPurchaseResult>;"
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
"name": "getUnfinishedTransactions",
|
|
1456
|
+
"kind": "function",
|
|
1457
|
+
"jsdoc": "/** Same-install recovery; does not restore finished purchases or override ownership. */",
|
|
1458
|
+
"decl": "export async function getUnfinishedTransactions(): Promise<UnfinishedTransactionsResult>;"
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
"name": "finishTransaction",
|
|
1462
|
+
"kind": "function",
|
|
1463
|
+
"jsdoc": "/** Trusted callers must first obtain durable backend processing acknowledgement. */",
|
|
1464
|
+
"decl": "export async function finishTransaction(input: { transactionId: string }): Promise<FinishTransactionResult>;"
|
|
1411
1465
|
}
|
|
1412
1466
|
]
|
|
1413
1467
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1135.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"artifactId": "himalaya-cli"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"falconPackageHash": "
|
|
70
|
+
"falconPackageHash": "708ea7531c66305a8eece0a6f7cffeefca465601cdfac12eb39a0f14"
|
|
71
71
|
}
|