@wix/himalaya-cli 0.1386.0 → 0.1388.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/stdlib/wix-sdk/video/src/display.d.ts +66 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/video/src/index.d.ts +185 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-auth.mjs +9 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-video.mjs +324 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
- package/dist/cli.mjs +1249 -491
- package/guides/branded-lite-site-binding.md +12 -5
- package/guides/himi-json-output.md +12 -2
- package/guides/iap-products.md +91 -11
- package/guides/importable-sdks.md +1 -0
- package/guides/sdk-reference.json +253 -0
- package/package.json +2 -2
- package/templates/beauty-salon/README.md +8 -3
- package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/beauty-salon/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/beauty-salon/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/branded-lite/README.md +8 -3
- package/templates/branded-lite/dev/index.ts +982 -16
- package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/branded-lite/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/branded-lite/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/branded-lite/tier5-src/himi-branded-lite-video/index.ts +23 -32
- package/templates/branded-lite/tier5-src/himi-branded-lite-videos/index.ts +44 -38
- package/templates/community-club/README.md +8 -3
- package/templates/community-club/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/community-club/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/community-club/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/events-meetups/README.md +8 -3
- package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/events-meetups/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/events-meetups/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/gym-fitness/README.md +8 -3
- package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/gym-fitness/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/gym-fitness/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/nonprofit-cause/README.md +8 -3
- package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/nonprofit-cause/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/podcast-creator/README.md +8 -3
- package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/podcast-creator/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/podcast-creator/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/portfolio-creative/README.md +8 -3
- package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/portfolio-creative/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/restaurant/README.md +8 -3
- package/templates/restaurant/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/restaurant/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/restaurant/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/retail-store/README.md +8 -3
- package/templates/retail-store/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/retail-store/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/yoga-studio/README.md +8 -3
- package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/yoga-studio/tier5-src/_shared/video-caption.ts +21 -0
- package/templates/yoga-studio/tier5-src/himi-branded-lite-home/index.ts +31 -1
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +1 -1
- package/templates/branded-lite/tier5-src/_shared/vod.ts +0 -71
package/dist/cli.mjs
CHANGED
|
@@ -3738,7 +3738,7 @@ async function browserLogin(opts) {
|
|
|
3738
3738
|
const log = opts.log ?? (() => {
|
|
3739
3739
|
});
|
|
3740
3740
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3741
|
-
return await new Promise((
|
|
3741
|
+
return await new Promise((resolve65, reject) => {
|
|
3742
3742
|
let settled = false;
|
|
3743
3743
|
let loginUrl = "";
|
|
3744
3744
|
const server = createServer();
|
|
@@ -3804,7 +3804,7 @@ async function browserLogin(opts) {
|
|
|
3804
3804
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(closePage(opts.doneTitle ?? "Signed in to himi"));
|
|
3805
3805
|
const extra = {};
|
|
3806
3806
|
for (const [k2, v2] of params) if (k2 !== "token" && k2 !== "state") extra[k2] = v2;
|
|
3807
|
-
finish2(() =>
|
|
3807
|
+
finish2(() => resolve65({ token, loginUrl, extra }));
|
|
3808
3808
|
});
|
|
3809
3809
|
});
|
|
3810
3810
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -3916,7 +3916,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3916
3916
|
tokenCache.set(cacheKey, fromEnv);
|
|
3917
3917
|
return fromEnv;
|
|
3918
3918
|
}
|
|
3919
|
-
const token = await new Promise((
|
|
3919
|
+
const token = await new Promise((resolve65, reject) => {
|
|
3920
3920
|
let child;
|
|
3921
3921
|
try {
|
|
3922
3922
|
child = spawnImpl("wix", [...args]);
|
|
@@ -3945,12 +3945,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3945
3945
|
child.stdout?.on("data", (d2) => {
|
|
3946
3946
|
out2 += String(d2);
|
|
3947
3947
|
const m2 = out2.match(TOKEN_RE);
|
|
3948
|
-
if (m2) done(() =>
|
|
3948
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
3949
3949
|
});
|
|
3950
3950
|
child.stderr?.on("data", (d2) => {
|
|
3951
3951
|
out2 += String(d2);
|
|
3952
3952
|
const m2 = out2.match(TOKEN_RE);
|
|
3953
|
-
if (m2) done(() =>
|
|
3953
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
3954
3954
|
});
|
|
3955
3955
|
child.on("error", (e2) => done(() => reject(new Error(mintHelp(label2, e2.message)))));
|
|
3956
3956
|
child.on("exit", (code) => done(() => reject(new Error(
|
|
@@ -4160,8 +4160,8 @@ function committedProvisioningPath(name) {
|
|
|
4160
4160
|
function committedShellFor(path2) {
|
|
4161
4161
|
const normalized = path2.replace(/\\/g, "/");
|
|
4162
4162
|
return SHELL_NAMES2.find((name) => {
|
|
4163
|
-
const
|
|
4164
|
-
return normalized ===
|
|
4163
|
+
const relative17 = committedProvisioningPath(name);
|
|
4164
|
+
return normalized === relative17 || normalized.endsWith(`/${relative17}`);
|
|
4165
4165
|
});
|
|
4166
4166
|
}
|
|
4167
4167
|
function isBrandable(repoRoot2, name) {
|
|
@@ -5199,6 +5199,8 @@ var init_build_lib = __esm({
|
|
|
5199
5199
|
// Cross-vertical media sizing. Not a generated domain client — the one place a
|
|
5200
5200
|
// Wix media handle becomes a fetchable URL, so no vertical re-derives it.
|
|
5201
5201
|
"@himalaya/wix-media": SDK("media"),
|
|
5202
|
+
// Wix Video. Hand-written: Wix publishes no REST surface for it, so nothing to codegen.
|
|
5203
|
+
"@himalaya/wix-video": SDK("video"),
|
|
5202
5204
|
"@himalaya/wix-rich-content": SDK("rich-content"),
|
|
5203
5205
|
"@himalaya/wix-stores": SDK("stores-v1"),
|
|
5204
5206
|
"@himalaya/wix-ecom": SDK("ecom"),
|
|
@@ -5692,8 +5694,8 @@ var init_catalog_v2 = __esm({
|
|
|
5692
5694
|
"../html-to-t5/catalog.v2.json"() {
|
|
5693
5695
|
catalog_v2_default = {
|
|
5694
5696
|
encoding: "gzip-base64",
|
|
5695
|
-
sha256: "
|
|
5696
|
-
data: "H4sIAAAAAAAC/+y963LbOpoo+iqrNP1v7F61Z3rPObPOny3bSqJuO3ZbStKrZ3JcEAlJWAYBNgDKVrpStR9iP+F5klO4kARIgJJsSZSz8CcxAYjE5bvju/xzsIKMI0oGvwyWy/znf/sl+ff//I//nP3PP/37//i3/+s/k/R/Ds4GPFnCDAx++efgDygd/DJIaJZTAon4o+7542+cksHZQCCB4eCXwQeUAQzW4KfJ1afxT9XowdngIaFZJv/8ZfB+9HF0P5yOrn6aM5r9lFAGfxb8Z86Sn81bBf9ptv5pAcm5fP+5ac1+4z/9f//7//yU0p8IFT8tAUnPYYrEH3+6hgRBIn6i5KeCPBL6RH7KGc35//MTFwwlqoPBfxSIwfSnf/0JkiLjfxycDf7A4Hzwy+Bffv5DCuf8Z3u+qkUuvG785Z8Dsc7lMunsN5jIUfIrkAkE1VC5RdUY+WWyGHw/G8xoulZb6H5NNX8/G2Q0RXMEGW9/4PvZIFkinDJIrE7AGFgPzgZIwIx7XlzP+Pv379b3m5Mvd2Twy3/pvq/NBeUgeQQLqLeBcHl4S3PCcm76hZ4Vq833LOf72QBgfDsf/PJf/xygufqE88HyjeXXPk8ESB7VD9uzlTNY6p1pTNv/+ebqXrm1ci1oQTIDGhKo5NwwBKnchrNBAomATGIHAwjLNjllnoNE/l1/lBTZDLLWIqvpfVXHuN2GfYgbttuG/f1H27B9bMo1+La+RlwcaFuqtb9oT5aUoW+UCICtV8woxRCQQSe8nA24AIsFZDfc20vJXYHxlN7DOYN8Ofjln5KWgQUiQChG+U/1CpQ8rj9AkELWPdezAaNPkyeUw2Eif8/1C9Qq74BYekknICgDAo4bW2Stj0HJuOE1WNNC+IcklAhIxJhwKKY09y7WHnNBhaDZZgzTB7QLJL1nKD1JKEooLjLCA1uj+m5gioqsa8ToOQckhakf1jrgsBsGuqDUeyL1cnY5m0vA0lMlfDlI0yASd2xsQhmB7B6kqPCf7QwkjwtGC+KX1XoiuJMcI/EZwacDnUfOUAbYehO9SqEACG8aZV52A56/oNQB4QCQll+vPrDL1lyhFUo9L93Lxnzf6YxAcqh5DFYAF35ZOqEYg5zDL0tIRlku1j6Sv8s61EsmAgh4oLUYZdBH2IpZuBMllPhxMqm5r/77Gswg9o5Vr5+I9YYJhEfoD1T9JQmoQZjDhJJU/51jgIjaMPMz9M35Fc8GZ4MsbRMJvQu7oMEUPh9KHBPy1d7NhFmOJZyorRcog/eSKsiHDBGUFdkkARi+A4mgzEttM0qoJNcwvUILJAISjWAFSUoRy8cOQ4eVUOx8uO7JwPM1ItDPAzLAHlP6RAKzgc9iKNnAtizgbPBbwQWar/VRwGdxhRgsgbZ6BSgEHZwNsJA/ZgKr0SlMKAPNoQVJIcOIQAlvgqFHKJaMFoul+o3smHTywC0oRiVpfm5QnvaIe7iCfmF7F7IzzqQl4TAQXDA/NQCcQz9oI4IEAph7O58CbO1ssIRosRRd8vQV5AlDeRCYzbAbmjqUYo7kquYIY33kUCT6sHMMErik2GgbniXmMBH3EoT8wtIS5M6XmDH+SBEIphKgEUuwPoQgCZYTazJ7G2UQ8W8zgxKSEVk011uRlrMBZUhqWEYq2B6e5FwPA04EZHC75bRBpwkgddcKMARmuIVw9VnB+VxOx0sDDWdp/Sa49VvBY2P71MJ34UoXhRAHOwZGA2Q/LEPYokKYbaSIy4NI/cBc9gbVM8MLxiFkKRlDcACmoKHc2OaLgAxxNsDaHjYvOnFR4vAtweuQZWCDfpQh8iFE5LxCTLXpu0oz7xDEh9I/N1HNsLiteoJHT8nlEpCFkYge4XpGpRKt4Q0mBQtw0qzAQsIEvOmWS56vIVkEeI+UHy5BjgTA6FtLZCBUSQtPlKVcSakS+xOobANLwEAi5A3DV7WGSTHLkDCzLhYLyEvzVPU6datD53NtgVXjK6G7HJPqTy6kVEOkDKk+m6r/ADP8a06Tgh8OlRIMATNUyLvzS4hzyKYhERcy5kiQ1i9zBufoOaBGzENdM8qk7AZ5QNZdAYxSy5yoJhDcH9UbmPwuzHJKFwt8KOkLB7WxVVi23AXPBAPJ420QQpLH2/nc37ksstm+RLzG3um17WTkETDPj2ZBqFfUvdUZIiFiFDCS10fz6i0ZroAAh9oRJDWOTwHVoFMBCEhbu2DcBUgPpu4EFfawyCPoIyThngB0NGcvv7sTmweLo9sselnoHaMLBjm/OBgw5+YLXpwsO4NIHtQSFPm8DJpRwkQFkRQKyDJ5N9ZtPkjDOmN4vtW0tjuwand2ObR3lGWHIj1pQI2GOH35nZWWw2ppp8tIb0t5zTujdFBNpfHSXbfvkDJ8YA/D0oYU9YKCXj2/raWyG8i58X7phj6U7rZxctNGSvA8Nn+QV8dIGwRLKV5LwGeDJ8BI6XIhXxDEzRXiaIa9OP9qMoqSx4MJSDSvtJwA9ikcgxgmAqbjdAvBdJOaaT4Z3EqFhOZVDEqdraXXZZAU8nSWECrT4BJC0b5PKNe208UaEPCgG66YxyeCnkOGhnAfeA73NSyJqbYiytsJecEIBFR/fm0dVpcYvNM9oLw6mxd4Ykz8h9k8LgxfrW4gaHkDAZVN/6zC3BQIoC8GartSF2uA5k7AUn+/m7ds4kD2OvUMd1KAHiGGh7MXvtBsv8EgltCCiFcqA+8YWEinggmmh7rESwAP63iycxPhS+EcFFhcAr4Fx6u+Vr7b/f0uQPGFskfIJsVMMHgwhYlB+GdOSXCDcopRYnBiDjCWXiI7IYPzhep91st2whNlPjtN+6hLU11bYgpntCAJ9Dsu7SQhYQHZ5RLl/HAOSvn2okCnyN7GFGXtnahf+8XNxiZ2Sglt96Kc76iEzw61i0K+eo/yFG+6XQiaS6FH+lBqjr5BoJJXESu4g+KoVuDMcjdEVWQdppeUCEbx25Fcd4K58vsv3qdLwGjBIT5NT9CCMeUIm8LNFk99DZNjsB5LN5AVwAFf4i4Pz1d71d6BxcGk9hws4NE2ky/p05ikKAHCfw3TtPOoye1qdK+/cChZHeY7soiN+9QihSkVEgNnQIr8ehz0eJbpuTQ+sBOuau8hRBbGx70P47zsHAadd17oYAiNt/aHLm1Au051jnm9bzMDGIPnoN/cq50F9bXKRDCUH+j4gPpCByPW/ZtYVsirha4gwyAPuzVl4Plzyw5lez3Rp9sVZHNMnwIimOm9DKh3UrEJe3FRMgW5JmGy6T0DKYLktbe0F4CQgyGcz/aHyJwqE3CSSON5bQSU5gAieczXTnTLghZS1xUnRTxDPGg23OTW2yRx5UrOXoAaEwKSx9nBrmm23pFCe30GpIeXH9ZOO1nOdifagiETVwhguji6/3jX7iaUzBHLhtYmJ4AkENstKeSCFUpJCEZOybeEHcz1O8P9GU0DvrJ+5yl32rscxD1Klgf0CmfFBo2j8VU1fifDD5wdMOKlCN77SzesDyIL3SEF+f5GT9uEUYxHpMO1UB32ogTOHMwQRnLC9+3LqY0y5C6MRcZyyojCQzkAwa3szi8U25QsIH3huxzENl+HVgwbKPpJ2drjPpcs4Yop37dkCZNHGShQs8DXhJWo7vA9e/mC8IhyF0IjdrrBwIeLqOpwGdjV00iqMlvokMz86cG3QvpbfX6hY1TQZ6LTzNntXbzTKSlbC6LksMalF3nvPSIdP1mij8KWGX2WgQUgRVRNS4ZZ5ltZo7oPottde6Mjyi57LtnwCon1oS0GL3XW28LrZvdIARbwRd9JdVER5BN1O30gi72OZ9gihBUSsY01xtK2N+onUp98z8BsBlnIon+l3+Hc5odgtuoOO/6mC8f6M9MR+mdWIJqTJCModhonhWZIs1aw1bYogUjrDoWgZhkB2hYiFruAyo30aDiQVYIkS7oxK8Mmc/F3r/mN0VzFDJrIGuXurpWth9IpY1Ncf1g32MmVm2JxOLvOVjsY9r4MG98aAK1vdrrAWsOjXhJDMiGC83sgf48pWTzkTOvD1XAHGXfZ2zuaS8TodW+3pHOv2s9Xk6cGudsLYMvr3qPLOE1BBnAu895IspgXKqKlio/R8ZnC2Fk2Ra6Yfm2JDdm5GczoCgS5jqW0UHIvx5bXJuYaLsCsTG+YuWC46nDMDXpQdwtinf7VO8IBH6vtP6DwteN9jf5N2H9kkyMgGaap7yT3pywc0hltWWU7arswUioCXa++KEHEvQF60c5cIZ5gygsG30t95LRyXsB2AiELo8resF9XzStetMGUmMCwHfmkMn9qrwevM9SRFVPvhnQmRdxtpcd20w6G4e+eCeP7bo5CB4sRbKfb2oLoMvq0SU6XQ/bAc96D4mDRWscKzNteyJEmGiC9yaXmB8pLvg7rwKZTeHGkzy5nJC3vZHF8q2Vgu5H0/wEdV0muiSucqiaI7d3gwcO5hnYStgA7rJwVjiPZVgyzDDUlJO+QCajjRodDhjb4Re8kaVBSiENuKMco2ejHrQdtBJu2eXCJkkcSijDUWY+mQUFG90+6ZJ19sKhruJAZBvpxI/y+0cBDGbJjeF6x0CsgQL/8+PUM+GywRCn80NQdHJVR6BDs6u8wNwTP9+5sauD8BmcMvFZPkNfphxVoU5oU0g7bGYlgDwqokteIPO4UqvCyXRil6HAXIMEUS+X6X75Bm3RxQSneBNUu7y5yGVk1gWyFEhjMjzVcAYTDxpyuxDqHOEmZvRYcMoakWzzZvGd4Ox+l+jPNl77EWaaHgOWOfZK+oEJAJmsw/L///d9/4Hplv/zxX//7v//4x3/9Q7dYv9noFArVeV388meKEviRHix/6BNYwbmMzd9JNCx/FSYc3S53dXdHlBhHHW+ou7syOwsY7gnPHWK0gmzd2dlhrb+Td30GDO5AwWuYgPCxsksCAV2IuYeCrUsvC7GrsM7ctdYbxbqWGlREZ4Bd7iEW8wawfxTw6KlZNjl8HtaygzKobnkPs2hIxEZF6qwctQdLgAx/OaxTTBL2Ct8lwGWXRX2REf5vLQHChjCy3cJOKDt8OoJtghCfgEiWu14QbbBW72GHbkV+yFsxHM48uJ9sidKRLcsxFHBTvsSdQoXB7FDiXPBqN3jUTvrRhn2OwUWBVfAWz4BK84sBW8Au4+tubO1wl+cCiSL1s3LpgBHu/UZpFszADTeGB5lRYfNCWJ/aaJ1ltHCkE79toxCwlbkYKb99XZNMoERnyFzSp08csmvaymNufXNOMd5qHBJTetm627OVSZC3UtRzAWReepV/EwiIMVKJUZbrGVMCvsTAG5BbLgU3an8dH4MFajjXyi3oyCuRQQbC0q7MPb2R36hBHTRkIgdUk5TbP6EFS3ZmsJ9RCumRow1yykO342UccbiCD3PtFFYvpk5RHyfRbPAa5sWhDTuJZum8h6COLhv/kj5Z8mJgQ7kATNy5oUUuGQsbdoBE6skSvJ6XKZONVNUOGATIZcnHgGy3nWMkYJ1hy3IjjSI8UaUyQikL/fmujDuqpC2KlEnrF1ArkSUnBsqmnEJddMNGkspRtkBYjIkZn6lrzqTg2itORXl8bSBfFQIiY+5k1mOSQJ1xi5QhpvZPVJuM21lPl7JKGMX+8k8dmFiibyP4RP8rZYMyzTdPGIRGnshRIgoGx+RO/6Fb63JGEm6MBVG5jkizEsBua26e7ndX5ueUPQGWTh5R3nWs8u3bjJNo+dcCFh3+1pdLkAtXSGiMmDJAdHb7PVO8bco0fK3Ie8i7D+Q5BEzGCxqJEFPBa1YL0tokEzLPjEjlNTaqU3VRcldnA1XP7ypgcSVuGfTlJK+QtOoSYqxE0ZDzpzSyBoIturJa7HKPR4VAhzJH8FI88GXeDzHObnbMcxio8hZOF72TdXrVw2YAJsr09QF75A1IlqHIu+4N28u23FAilpcAQynXHmh/1hAESxcF1OHSQnIVtOVaAzpMumXln82Z2aqRHZkkGRdfIHxMnROxzVI6nuyqqudEid7fRjqWYfobSBTpI2IZIL5y0zqiHIhYdnk1BfctA8+dfVTwjgORxtUGuZZZTJS2pmMEv1pnM5GCysYTrEaFdRwzckQ2w4MZ06XrqJH3L7EfShvvAattttNuSjD9d/3fk7xFUEKSCnEIbkTdHfZNX20I3/peDeq6ZWHiAy38iA1JGuzbiEYSQz7Sp2uXKjpeX/oMRyutvJubFbJwrlbUAqZ1ebXuKrJQE/GNrhjluI6oMiTCigwnIL9BpBAwVB5XLaph02OwoijSrX24oUAfg9Iw1j1qp4hN6RAEDnWxsQ9gVGkBpjRMHawBHSBdVx0OEGWV1jWY/9oDlzsBYQp5AknaFSr69bsurGt+paZpCrjbteTrEvJnAwEWugGdr7gaaSdJtwMItL3tFanT2RwoFPqvAaIqWoykjKpU6BlIVMsTnElWQepOsZJzXOleeStA+eBr6YVYT69ZN7aeKyBrU+2+hNcyMEvCd9lmSgraTVXU1vevB5q9Nuq75XRbm2wRvsNNIVhAd89fVUg/aS7xKKXb9wUHwaqPHUWIzwYftkbCZUTCiIQRCQ+BhH/fGgm/RSTsAwkjBmx3CJ1Qfg2+rWW2qW3gHINv63Osw61rUK+WdcpwfjaYoUoYNlU8LOOozFSXLAFBPBv8In08l2pKS8rQN0qEjpVvrc9WxX5oXqM0dJnQ4Yb3OQlK7gqpeN3DubzI8U4llMpB6a+BazSZ3zXzapcgTdXFGMB3HqXWdicCbLHTG1qYTQqMJQY3Z9feZA/8dem7G7bme2iOc4A51OSjeffXJkt5wZcOAdIpVuwWBpX/s9Nm8vg4ber2y26QF2sP5mbNbgcysaX70SpXaIvqVQDwtXu9hwFh42ekYE3Wzi43clvwTQrGQ3nmyDUF6Q11brMjFkQseB0WyMTtk0BVzUaxgRoAe8Eti0fVJjcXubrsZIeYEldlg1Ss3USWwtDWU74LxlspOjfc+e+cjaH0k6zgVwJPDcxB1Au3fP3+1XamjFQoUqH9UKEN6Z8b79UgX9e37357IxltxLKIZRHL9o9l33uVCRz/pxbvtZM+HXASJtvKOGgoOZYhgUmPSQ6vwZoWoteZGHe9sUwYNtUuXn1ZFeyp6Ky4J2PUN4Wm+rRnvq5Ul2tA87nphUzzDZOTx7ehZQuK/DDyw33pvpaNJlpmInT+DiwzDeNJp39b26wRjRkRcSPiRmNGxLKIZb9nY0Z3usGmIcAT5d7U0P2Rxg3VORQN19Bpu6WFqqrx2UCFJWzhELJgSgP9XfiCWAkY+7NUqCnIqOMiO4GJjKxk6L05pvTvG3MSNsYTcNDx0pMacd6wGaudfNWpQO0iZWjEqF06wDqWDkNYN0/pMpNtOhE54NIElG6i9Sa8/026uOaSaffsQNc/nUooI5DdgxQVvbKxOgVCr5cy0e35lNyeLRTdiTg2gdqb4KKGtrZIflx360mOkVAJd7YguVwOPl/J0TbhzRnKgE4t2r+LUwoFQPg05mI25gY8f0FpQBzrQxIqD6zarV5R1QKfDXU5zcF2jfJsebcM0t4LOeIKrZAxPG9CitQMtTDC/USfm/td4zhItlsL1yNt5K5SN/bCF72qcdllq8XSnoSIqbSUUIxBzuGXJSQjGdTco2vB6cBCZ9Urz4Z5QrTPBqp3Uiah3gRPKqL8XOestoGqqvHRm3Zq1Rnpaw6lDdsj6+3Jmn1YeTXZNWggGs2j0fwkYl6AmzykLwKgKFCVhbVvUtj7RPSpeKbhgXQjtDlwp5IFNltzDBAZHIsalm4QXXPnmTPBLD22gq4ZX6+SyAuLncZb38jA3ggDAxuyWLkkN4gG4RENarknGumSsS2Jl5++yOYymdQmPUEVPXEUBPPD01E6zRSDOqew0mBtKxDbvzkAPWmeS/m1naQvuYVe2SWD93AeYnYb6KjoLmHThjv5OdYgBLKswKpBCeTyHDsoytwGOp/LkuAe1BYb9+XHXNbBRSOVRrvIJgnA8B1IBGU7G0LLOTDi/QAlVFmu0iu0QGK/IS0+2GcFScIh810kqnshvG8RvCoV1dcEMvAsM2P2eh0oi4ak9In0Go8k2c1QXgXt/TbQavyt4ALN10dQj+RyrhCDHptRe0kyMbQzTywaRFLgI8y5zpq8acIFSSHT5dFsYUsw9AjFktFisTzCfOUEJqdwq386xvfKw/Fz8BbjyBO5hyvYa/amo95HAIwNqmwrGgbKH7ZE2Wchk/O+QMB+U6J48GdbLL0W0H9EqbWlc+rVKnvOxkzkXoHUl7+/JVZ6KpA7wqDHG27XspyuENSa1Q9+rq745dluWy46oDTUElheI6a4ksQr5IcGi/d5dm6+x20zxeCImlu1L4PV4Y4zU/Jqk4UHqYG2iceU4jodC4+cUIeBB3AJ033eFxMkEMC8zzk89evHZJeF6Tk9wxXUhaNeYgXY/2zKuiVdWoosPeVYxGURqgbBgSI5hqrSKDzf242jW8OrN1dsWZ9y0+lJVuRyF+lCClOX1SGWYHiEA3zjvisS9MMumUez8SDSK0NhUModiCy2oR6V7uEIegzJzBT4yFfYvd5dh0qIVvJB+9raYtytzqeAm2pn8UE/D/KoGA5zeC1LaFBtzw50l0Ss6NweqNuhXAEcyuBRP/x1tj249AIMUmaCsVnYRoFajrPlaQIy+IZJcgcx2vpexSewhuXFF71vBRiSBbDCBsXN91ie18L5XGLAHpmBT85oeScdV87pm9+dkuTeMIwo5O2VrZXkY99Eo4XXbQ7Y5HN1Vwvb2rX4KsRpn54/J1EHEd+KrXpPTrZeFEJsR7tneqRNvRnt9+a3X294v8eNmlKXRSZ6oEcHvrfpgd67p0eKuCSsaX8KsBfny2l1JT5xxvS4heauYfy2TSHlVcgbX4asOB9yfDhaWaSXef/bN0jHqBQoCWn/xi+pv94SvO456/NpZKDIEPnQ88WG14nbzkPWn2pSysZ+J/oO7/goEEaBcH8CYdCTw5al2gSsKa60ft6QI/bNdpsMft/vtzivh3rvEkniYYQOr2q/3mYivsSEG1KxOGS3O01Ekx6W0S3vtOC6XYjLuRZzndwpp3ETeqpZHrr0gHpAjxtHyeUSkAWMVojIdN6WFeJsAFcmzdQjXFu4CElCNTLaMPUI1zNqUvN1KTgpnIMCu1sBM5lYxwk5XNKGt5sFUZVbHHN/lMJEktZjFFOHScH69RfPCiwk34Y3JxES83wNyaJf1y/pb3kJciQARt+2issgTSB7oizljYhYafKXU3ZumpeAgURAxo8AbJRMilmGRGQhkYX80CyEF4sF5J7Ko+39p6TpUH4Mqq/Q0JMWxsPlmpRl4bqCExmg0qAzaaMBsKP4Ws5pUvBoK4+28trqiSFg9W11byLOEuIcsmmfqR6kBwFjgZjn/q7B1Jy6dN+cwTl67jdt1LznGcwok2EzkPdbw3IFMErBrp4INS/3V91YwGd/bBgitSTeNmjZcrrP3BV2pMnAc7hTN/gY4TaqXVOP86h6iAi40G2K/mWQcxNZ1N6CoIclboaqUfIwwwVrtmlGbz7Wbz3YGtP7JoH90uETcvDe5OYcTqPqWCQ95RdrU2HU7qJ2txftzjbL9WiMq+xlbV7mNWTtyLn8pp8DGnxsm0zE1Yire7LEOPaPXawejmHi0OYIx2Lwo11XN5TfNr1ytdLW8it1sf3LWinzSE7zUJerxrTf6uoXUav4QbQKR/D3Q1kABlWY2JQuFnirzAtCj7SdDnDfma9X/aZjiv4GUUSJIsoJXhbZVXEFA8njba/JNfQU5vNe57AssllM+XI6ntG6tVcLVbgu+iqc0ikapyI3OTI3sUh423ffoq3tzpLo7SNdhh9/VWE0AfN8y8poZuh2pdGOQZfesBCbIdKzN1ufn48ifCS6P64Ij1T93NOTmVZBM1S3YGRolc+y5W2PglTE6T3jdFiAGa6AAFvJL0CPtMUXlZL1E8Mbarh0GdSPLt9Uc+5IC+LPk3ri6yrn3LGuftM3nXjeeBuYd0nA18Ct6jVbpBHvTOvXMZ/mJ8vXbJW7PJDUyKRjvgDpdumYZ2rg26641XsOFUEfITmxPZNT6tL/6gGnkvpM13LotRpl6K43HPJdHb2/JyBN+qtYyNs8sNjqKg8s3nqVvIgyPzbK7Bkx7hhdMMj5xXZSbm6Gn88asm7ZcVrWunJW3Z7+1pheEwSSU6M1iIhOvJUW5steK9r5513Na6Ohtk8zJSIpFJBliISqmh65dFbae7L23nHQhZxTYUcVce3Xbd8i8S1MaVJRTyqpQE5Yl4psvHCtP9nCn2CVnTScazw83xYodLPU+oxkzzvKsm346VyOc2xGaZ/wX8+jNYOmkXHwByaLZA3+5ec/pHDOf05ollMClXH6MLNMlginDJI6ktgXYhme1mFmxTEVMclANFC/4Wy5TXuZlUCrgWm98h/kxxNLW38ZpXIpSRf9iEErEbMPe/XUhXulXLF1RjwpXHgy4vUrYvTuGi/DT/pOiWCHkcS4+hgB81bj6m/q1faFSvrZfxHd/VddNqoRu2cCevRtYV2oS/snuq05Sh5bjbp+79fvLVvVHjfCVNDdBXNj2H2UimLYfQy7jxpMxNUYdh/D7mPYfVQ6TirsfqNMcFBpuor35zFIMLLnGCR4lCDBXlGe19GJPAa5RELwewxy6RUBjfVsB/yjeaVmhG77XnSJGOblXE141xAEXTnpEHJ+Vy0s32WSXtlm2OAQw0TANEBJIkGKBGnvkskmi7TB9iBXnZc3od0QqTXRsIuZ7v8SlGleVeZMwnzaqN9mvXoJV4yS0ijQxpd6h0Lz36g2bQapDJLCNS8uIcQ+IGsddkmQ+2UkaciDtkuM+0TQc+g4w33gOdwXVLX1jZB9xYSyBnoCAXXj10htI7U9BLXt0lD6tL20pZajBb/uWVa0XUtand02zGgN/XGtoTfBCXlA36smBACh9H1oeDI0g8eiP0BkXtEfIPoDRH+AiKvRHyD6A0R/gCgBv31/gAZ5UrLwWZnZ4Gxn0dn4/NqOAPH6P3LjeP3f3/V/AMM1fr4AxysXfufqP174R9SPF/6dKFdiywtwrgyQsS/74xV/vOKPJChe8ccr/h/pit/POgzVfwHnMHfm1d1+vNGPxDUS133d6PuxVUH1VyWGyGQTkvaOSjvgxmwTcvS5Nhuefg7VrsyAHK4gQ2IdCiuvrHdqrQ5RBYwcIcO5ueLtO1veCnE0w32mLnxDmY4tmNoZkuzDblsb61PYoCxYWV8rXWxjwlc90kZoS0HbnCUuqmovU9WOSxFtKTxIFG3lMVZnjQJVzLL3qtJOFkI59Z0swGooz70hnauj95qcdBfE/50bBQ56GE2y0CUn72J7OKa4aBk2+pMYo7k7mrujABHN3dHcfWrmbtlxBQTcXlmW5jOfxuwYpw9RbsJfAvjYX6wN6cf6ojHPdwkfuxrq9zm/qK1GZnMS2qoPSncoOVwQ9HzOYUJJys8tUDp4rfMDFsl8UXnjeMEYKUy8YDQHLV87EUDAeYEnMCk3ZJOQxM1PJEExFMgqOyNakfweR3WqIjMa0V65WLstrTuVFAhwhKu5cnonUZZG78sO8odAIlCSkxezcOehjAMg2S4iJBK1SNS2JGp65HXQPqaAfBKsTFuiQXiE/kDV79lMhjLA1o3ANCleNVtzDBAZWJgwMeWp2y/lmfPLLPVsksbfr/0XDjgCRWJQsHUkHJFw7I1wKIgK0Y0TxDQl75yAFNLYGi3j9XrpUomZhxAuLfmva78rySzKY5GsRnksymMbYqijoBQx+vcrKJWyTGctT4+UoYxUjxBDsaV1qhxrW6WqeOe+SsXXYdV9zaB5Y9zfPArS40bs7/7h1TLsC4Lwt7j4r/a3Gb+vAkIYWGSQiIkU67cJCTHjz5UeYGNUAjjs259QzuGQXuwJlRm4xCY9ACQJ5BzNEEZiPSSEFiSBGSRiq3yB9Wf6dCqXBFqnYLsEvMdykI39qaCsPGx3mvtGX3kSjGLlyiZYAXdEaBsn2sBUAuuPDaINKOp+96bjleO/UPYI2aSYCQbhNjTrSf3gnJtfOJFsDMI/c0r6Jlw5xSjZ6VIHYEyfYDpd51sBkS2U618Ojey3468z8DySbgQwvViLcEbEjzQNd17BPJyv68OW+WacDfCsqj1Va2LWNOyP9mvcmwOMlZx/egY+B08qcLWmfGKEt4nXbe22QriIZqeHZjYmbK0eboZRpTmqbJHvSqfcjcqjGq4joR3OcSKBPFUyqxi+F+1OMXzvVeF7HjdJC6bsvMoR0COg/7CAnsKZ0gZveDTKvaqmQvTfjXRi73QipvePQLV3oHJJvveeAGEB2eUS5Xy7zFFy+Hmixju3BOUbjp5n5sDJ/4O3LCeZMsaJpd7tPCwCcND5qeIrEzXJHtNRRQU3kt4fMD8N90n/5/o4v59Kfpjm3ZBiHb3qAhX3ijxrc4qOXS3eLr1vU/moTkXyu391qjN7h58CyeYpmG0lCAs5zrlxNj88uvw7A+mWBStPTkCN9xuR/kTx7xjpCXnpUd8VrC1o7m7EE8rhEaKwTyRpodzeFVSZjk5KPjasxjrlfvMmG0b3ltlbTDcXGcKxGUI4pqmD7m5KQuehWRtiONrERHvPKO9vmF5q/6ztXGjMb86NU9fJpB5/WyJxTPMdyWYkm29Djj5F+2lJaU9HRDx+ouQoJUZy97szW/oRX466BIwWHG4lxiXlWFt6q/B0s+zW6cd9CCqYLBFOGSR+wUnNq0tsSgrGIBFjksLnPsNjo+AUKcnbFJzkXheC5hisx0RAtgL4ptdI8xrnT0Um04DbqxDWFLV2I9xNKhmroEeidYT8Ql6y0oI9B983SPwaEVUlPbDYspCeGugEhYEFPHlxKMo2kUxE2eb1sg1f0qcxSVECRCD7aS8VUzUN6jdkpiSDUaSItOKt0IomNm+oW2bQTGfMh7nz08358mF+jqpfuNnyYX6a/vinIjNs5aKSUtEELze3q54sTI9doFCfb2M3e06cC/MdXXU3UuiOS+ydTmarzVOGTIoxyDkiiw8QpNuJ70n1m/Ol/pFj2bTqJp5OnftqVq7RUpJpRGQ1tLLi45BzKPq8762Sk/Y1ATtBal9zgM85IClMP5xAskcF7CcxlVIRPX09WYqIGIPndyAJyfg9hMPXCVZ7tBp2lpV1KJA/+/PuSY3byORJddmCck81yxr8XgR0baDoDp8xpyWbhysgAJsIhvJtOBRQw1V5ttxhTrqjf09YPY29+G51whNBAgHMdy8senwObR9NyCHLJBjvzeq2ggyD/F4qdn3OIwPPnxFHM9zrbkjF73YF2RzTp34Djc0kLvvNhywzb+btGvB9S77lpDoEX0qmII+m5GgeenOmZHmq7xlIESTiVO6mexUvGwJO25+9ljxOTt4w3L1ttm6wXV9WTosftml+g1F5IqSbHKQt/Nak3eOoaMhnJJqRaO6naEiDrPnKzV4AQraz1830SMdaDleQoWY11PaeIjKn7vIKlf/caXsCjDTLhKXynokdIbaxd1NVBjkHC9h3YGVA7Iy0KNKiUxbgzIqDuuyxdMhG4bWT8HGsiPTZKRgubZZxIEYRNmFaRDZQ0i7SvEjz9pfW0aVKbVrUXadxIx4r54dyotv4PZRjbRkuCh4RCaPg8WLBo2BqG/sNrPhx9LBTFKBKCtmr3BRFl0g1jym6OHStTc0OL8XvJBtVKKpu+eWWXCGA6WKrW345/DzV451UgdEmJE9mjlg2jBJapDVvU0JLAEkgjgAcAfitqhiQC1aoBGK92jYNK+hZNi8RuvdpZDQF+HTCzrSw0mTY/WagfJEdtiVxRDIdyfReyHRTEoiAFQFrT+WbHA7dZgNN1umpRe/wtDbBLJnNhqjIABeQw+5RspzCZ7GNSsxQsjwXcrCtD7NiP3lCE5kG1R+ZYObX5uRlQFt7ZwB77PRDa0PejOLUAQIkAEaJ01SQFDKMiAt8ssqy04AReTSgI/+MtCXSlr3SliZ6S/zotSxEY0KKJPQqZJZEKZKiSIoiKToxUuSlFrL1C5x9RvBpG1nkCc7OV3KsLYoUewwMr4mRL2UdkZj3QWRH+t5yv+HBnd8CPIeJ2G8YWucHecIoxiMCZhim+zOddH5TScKLXQy/Es0uCiGCGE1zH9I9wZkE04cl4oKy9YNYQvKQy5IB6jYLY/oE01uGFojsmO4BPgvICMDXiDzy0I3bg/m+i/ZrLmD2MGP0iZf3aglIlvBGcg9/fgg4BwVuEihMgcun6HwuEeMBYg4fdO9XBb4ykcMrOUbBIRsu/D7rZ4O8wHhK7+GcQb4MgM6SPt0xumCQ8wvA/IPkpBFZTEN8HjJG2TRowkJEruvP/IomhSyvMBGAia1Gjkgoa/aaFiJ0vrzBNGC6gA+CPsj/jV/GmiQTAUQh1zzMcwiY1CoDnmcSHrmEqDsGV4YUt4ctIBcFg1tIUiniEq2HGPvfZPrvEEmWf6c06xwlD0WXInRlmPZIWQcDPosbSIrOcZ84ZFcMLLo/C/IPaLHEjdj19sCJImQXqmbzFgOr5ES8c/AVEOAKCpiERn7fZIjIYIq2udqShz9WnO0Og7WSK/xQYvI8dsDQuwJjQw3Dg+5QIsFoTMwfHUOHiIW+uHH5OaNZLi7gnDI4soim/3NzTIFAZHHh0PvunYM172q/UO7jgtGCpJdhtQIREe613sD5Z9DxilD3xj1CMmVnAnOhcnfaXMV//PeK9t+SSwZC5Nbwgi18v5cyNo4QidcrJNZB2qxo762K1wvAHoOJjLZbdwzaAlzgHIpkuU0tLbaA4iVsbSN7V6cukuXEH7a4cRGYJgCrXB8XBUkDzCql2URQBhZw1AXAYolYegeYWF9S+ogg7xzNl4DJQkSbRz7B2RWcFYsFIovOgTOG0gWcwKQonYs2OMWB5yFbTNQ6ryFZONGqTmDnkC2uYB7uv9E3UhdrAf0eTwwIeI0yJG7A8yXAeMOoL4ik9MnrPbXxSGWZJkjEO4QFZPcF9spJZwOQ55IDpVc0A7vLlPkSZpABLJmOhA3YdSIfQQZ5rqXxnRKVUcIphu8oewKszCjgEcXQHCbrBMORLPQSIEaKcGlldQoxzKBg69BICSxXkKMFmdJHSELkDS8oQ2KZoeQKsEdIghNcohR+oFzAdIIErFOceb6dZZDx4EWAooCYcthiONagRwjzIQ6+I0dEz6VzHjZ1H/KJ4tA8REuVIvhBiPxSKgehO4wVZBegi7nJbfqCnocp32Yb31EqQtPnkHNEyYWCvsDLqhcNU5CbN7UlZ1dHQ88NiwqHf/qTUV2cyYUEyu/78wXpVltBDmYII/ny+8qEcui0lB1TekVyAuetOxl3i2CCANsq04bDcPaphs2jbelomigCl3mLaEeIdoRoR4h2hGhHiHaEaEeIdoRoR4h2hGhHiHaEaEeIdoR92BFCBoCt+YH8xDXiYixgto2fBUZcnMvXOY4WGIIS32rTQzg982F8zzimov8kXd60qKXDbTApau9p8L3TrmbVlc51ZdzOTmrm1aw6Zi4YQPhkoDamxY0ueW+0eqyK2qdsY14RQpveqUu4YpQ025JH6SN7rHSOk3alon5KoPQ+ETWLSt7qezt6n0jJQ3qeyAnle7bEvC42+cLKIbYk0TZDWcy669sxPXJknnuuYmyzt/0wNZfcB7EkPMIlkMEXhEe0aJsv6fMEoy2LtHE90lYJNfXav8P4y/QB1dVV7SVDpOciK/1Wa4R5rDAdSfjvXv/ZRfU5G8CVcRt4hGuL/kCSUE2ABiktZFpXNfUggB8rNUuR55B93itdfsEsalLcq6pDeq27mcKZus7vNyGo8QRITyY/Ta/aTSWxtG/sEAnd5AUK68I81kSP3O1I9VsaEGUhrkvxW+DokGKv54f/ft8hXq232lSldaGl9IrS10q6UzGKt9Iwyt+cJ+ZHzv1T32m+wtrOUcjoy3Qe/Ypum63SXGfUvciUxYLoEeyz0jkpH6e9GgGjZhJp95u8mdlGPbEdDU5CLj8BiVR6s6RQQJYhAgSMsrHDYFvg0JSabc8iw1925yoW4fcUQIwydKTDe6bD3ZJwl0TrIRdeoXdovJAr7/ytks6bH52j6leHs7EfR+g8CTZzKhS+/yrzfRvCWMsBK5qfdlPTN5KfjmLHQRWfBZyTdTFYKgTNJorYb1MRVg0/18zBJl/G8/w0/O/kJhpv8K2jZy0f+0NLxSdRt1L6k79nYDaDrNd5UHJlZIiolUdp8K35S5qt7FPJ9Ypu1by6xDd3UI+CA0ybRjlf3lTJedz8p8aFzW6rfMsOb9HsuxzE2UBhYNZiu+3NoybW0ck7S3SG2cMX+CsENTS+3ytSfEo1BnuVTy1prUtGs+So7aWnjSVwG5KHJyrYFgmiIBAFgb0IAg6r9sRGNplhO62H4VJ74k3BAg8Nur47NW8R3BaZDZmAlUpYBjBu0gUzOc7WAQFJlk3v+r5UwIpAvbZ0BQqlXAkZ0VHSQCZ5TPUhBulAuOWrOtWNJUe6LZuxYmykqIfMDq+wVmNFn+UqvNqQOuMuTYi3w7U8+a0YzVP61IgG0FmE3O1WO/hgDvbg8nW9ulgb7xSE65oNdjG/JvuJbCmypciWemZLJRvYK/F36PMOdd7kjKaUYoHybcRxYYaeqkRellfqNSL61K2cQmb9PHuFZmlDYiGO4dgpGFosmpdInpUBd2WYksWDpEu8j0nHW6fIg97qrdObE3WDhfXC+QPCtrbDUEiLiO2BdEUDdqQpe5dr5Q/vaC6Nv9uIg7kZeqri4Ek5DP2goln0ToiyYqTrv28PpWiY3VFa3dI34tgS6quvr6NQGonX/olXt/nycrmd7TJZNgyXvQeBbxNPDThHXDTcMPKiscvFQpZCQY0sYnOVov0IMqAhNWNz/eNZz54ugo6xiuEKCMA+sV5Bg8GMrkDf/vsxx3Ak6m9TIqXkXmJQTMMQgfftAa/OXXNyFpVyWp1OTvaYPu9BMVwB0XNeCCGru5xYYQk5pa4DPImEGvUsYyBFVy6NcMKMfakNDcl+3/K8T+RuxxbbsrAvkiNm8I7cfZ/c3RYeI1BFoNqPyGgJdb6KYq7c1HZWsAQaT2nEUtLYMRWNw2h9cTrSuMbHinNsaWLj55rRtPLO8MMXGt9fRhq+MSVN797wCuyXFKew36onZJimUc2ONPPAarYE0BflLLQgI1qFIrj+uMk5LZiKidpbmbJ2rA3s8vg24rvM13MRbrhiJC6RuESlNALVaQLVFqn3q9jJzRn3S1ZVK37LqgZ4X+rJvCrj3dcMkiXCKQtcBLQ4Udgd7EDzrKanUkNyKKLM4EJuC1rmzcrwdZd91i864eoEvNh4hXiCKS8YfC8TXm+DlWn1k3OVJNtBz97DFXsvYy4ta885IOnJ3baW0+oyRDlj+iRxvjiLk6RwlEzpYoGjBSDKUzEk88XM8YUFm21K26avTWLWZq41lXkRbbFxP2J8xPh9BUxeS/8MmF7W4LlJKMP6F+clRJ+OV7pXFNFTcmUQecKIQFwby05rzmVXcM4nFBv6Juv2eOlyB/2tMGVrBHFVlZ4zu6C3HdvgST53bBUBUxbd+SxIPlr2tOrsPZhrDsXn+jEtXe42JoVSA91CHbjIyAk6fEgwoE97ydmaQIx3ulNqiBj69yeXxlJuT5fJoeqPqOzA+fbQXQLgaYOdfc4+6vAeFIutqMNCDYxVyPaR/xSRPksbmOrlv8/KCi9TjLaJ8JVlLAF2Q/cRgeAYgbu9VnPzB6ggIjr5DyKLvfDv1X6rnH/vkZHLbxOU9R/vVJ5dlA1eDl+GyLd+Zajv1mUWuqKDNpCczip//A2hnI0VHud3C1x9Is49EIY4bZJxmB751oWcnhk8IgIyUGX57jHrQV0wOt4RxhuDH8tLGJnbsJ4Ncm/eonoSGmG7GnQbdbibFixLD65XvAkpLCRPNbiQL964Zg+RKUSmsBemELLEH+5WoFvkLgnLluTExIoCtmWYqBzYDhDtm5q+IEz1KBW9Xxim2jY+/a6u/M4GS4gWS9GnSsMhQ3Av5qoNF/M71k/dEN0UpkYlTLUPUjD6CE/NMHZyQWjBLX/JKQYPI3x+NUq0EaGC1QihDR8v6XpPSSG25nCpHO3hcxyj5Cj0wHvCwev+U7uE1tvUmWesHnFS6tdx2YtYouSRQN5rxfNEpoRm017DOLxQZE+syxFQDZv0HYnSsYRqbp3ujNG/CjZo7JugrA4hC+phrS86qN+ej4uTbfbZgvndfMOu4QJqNrvRk1OPtJng3spmh08qLB6E3VgzwB7hm2CPG0sNn0S1XsqQbb753dOlVxbjPRlg7y412jh1H/G4AgJs7VyaAgH25GEa2Fh1U7JT4TiA0cKfbe0ppF717B6yL6fXQEXolzglRrfXnc1ZKIUfwgkVjpecVwC8U52qI0FND8mU5U50gY01ok+/UfB8HyIAR1ISv8EZAzGzxG5O46fNsF7nx348TtLhyd6kqb4EqSWxOxES51IUj1xXoXoLwSsc9OYWuUfJcocQVoaSpTd+NaVJkUEi/swp6Zvw2XM5LcNOa5cCDISSa0QeoydadDp4c1VM5gBjtcIYYW2jg48+trN2NwiXJ79kSRciNYjUYC/UwMbXDXH8lqwwSpGgbFeJ4Rzqn9mCAwEZPAVhIQotJ5VfXlCKt7NdfY+BAZEA/yDi2L4DAVLExDqYLrzIMQXpBLIVSnqlwXOE8XAFEO699GmGyIfe3QffjAh9WJG5lAyCYvLL5ehNedwr7tPBc2JAQGQGe2cGLZLcTkPcpJVtCukQsRbp2kHgv4EpAu+07WqzpJ/J0efa1NXy8j+keO0hoUdhbcfOVrHhesOJ9HU34Ovrvrq7x3OQNG8G8JDHw/aLLXXVKXwWW0Ov0lNlki4PBKO09/iUvtXTftOwnFLds6gMRv7/Rm3zlEyKWYZEBN4IvG86DbrkyP16daZhz8ug7BP25dxcVyzqmhFd915arOYGEagiUO0jMX6bSsu2zxQl8CMVW7l+r+TgcyJH2zrYE1jBOWXZG4nTL6fb5eXjjOnz6rFgCjhv+GllLqvn1bWLjVF9qqiUo1Pcx3peXfvYGNVnfK0A4sQiMtWUOiOTqwF9IjLEaAXZ+sScHs2sOpHYHtOreecOg3XUj6Ns9AaNO3eg4NEwGWH3TRomIYz+7hF03yLo3gMB46VQBOC3C8BQsCjzRth9e7DLgDjFzJ1mZqdlBWIbLBjsBAwYvRam+X42mAF2SQvSo/fvCYWs2Rb37bGqadRuO+c61ubW3rbNuW0O49hZW29oGzI9SSENevp7wnO3DGzBznCSnMq4FNlrZK97usOtjD4RpiJM7csvwBhjIkhFkNoTSLlGkghYEbD2BVil8SLCVISpvcBUZVTYXulhrjpR6yKsS5sIFly01dDmx1RcFmD/KOBW3lSZGWq7UpWl6H/H/kZK01tj+DsulHJCloYSIHe1FVRHuFsa6ynKoCx8ug3+iHKsjUCQiH0VeAln7+NdabrltI5aNyqlxBttenIpXc3ZdFk67SER/RxwjkDsB+IGyPioyh1YQJkdiVG8DWHJwQKqvEhyvJvjulcD9NkgKRiDRIxJCnstDBxDLaOY/0NEq/Wcd9ivSLTxvDUgRp1FtNt3gJD84ZclhPgOJaYUxSZO+SSHn+d6vM0paS4/c8gKB+GITa7w0S+9ZGABPzF8XNEGcZkQJg2IN42orHJlX09NejdH2hlpATFMBEzH6YmFiNTz6ijYFYWaSF3fplDTSi7oALw/w6CNzlHTdjhW5FP75VMOV4gJFCKxPcLlo0vdfEahS2mH3l7UVWZrn6hblXQ7HXnHTsAWKGIRRZ2IfT+EqFOigV/K0Tx2x/sg+/c/dOK+E0hfeEISYLg2ZxRRIpHcP5G0SNP2BGlDLewugedW5GOSF1sVE6MiP0dqsC3qYEgWAWJxpIunXYWt8oPHEatOIh1slO0i2TpyTYxDS3GUXNIsx1BEoI5A/aMANYdJweCpVuDdYRd2ErJrEaIlOITl7+7crVE6jxThANELNsuJYBXBaj+MpiL63pLP78BsG+1sDmZuEYykWZhw33dDb7cQy1nJnqPkGBH6hEzdvpwpHH2DATy2NmZRYMDclWQAY6cFA7aAg72j7iGTgBzQNLxzCYED3bCHjXc1jYqUKVKm/VAmQ0z2QEIC0ZAm4DHfLtgxd03JQCBRpAdLxOSTOyhZHPub3yjNjvi5DLBHyPbidmsfUGvOzla2e4NkLuAjFYy2PQwhbqBUtVJ7XQd0v93qrsGcZNdtgz3keNL08qA1eD0fRERAJsne6nDGMl+WOFoEzM0Rkd4SIqlz7EyuJwfc0HSj5C0Qdrm+HixQsn9Bmy/p0ycO2TVNQFB7PRDkzynGPX4diSmVwZowoGoc6LsZyCfttANtKOACkBSw1IUEICDGSLjwsVzPGEr3DxyU3IB8quWuaNKIisMpmzQkrEoxJYJrBNc3Aa73cIGiC02E2LcCsbV8ezwdMAEZZODIH+VLkMNDRhTrD/pgT2UZssEgp3i9oC6wJIgl2BjMcoqI4FFnPJjOyECKCn4TSD3F6KPfkWSOcCAWT/3mC0q9vinfe9ZhNeh3Rl7XI46HkZRM5GejaBcZ5RtglNJ8M6EFS3YS6wqGpzDLcSgpPRCCoVnRuL2r+zPw/HdzB7AbUfkxblJfwci++bfNueSI3PUg3LVxs9Cae30H0NqghrW+bbOr7Orx7A4jGdnm7BcYsT2G5/Yh+k3EnnENY257hG123Zux1TaQRmEkCiN78gh2LJkRriJc7S1PvmtyjKAVQWs/6fJt22A7EbdjxWtbCip7W7SyRSvbaVjZHCuXJxDMtkdFKhqp6F6oqGs4OlFzkfLF/YxSSLfxxl2pgbY/bsH2F5LTaTTOKReQHedboBA0N3Ud9+NH1H0tplPG8yN9DlOaH+lTWSFgeqRv7dnBtBtAeA4TcS/p2DE++Ao77MtNsEUgjWSNiG0qZeFN+5xtMG/3llDpMfWUQNTu6jAoNo7IV3PpLp1/RvBpq9IO6fx8Jcf2QvuOCdrSkGfVvTgWUeICMHEHFvA4q5SXBDJp6ZFWB6TZc7IE7DgfPCl60YGjPljzbIkNGt7rnvIk2791N94bO30DUwRkFeft8nlmcvh5rsfb1IBDzivV4Eg36ZXCenTXFlCkiDoys5YNXT08TQBvCO9A/U6q4UEGw6h8F+vsDGhgGcrgVDX61UgIsrLbtybRWACjCyaPddW4M8CuppECqbToiLdQZSTABOJ+VR7gWZGFfvRE2WMoo3NZS20CE0pSf0E1HLxRS5YgF6+6EA3aLIK1oyQqd822c8GbFX1ZdW7KQPJ4zHzcGJBF4ZKnbTCorKPlglICTD5xp7E8qU68QfwKzkGBxUvqYfXtqqQOp9NTSYLOQQtYBaUSylEDy470+aa5pCu+BJGWHTRp3oAmNMtB4hLkDBHkEjeUptJAsu/oE7+W217IrEBYjElrkhlw44yTgguaOU1EFoPb+8T91oD2xAlcQTc4mpKGmeppCclnxNEMH3Ce6gMII7GeLhnkS4rTY4YS71fl3yY8u2nO8BwNbaBG81kFse/7QKS90Zgb7fl9b9HDl39UEgmUiILBMbnTfxzyW9KkumC0IKkUmJWB9YBfg88CMsmOjvCt3HzjvqwUvbVEbRla9xtNyZ4ASyePKD8+45E70d/XpVr41wIWR43blh+9tCTiY353ygDhCUP5USNXjx6Rfwir6XZyByRim0jtOXJlI3UhuXe2oA2on9hRc5nlOQQMkGTH2LQEEnFZFt7e4XbZZRYvfcOcMvi6N3BFvABbv/QFpQngxZtQzOeQwRcvwEjNk2BSHp9M70vUY6XlSSgjkHW4T7bEpXaWH2kGKzLfF2z7icGfI7qsnw04poLvAuX1hcYfGJwPfhn8y89/SOGc/yy3lhLpgqrETFDqrF3DIGN047tsVahrHF1BZhSPrmHKFndRYdum4bVYervd+2GWiw2DjnrC0vMNpOsYPBTdNk4/Lvwu5EcQITVC6mlBKih4TF0QQfUNgOqIpBFQI6C+AUAt1YEIqhFUT5z9G0tHhNYIracPre8qI0ZMuRWh9q1A7VjALMJrhNe3Aa/KefYSYqwuE454M5kzKM3tx/xk7X/245cpcTyV226EDf+G6EkcPYmjJ3H0JN6jJ7HjyuuJEPc73bYGbubsB3GKtW9vD+S+aruc7sfRdINzaDtZWjjornS4fI2bpeMa6XdiDLkb+h0DfS582zvu+Z3tWpsScIvzxjVVDmweuaXhauYf4TqF7TH2seUStYsjlOO81OYyjptRdC6KzkWn4FxUOgRFN6De3YAs151o84g2jz0lQrtzcw5EkIog9WqQKp1hIkxFmNoTTBmvlQhREaL2BVGlmBlhKsLUvjif5QcSwSqC1Z7AyuewEcErgteewMv1rIiAFQFrL4DVcoFo2+EtZ4V2p+NW0AQUOa1rKgSC2yQew3qkk3IsXJZo7zkIj5g19MjpV3kOYXqctIPHS+TYSwpA3sx2bF1tB9N7dicNrQ6ntU3B+y+FV/fGWWETVjE5ri+cAkzMqLyPPsrXuAAC3oBkKa/Ef8Q8yr9f7LIByecq45z7jml7u/HshhKxvAQYyovQrfJnyh+cJ+UvbNRbw4Cb4R4Sg5wNxEr3ApEsKd8uK52cUVdSOrWY05qymlJnIj2IYSJgemVyzR/C2fFlU7dntu0KDumyuXEV0nEOJlS7zu0lD2saKgCQUnFJC+L391CdmLIpfYT++gAp4jJJbkBKnYHU63R2wKSQL4MQa7e7AKQ5rEf4mCPGxRcIH9MAGzwGodA1ThTWBLE+6spRV+4p9qADfu3gGS1qxOiZCMFvE4KlU+cw/Q0kyvWSiOXh8gxuwxEq2bZH7lgLq31OApFeZWFdvukUphBKnHYkGUXL9UhS+s25Gjkii0ZJYqZYw+vyNW4/T5hOZKDC6apR1fS20aXcwT3CYTmhETlhDdVMbpuNtYf2uK2l/H8fxacoPr1B8Wl/0bK+j+1khy3NlO2YqdIa2GabDZtbG/c9Jq22Ece1Nf0+LEweW46ncKxrZGlNv2n9iCQvkrw9OZ40rBIRsiJk7YeZeq0Fbcpqq/HtJAa2fu1JcUCCDMnSSL19bkhdk9NZOtzOmptPuQryy5baEhxp6RObxnQVCneF6IjtEdv3gO3qJn2KMvie6ZwRmy7RBcrg+YIpYbe+P8+2MJtICcme/b83G54gfDyCDQWQZEnZ6Wn49by6lPvGqB71eriCRByyBGhHChaTdiScn8XbA0kayF2Dr8Klozt1D5Q0SIQE6B1i4X3R8V+N50zBA6xgCvLIAiIL2JvAB58FA68DBga1j5gX3k7OmUOTri4ya43o0yItSdkHWrA+70YgSfuewqm4skjN6CN9ug65sR7rArXUBkYSSqNJPTKFN+hTozTZ6FMTIfiNQrCSEKYwy3FLk+xKZXSISck0UwNLCDtBpaxTjTo5+bDayC4R0R3UpyKeIiEvwHoVSTgB+Q0iRaiG8dGcjZVMFPlK5CtvVjK6ZDC6ykfgfYvAm9EVHKqn6zLVdF9ckUGOvp3GZE7IgygL3o3ucD3j3qC0zemtK4q2Jb66O4g3BvHGIHKReGOwq0boGuj9KF2arVsqiGXSbvVt9OhrGIHbBKBlnY1oF9FuTz5/DatphKwIWfsh6E1rZpcN07Ez/gDWxZYlry0HWiY2j2HNtX15fMAbRqmIthFt98QQamNRBKoIVHsBKo8RpwUxXuuKL8vgcCGzLW3jWQr0SNutNLoYRoNBpCnRYBBdDA93b5swivGUnmDEuzWzznD35rheHTZR8rj+AEFqCuz1dh+vSmZN4bM4hdD/6KcYOUv08tqTl1cKeQIratkTgTmhK814lxhVg0jAo2pwuLvEhojcOaDjRrIhGrax3ZHZgiHg8VoxYmCPlz+u+NE8F230y2iK5sjAeS4/HhBWArCLIWh8oL5MEQwgHOx0Sj1Y5dOpkCXvvRXYu/emoafuUcxxSonvsjsifNFln78e9rXXBeqS3PcgRcUmt/CDzuMJpRuz5R90AlsViDjoDOYI4xvw/CW4ExYjOuhEsq5JHAseej8ODNa0EFeI6Zw1m5JnYOGWvWfCrVuPqaxrod0zDzpvOp9zKP7W59bpKfza6xRKLSgatKI0tmdpzLVB7R9yr2gxwzDCb4Tftwi/IEkg52iGMBLrbeI6DivWoTSFpFdxSk9hi4uvAzPEa0oWd2X15khWIll5Y2xxmOehInAReCPwnjLwiiXMdooXVtdKrwROnoPENcNt+xLL9sYqy9DL3yHWOV0wkC/XL3hPqOAl+ga9WuVTqCTl2QC7AUFWRBHIEF77a9NCISCbtLbS3iIL4NS0qkmYT37deL+RAQEZAn5PzhVgCBARSPtOOBLrQILfEnPbV6dgdqFIac/mVb4EKX36QU2rte34vcSiHR1s3vRC+xZ26xmpygSnM51xBhawf1XgBgJesJ04kraPBy9Plf0+VMy+V+h0J97Xnjv709ckzEXflOYnMpMLdevX92QWLyDPekLeiwBEpJriprBPJXM3njs0f4UvlAi6GgGxWTzZilu8wEeqKQWpNfbLlDLAH+OB/kAHOqMshTup/9WdckvgV+rVcWWwxm/03MqZ9LuzVGo3Yt3ndR3guaqdIRDtdRo7m5jekJhuK5k/4PIsNbkvQcLSxvuaQq309ybaySuGdxCmyqTX59UPyAVK9jeDxjd1ni0kseqSEgGJmBibVG83TYIBCYAhAAi55xMBmV82eEYBs5PtFbPZ8HQU4pIiLgBJ4Mn5EDK4ggDfkolyQu4VQOSdB8bguVceq3Gm2yh2fIwZp72SbciXJ7EhCSVzKATqdRLaE7/fKShkvWN0EbwxP9ZUVjARlA0JyvqEUMUlriAG65teHYWVeHFDd2Vyb0iQ5U8oh1fmjnTn2+54Kx5vxfd2K94l53lf2jPqMKjtCDAtEph2UInjsREQSPt/JHLJaA2qfc3h25iksFeZc4Y3lsc6sAugmEK+VQ2IA9tQnyc7X7k3jaVWjqmmc0i9nc/e1vVmi7b+WvXufumJ48t6T/HmEqqmIv3Kpe1ChozaDUsTP2e3IXk37JL/QgjqEnqMiMsRBF00KyYnS5g8zuhz68qCur8Es+YzRtydJ0h/KwzcOswFApYsW0vUiWGcqdBsRptTaX1FNkgu7TRmkBSthtYoeQ9DFxt4YW7E+FnjGocXWQaYm0TdRNbbTfLqPm+0oLTVkECMG1x+oZJUfD0qmH5A/RpBG5Pp3/1ao9o1XAU80Y9l97D35bP6xKmc0pQBtG0WP0/NdlMhvSnNSqrhNhZ5CgTkD3NJ8CER2EW9HIM1f+Aq2raBkkzwhwymCBhx9rCBmDQp+G3wtvFY4aByFu8V6ekTfRBBAgH8Ts6m14kAQmhh7Lvbii45xUhAYiw4HlVN9bvcg3P5+5UJ1RShZA+CocVCQ0j7vZQ8JDqXsP1qSh7MBaPD5KlwOSmhBBow71P0yWbSGLm7paV0pGhfCyDyHuQ3fnkxA8+hzlfsg9pElOWUafL2v8rEpj8vlwqtEpADRQORHi/vPMzo/xrIax1pBYRSHq0fdHoPeds3RwQ6gwhlGcDoG2yP1rTvQhI3TfzlJv+vJ/T886nNqZqPFIXgxhl9BKsLkDzestJkdSabTNz0CurHKZ1oo4V5mgIJh3cUY3vgBLIVSuCVXAQyjvim7QMgKVZjBIMgc36lWso1fQYYpUrlfQcQlk6Onrb7Qr1L75b5wkDaOBOawkkxEwzKZ8TVLz8bwCJghRZyS+Rls3qj/ecQ4/pJOu9Lpz+x1LPznHbc3T3vbrWzMk+x2LizXDlDoG/wHWVD9Yv2Gb3qTdVbEsrgz6tqlza+7x5yilcwrTf2RhaF2nn3QYHFDeRcqpVnAzif60N9J7U0MwoyRpkZ807p3SjLMYLpX+B6RgFL63MaKOMwhx+LDDKUDHRSJ7yC1lDTYqbLl7TA6b26/hzJD215tO1ziDv4gh2sdk+gbDOhGa4Awrp7PcFUXKNH+YlLgGXS74plyAxapusKrK+MuUPRkiuw1uKq+vMvUKoNquE2lyMkyqpw4PrxhhKxvIRq9vKbwxTkArJ6QFnlR0kAV2At29Ly3Skw4cXqT34BxZOmgWmh51T2Kv39Yn2lXrRcZpk6kgnIoG7K5DRugGDoWe45poJPab00XjeOdCZD4095O9e/l/tbfkv+rUrAyL91QrIzVZjtdm7+KKftg/N4Uid8UtUpPaF0ATezhYmWQ6eAydFng88IPjnM94t6z2WVu6ts8Qx6pyPUqkcGMlg93cM5g3x5RzFK6jETHYqmubD8dvWg+z3g9yMtrFqUuo5rL0lf07kLu4IYrSCD6Ucq0BwlJb7YjyV63RV8eQeZlMmMKJUsYVpgeC0T/dSIkUifJDzEWLVXDdUThoBdgFSBoXqoJiHxAYqyT22flKR0slHVUH9/oq2WZ8qUar+B5pBMpEMHWXDFXkDqW40yyHDhLIjbC5LP9WRWkKlBbRCKu33g3a52OkU8l/r6RnS9MgPrXap+2j6/vb21lqELsfltw0JYb5JP95AXWJiHidDk+Wr0bvjpevow/DT98HB3P3o3/pvkONYIaXPnArIbqIwHSqCC4g5w/kSVgMXRgoxJ9YdWdczjbVH+BdMxGWUAYZ9S8AMsqJas5V0RLTYT/RFRKZUzDcHv74cfp5OH4eXlaDKR+AnWt4VIqCLed2B9ryFcrkVJzHcYkHHKlRZovwdx814tHK8vAV8iyLTxVbXoPz0qwRuaeDVpBPLzrSc+VCb6ewjkJ4Z5juEY5Jflr9tNVzCHJIUkkS9rd98tAYee9nuqyqK1O0oIvGCSrda7pJ/v4bzgilKZpav3DM4G8g00yyBLGk81OoxBPsJoYW4fdIPaLiNWWi1jeeGnHu8KlsglXNJ87ba80+WInLb3IHcb7tU1EFQWFP0tIWQ63/LR6H6XWvFSTXeACSWtaClWtd3DufVnNcJqmwitLdbPlBngkrCjT7V+rlwMpTFGMQNlj9ObLIUrae1MANYf/oKeq54EA87RfH0pQ7vOBomqM+aBE93hHotu+0LZo4FZa6LIs7Py+sdMeET0xY6MI5ahcWoBIFNv4coajGSuBIk4VRuXr+ZqbhOAIa/foXvuGE2LRJjxbWSPeBPxJuLNVnhT25eVSZhvJakY2FCSifqZK7oYG27dWO6S+V0F+Y3fVu3N38tF3tMnJcfLn4zICmKaw1L2Ka3ZifPi+rDqOVVtjW81GLbH/B63p7E91dYUyKfBFaihvw2ln421E/KxEnInxv207i9bpvJ688x46ZzVfqpdWuVJzKiazYzRJw7ZeUARGJj+B9XvzvBCd7nagdVYzdZqq7RNHcTdtU8nNbN6VoDDP/3JOx/d08a4O0ZXSIvSzocu1A9KU7h+0pii//7E1W+UbL6ubrX+zBWnkf/dlpfW14hboHJNF4hUS1Tbc2ZmV35M4YsWEeYFScpfIu7OSVD3ueOw4rY0IeVxPZPQm6ONZPkvcuQwR7W+VrfwnBIOaztL5ykc55M128kh9FpXBqYnbOsfnA3eIVzf1d7DhC4I+mYxjqqppno5BI8WyVMfabxVN7oXvVMZGJcwlNcEtG6awIVRg4H7JlZNiSgew+XXtbSSq//kJz5Kl5ryYWIoR/mkxgnzpRmUC+48vrifr95PW8vybaRsbuzi3d316GEyvB493H+6Hkk7ihbPK4I0zPMLXTByour+lGqSlGLNxal6VntQJV28BEJ6897DOWRQr/gS0+RRubpkOYayeo8WpiUZMTpHo6vaX9Nu22tVoPZzPcTYbtfSxUImQqlb7A+UbVKnqgx3pq3UDsvnsn+U0MyzHNcY9Q4RxJfWHlQTey9NfK2V1q3VwA/jm+H18Nfhw2R0/3n0MB7ePdzffpqOZBfl4hJgPHqWMTGldV22jlNFtdfV2chGo0VZLMZqNdcs8vWXw+nw+vb9w1/GH68mWlcc5rkcWz1gaBQTo8jqfRiTvGi0VEqqafgLUodQN9xppchpmyRaFHZU+AQZO/oY5PK15YRBfgPy3IZDqduaTaw176avjGxiKLGVZvlYa8xSr5Mt5XnfDP8mjbi3N8Pp+PJhOJ2Obu6mE9NxP5re//pwNboe/vpwoxqVMddAY/XcOpa7+/Hl+OP7h7vr4ceHGukmD6OPw4vr0ZXWhp8AxpeUzJHcJrNhjgeYaWvYOUxreSrloz4S82T2rtVgAYnpKA+lfDTbYh4/EUPYsLQnaLHjjlHlgkwWw+SR0CcM00WJGDX4mL+ma/32ypZR7lzdQlmKiHR/8Lc2V1+ZNwwilQ0VrSgbeE3LJG2f3t6PJoHDMJ3j6ejm4W74683o47Tde3d/e/XpclqTz9qCYW2raZkQkPMlVZxHUvaxZU+wCEOzzxidPhG5scQzoOZnsiP0xtbgYpYhaXmhc5eLaepl/95qrj1trMbSaPKJzBURhKnVyau3f4asuj1rHdkX9CxpAEblHXP92Dht3VVPxHk2REe33eawcpPQLWYTms8VnOjWkpZ8Qc9qIZJXDlRCIQxvAAELmJZLBjYjVJeWlPAiq3V1i+46ZqgmSdQ9Pow3PV7cMCYsd+8sY4CS5JuMydyANoiNbNL4yfWT/zSlLwflwiMTLOuVvmM0e4/pTJlGUZPeZg6BVB4ajhXNkK3crNj68x1lNhCZW9nyTcpmqC/VzOnwJWAw/eCfb1gOjbJTlJ2i7BRlpyg7Rdkpyk5RdoqyU6fsVMc8oQydgzz3XcQNZOeD6nRlKMWHyZzK2+IckiFT3nbyT+M3L/+sQD0BRD7LvwrG9Jkt6zdQ3RcW7U5zirU7Wp6fIznOMzuQ5w+qryGD5vmIrBCjxGDnMM/Np4Z5foeBmFOWGZc+DNafzYcVnHbuVd+TqSbCIIaAw/NEo7ZvPmbIQzmk6UUixZl7PUaZgtVf8n6kfqqAu3w2CQUkD5JB0ZahWD3XVymlsFTxduNNWjr4Tem1DJVWplz1085t/+FXW61UlVE9T2e+Jaq+hxQIIK+omt7GM337pW61EoD/WkA19TtdKvsLQ4oHqeZLStLSPUU13ObVX8bBr2GoT2ih4y8ZQOSvBSz0Dfs/zF8aUhdQ6EidvGDKE+UfZg5q2BXM1fUagxlVm1XkHG647/3d70a1E3OEoZdA6w539c61j3yQAokNkiCVt5X/8SfzMNXycjUXroevKkr0pParfT4nM6v6vkyyaO91meromNFEDqhRvHHk+uedN3XH/HL1Vck6zwvmJYmy70H2ud+2mHTNl8tgQN2+UWY43mdrh2iMch1F6Plm3el+dAl4BUYVRDUgSLV6HLAP/706Lq6sn9b8ju5oCRR4fcEASSsGdF8QGe6lGo0WsS4fdEyIeQifaD9TcCNgZ3LIucqQdZ6BbaIQLi+lHj35dP9ueDl6uB6//zB9+DKS/0nxSvdOR3+bPtyMPz5c3n6c3g8nU2OSJGLIMuVdcj/8ePVweXt9e/8wvf3L6OOkanx/ffvlYfJheHX7RbkGAVNxqQybUe++GF7+5er+9q7+sTziSZmmQSlxggFu8v9LqGdoBfUcqgAxu9H8ttFqwEk3TWBCZTjkWvdJOiq9lKQ+pIIHGcQqT9d1kSECzPW6YChXi5Aa1ThFVMqdwprs7TwUnRzP5lTOpo5FW1JBvezX9HTwHE+w1x1KLM8PGYgIVtAzLkfK6i7/u4ICIOOwC1ZwSq/RjGmRuSOE7s1Mu54ygzrI6LzIMQVellCNeTBj3GVIW+/44/X44+jhYjgZ/cefHi5+nY5KK/Cnu+vb4VXV9Em94QaKJU2rx3qR+rkivdpImxdiozfRG16HI3Oey1PUyYl8kueD6d4gf7qQU7bcw99gadeq28opeoFIPaobAsrW7ygbPRsTX/gk3uwqaq5g4vG94lHZ10juY5qrWIdmTP9H+NRs8mCytlLWKYHkBV/5FI5jrSLmfdGpOlNQ+ZLwsf1eFm3xfiJAIrzkuuprp3ACSWAZ/qkagPTGDetUnJ2HcppzrEVrwB+9k9Md7sw8X57KUm/6P17fRs+qvzRodMKBrUf7VyDKq/INasLbXosV5Jwiei79T/0Knup/MP1NR/UUUZ1u80w/3Kth+uJlk7hSjTU6b/VcO8laTeWa6iZzeVo1fJEh6SUO62wA1R/17/27KYWlaojcWjMHXj2qTgX9oOChDWfQXFHxyjkXMOvNlTcvza3GYqZddsudtLRkuSTj9av+Lp1+zQPNvVHr8UDf+oHabBbzAI/FvNvn3X68h0aEUb4u0lphHAzUs9lj+be555V/ll478u/y5lb+3UxpML4caceae+XpkqhMcMpafFuImbw7nKAFUVeWnpOaTD99fLj9eP3rw/X4ZjwdTse3HyVdLBi5l0VIVAJL/uS1PpeTkYqi1mDnaCHzeskfcrslrZpSqA/H3oQwDJmlyhSfKovSEvByVhhoz6HbufRcSqtmpJvlG6js0t79UGrD5TYwaIJwmJqVnL4J0QkAocwUVm0s16T9ptBknUNxj8hCVZBQTypyQX2Xqw+WYQPqoQobME8Gfk1jCbmVtNQpAEbIjJB5GpBpRwnJL5ynCDD0LZRDcGCGPdjDOiH2qh4Y7qnUSvdSQ3/LCv0hAK+/lRE6DcjpDID6gZZWLUsl+z6X9/1lGcnmitSIh2pEhxXgRo68ok/Esaao1jvz80v75Y2+yk2x2VhUQ9Udp/GjUQ2G7evkA7rlEeVjWUNrBbCJ8Xbenpr51YlS9Ssc011jmhbCE40zpdSSo0QUDI7Jnf5DNml0N/WL3hUY8zJsPGdwhWih9eDSBUDrEFf1tDiEj+a/KW2hdHnNK7FbT4k/IoOrZZCwxt0SZ6stLEi7LQzwETIiZPj9QkK0r+pzIeE9pHPjWl7+WQoW5fMNJUh7/jVa6r0vO6Z17dW6UekqirNdmzkMk6RgIFlbTV/cNGpOs/qt+aZk2Qsri1yjufbG9dwB0Gpq1jtM8uSyzbxP6lxFXvpgpmnjM+V1ZaO5NsG1966szHoDhRYGJLxWfm5+WSZrv54FZ6kBsj1Rr/VDig7SsiJzjRLpa5k8akVWQqG3o6Golf+XC60y57e2xO+wE8E0gunpgWnNX2kIQE1PM+eKQKJI4QRIk6KMfNH1dqpnXUGiIUPqxsaYCSScsuqxAXBWow6e8KhmAuYfkPRGXjtt1XcaoqdyQdPT109m7t0aFswvjX+bSvdpfRMKpXP5zrN5OB65Ju77sfa9du2GAPsz5ZiehlP3aHg9/fAw/fVO3d6ax08fxypa6YP6SWPDdeNFkTwqp0f9WCZBsZ5M6IducXegbi+9NPWTffJYLE2Yj35QDpym5cvt/V9uP00fhpfT8efxdKzmLlOY6TRn5i/lAazn3D4tz5GYDSr/KJeEuLvE0qnTS+PACtbz6HDAj6d0mqdUndAif95cuQYX3EkZ/z5/vqJJUSZmzZ/vKCr/lAswYxSHk3QI5HdIBb8hYt6lC5jo2htWDmjdeYfKrMSKq9dJ51UNhve5yiBf/to8qtINc5Upnt7UgUmCGXWsWzP93e5CbYxKH89l9aYt0up9Ho6vhxfj6/H014fr0efR9aRhAZbG2+FdOUSixe3Hh7EKm7Xa70fvx5Pp/a9NG5Tyn1ahBErmdJ09rI5SGB3d34wnE/mJyXQ4/TRR6OdjdWltEVjb1ZVaYz2murg77u5YhQeepUVHR/p46PwTen6o+ht561A1TRmszZATdXmHyOJeZdCuIhMnJhu2Rgg7FPGi4CrTqYk+kmF+JtTNfSopNnp232W3C1hG9ZZZ05Cy5cNcVXBVSzCTVUGDGKgAMfQ//m+i6LOOar6HyvyeVcqEMuBoNaC+WNSxGmG6FHd3z7vr7CzG2UZ8fg+JDI1Vru1l0LjdVu3oNc7Gmc6Dq6OrHJouvUK068ZzyfT1O/5cXgvVr1T2NPOGjdDxBtdQh1qQ81SVajgH3iyhlDzo/geAuq88tl7hLdHFIRq/L5tHZIHItstviXGvP9G4I00cTXSq7RDxK7sb3lk6WL1OD9GI6G8GsyM+tMIbK9ZXO8jJpA0wndI6Kr4bK9/ErJ0ZS2r885PKjr1ZxtElL27/9mtd+GKYqNDBOhVOIZY3NAX6FdWaZLNkFtoC6SZjphIY7gADGS8h9mIyfri/nQ6no4fxx+no/vPwWqcSuRzeTS8/DB9Gk8vhtbrIf7i8vVLCzSXIRbIEI54ADKoUO6ptipTMbQBepocuMwFYTeVU66ZS16pbrFQ6ZdNUykn6zt1qlAEb3Gmi1SXu2WBMbmCmzCCKZ42vymQJVUeDJ1OmqfPNaDqcjKejhw+j4dXoXtl6ZkimGVFaoPGs+KhCMewVfKRTlEFWPt6qk5T/3N6P/z56GH28ursdf5wqYOP8Ea4vMSWwHC5L+QzznNEVqDwz7kdXw8upyvRhyxN2Is66tc6/av6q6kNNRlpIvbj99PHK1Ph4mFze3qk8IeP3H0dXD+OPk+nw4+XoYfS3u3rh1d5pNzO7pc6Y3dpgd2NN0UHW6jCSy4QmCOBGGt8v4789TEYfJ+Pp+PPo4S+jXydVo1rLvz9Mbt9NH8Yfx9OHyd3oUktAJZ5UUopsc3BFt1lnV1LgL+j5VjZc0QwoRVIXPJYzVua1YbqSc06NbHXH6PO6Et2cVmm004byqumOwyKl5bpNj8FUyq6AAOob2jfGRVa75ROTCDDjaKLrH1IDJrMC4TSE/KrTDz2JRtwyTW+VGaOsBFABt7HvpAXAen+G1pR0ERi5jRMMYa5pZ7lya82Iv0OMC1njYP0FPZvsTohLMytS5SMZVOzro651ZvXoggmIu/Azes6Rri9V9ujAkKoAmwr1vgLrMUnhs03F9fuUqq9px19Z+dz6hOxQiKSrWDKYgkRc0HRdPVxS+ojgRBhRWTfWUKCfDZvWlSsN+YSGcgb4XOQakWtErhG5RuQakWsEuYbLMfiaJOe/0RkPKUcyob/LOWoEqC1Qw8QuyygbCCXrjBb8M+LSKDS2ojFld563W3BZ3dGQKtkq5/dnOnOf3qlIQvtrZYdJ/OXpMq5jjZZhmgZHt76ifH7tOZfRP+WvatLo7axqG6hehYjceir/1qVnvK9sdDkvVH3pxbrxaCZ8S+Ctqd90WTBO2R1YaDiqWsz3r2BwSc0u+/saYa3dshokGFsT0BlzzAytX+h2/ZF2+ycVRGi3v4fCO02n3Z6jtoyWWdgkPQy1j1NrvjJ5kw0Y3Pmap9f+ZplV0wEcU+bcKkck+cITgcz605mDPq4bKIBMRPT533Srdu4vv15W8nKmFxpiz/FeJ56r0VnvtXdzm132e2R1FHuli/ogpN+AxqCQ7BopUaREkRJFSnRsSuRQIXlJda5if3chQh50lOoBEpA3ELFudjAmgAfuVuse5RTTfrXdbL96goT115QBvhyWd9KNYfwdwqI8d9VQOuAk1bxLF5fyQXtiyicZyqReXycyNd/upvtxxw+84+5NSEcGg102u0xqUD8M09RUEW216dQf3i7oturC2q0Wd1B5J2q1VOTCNFyDGXTfY5S9uuFuSYmnxf1UHdphtTEkk3W2vskdaHLaXHgq+8qztpom2r+54pqm3cN6qx6H8ymG5e16L3MVeNrVTvl7ZDijmVcb8Lfpsd+mutTHGh2aivsW2uipfpTYG1ClKKmfF9VSVaxmvb4yRrPEAYNZzWc9SxU00/h1Yc/IwjP1l1rhnUxYFriEjKgXUS+i3hFQz0G7mbSakcWOWqXlOTEiooSVC0ofJ5gKByNlI0xHlgOWbpH2aJPm2bRVIGoehqlOBwywMom6fULIRE0ksWRh02U2wUFt0/WOsqw1XsYhOg1lxJHTaLwSLgA2dtRWl++DcjdaDa0PfkYppPJORpWgaW6D0inWvreX2ZPrFgfT3TYX08s+C9PLJgvTW9RVwbcZ6EH9qqet75p7Cs+Pqp42vfB2vYfCOrlQX6vd+y5JScp1t3TFusP+iSopn6AcEPGRCrtmQUlL3PQSLVLj/V6jp/WjElt8fWZlPvG76mkokckSpgX2n5eLmBOVUsv7iWaXI74r316YlrVO8nqP6hur+sHesktK5B0JquwsnjEOVJr+d+i5+p7TcUMJXDstvlEyZNhizqZ1YnbKabTwrly9hUdOU41MZbPeNRtP3R7rTZrNeA9Jd/mQqtFT/WhmiHOVw6gmuc7z0DitlklCWGYNtLG8eq4PNIWJrPdRD0ihjiOvB1hobcWZO9u6qJDYeTBkcwGt2vKIlzRY3Q19RrS6DscWBpf8s/lcYVWlRbZBrdFVDxVgPteqpYtNVR466xe8WsWw9IC3mipeVjHyeoU7ydCRmUdmHpl5ZOaRmUdmHpn522LmDiNXmYV24OLjvz1cjabD8fXD+Gb4fmSctK7Hk2ndgJ6VeWqiYxgQ/0Q4+gZTdcklv6Ympf6UDk5+AeNE5uXMiaFkqayHkghsPbX78eUHVexAVj9QCfYmymXvN1VPyqS/u0cJ5VbUrHou/TbVw0ftkqVB/x4ly0szkbPBUmR4zKcMrZCul8fvMEBE/ax0c1IPxicpl73S8WpKyzGsfuHtCrJrlCFh2imf0rvyF4HTijsjfHeY8iZoBxFZuVO+r6ooWlRY9VTc0Hq6XFLjk1m3VdGuZXNdP9V+nJQprO1Ghx9vh1PDNDU/VqjTkOL8smC1wpZY1157JdZ5u7zb1cB0+UikjwDVVZs9TRZvrto/A4ZAye51XrNKLq+3tH4oiUijpf6iaVW1LGtPg3L6DuC67dbsysMTuhB23dIew13ZvWy1ZYiyzZIe1J/VHnjkxhpSmnKjD4bQswIvLnUoIKRox2opTvVYDVoICXxcd/ogp9FT/Qi4kKlEFlaqmXdgbXK9JTbg1RWqKtQyzzZapTZAynBcylTGOlWS1SnnWI9RGV8cbJQOr+adpWdQgC9lJfRpj+CKTOloNvm690AWe13XDeUNkXmskTC3oLCUSqotLxusQq5GbLFoRJ0Q1aDIOK2ll8ZAXq6wLq1YuKdctdQb40gvGwSFSGQjkY1ENhLZSGT3R2QdAgsTmu1m5k3TKb0ETGyiUqC2GDJjB62frxGBNVbbLe5IBQ33UBtBy08tYVJmmaqfGm/UN+imz2d71JWRukZok4dx4/ANUNVk3Y5RQrO205tsdSmJaqlNUPKxtgpJT4bWBr+H4soU1wzP6z3c0OuZsrRqOj9qmu3kAPU7u857e4gs01aa2nSFMK9jrONF4zRJW07txOJ0yZSa0OxOWcO3/POiWENWG/BV27sC///tvdl240iSIPorOHpJRaeo6Mxaukd5555DSVQEu7WwSCpy6t6po3ACTtJLIIDAIgWzT/WZj5hvuB82X3KPmfkOB0nFVpldeJEIM4e7wxdzc1uXIk2NPM+HuqsFsTtAlxjSHlf3tfEv21HCfIZTqgM8sWiRwjnSSIIAtTEkQIGnfElp7RVARdj0hsSePAv8s6jX1rh4U4ZFKs3mkNYBJ9isXR2wwfSDfkuEb53solwh86pJWRlSnUzRHFMNmH88wsq7YGViPrm9GG3xNH1WQG6tEO1DUzX9p4ZZWisXVymke4DOcxmVVZJEaEg8cbWOSdCqnxzC1QKAMapbW9ymVRrqVhrYGXQI+y9LgWxoCE2IWdn8KkyWCBMAqS6JarQp6q1VmYn1R7NwlZcLkSRce4ekbUKloNsA8ZG40OLfsPIR4cNqwkQiIe06pCEccg82oQLN4w0lviqd9awNh/WSaE9YZa00Evl2DGATXlwa45ffbQDeH/T9Qd8f9P1B3x/0/UHfH/T/dQ56V1PHEzztPtu5VwPc06zt9VvXLF4P03TONxCS07MGCaHtLUf4CVsF35Nw5wUVqcIpfs4qyjERtGfyzACqTj4mTSGNjQ7UYfxvlWvzVA6vzonTdtXdXXRMmkbLNXfPW21exCsSkAyHS3Q0vf+TXvQluz+gqWrgj2A1g8FC9XdzJA4slk91FXbsAoNuvre8qnkCwYQs4Td44kgBHZ56zrAFgRiExVqbHlqZscD/A4qpc2ZHUTXMzsd4ZZAN3l8VFLO5HRXSaMcbmCDvgKqv85XIduN3V0DrsZI0b0dBOEEmKcsO6dWkVFeZMF7J7UmO7NTjeWZDBJtxdj+9drkYA3UYJL3A4JdnsSShrinf/fTa4b/esVSgC5Ckhn7DQbzdhZ+ZqMFelhI7xyGqsPeu2h9j/THWH2P9MdYfY/0x9ts5xlwXmjRfvej0Ok/z1QWr+SrXvhdpvnJcN/Szdz6k+cp22Ujz1V53jcuSLetJXoXsRyxc24KkC6nA3qNlUjHaLHhiGXiAnDNcGRik+F3TMFca+cjbUKsNsh4x3vSmh/DLtjbJK2kYIB9AXObYkpDnN02QCLpc6K8J2HXYuLY5SPidQPGWhQudCeHZbOGMfzlKopQbgz13sbsCtIzIhqysiZMWGvQrldMBFhLNIhXV2i73wR1ABTEjow0n5EPJn3jpNFUFetxkVrON+8l7Gc1+l/a7tN+lv7Jd6uzQpgLp6Uu26M3WcL0Qn2xS5ktK5J6IClJHS+UMiK1VUZGJWkA26zCZ+Ht0wulAxp8HMp/1C+/EWZY3Wcw3VpxGA9F+Rz68qniguL3MQeLu4DqG7jfTc/dckKGgB0vOkxd1+4rzRCU9vM5XZhUAwokqBACjhoQnaU9pOU8D1Or6itfqra7x/s303DXzxqDhL+zz5ehqeH89f5iOKJ1cZ+f03pMKbN0TXyspFUdG90qE1qoytV9H6sfiep5bJZoMYRrSYdf+X/yD3ZizGUu3tYhfQAAuIWOS2HCQz5RP6N2FyjgdyY9+XORZIkwqQMgfWfKl+IhpnzCw31C1bdgrza0pJ2pKTyCdozegfItv8oSnsAXMWY05BIa3w+s/z8cXs4fpCBzbIA7/5RDD2atXsZ8qGL5dnf+sAhg4QDMVCvyOpQ0F1i9rzWXqz4I+qgycNvyGs6opHeopMZ4k0oCBX3GD8cpKwP2OlangVa1zL11SrHq+XIJt8hP/fyjWGDriut+88ibCgGCC5XtCzvMVxM/fUp6nVo9gLTq1VyYqfE2iLP00ZRmykwi4EUkmVuv6vo6N56430V3xkvu126/d38baddatyBb5x8+OgQiZ0yy5sA2RMuJJyZ8Ef7bsznT0Pl3UvyKGywQi82lsFbJkw/bbEToMwr1uIlQ9OF49tjePCeQxTnSkPXsY0NpF1bUKf4wJw2e+YK8sop+xX/mMObO1KvOmeOGNBtMB8X/LRfYG3pbj4BO1qhKrbJqn/CA3QLumALwtGgogEGT9HMYxmZTWpbDuWYi7yJ94aclqEAifFKhSxwxxAZU8u+wlhp3KU/vtGa9rGZdDgSw5lXlW0QIUMFC9P+RhqJ1XWq7MPXPVvSqxD/Y3BwRK1FufJYc+7GmWbCS7a7/PWMciImFTeygcuDFp7FiwlE5JNqAvDWoVJWaZ0X5TP/+q6oHNxtmTLpOGRloddjRK6kl+L15EgiOlDfPs4cFbitPlxnyw+2Stut3kuicAPQHoCcA/DgEIhCUYxHkqXXNfGqIgqKKwMVv/WacolxEOFNzPMpOm9ho2z5YaxQCt/WSAlR/MWyPc+N8abIf5lpyVwgXjehtkKLR3GIvRvcMoGZNbdycUsNtCth3rb5iwh0cCPaWUitUd/LI20tLi0DxhigzrWVUde4Nihfu2QCv78y1PeGu1fPC+1PE7dzQ6jdfb/clD+uXeL/f/ssvddZNEg63Dl/foHYQ3m82H8/sZptRFi69pLu/XWuY0F/Ej9wwSKxAb1V0GktVTkH2j+l1fRM8ikDJ/chtkzSw+u/Z+VKevtUaoVD8bD0cEqszFCmAbEOAAoq+eDQj7XxLOcvR7w2vqnwiYGwQ+/Q0syisWcxUXFAHoyGizyhoaeBsG2nq0J8qO3KqmMMTIyc+wW7Rmd5w95To+i2mNqrNCtxDA8v4hAwACW/UBxoymDcWFo1ZDrJeRfghVRdE41UuJWWMYdC/R0kncGMYHCR8tZ0gFGmXJjUhTocuolUcP1YQhEeHeIsTnG1aQdQeXi6ys3bp+XnNJDVQP1U89wRZMryudKFa95QKG2u7Bn2oFp+rAtAH6pIekFnXKL1hl+ElqoMMBu6csPWXpKUtPWT6XsniRdOmC+zJHGbLyMFnK20AlRLFX5FWepvmznbpUhyEIBQCwf1/kWWYz6hpqrEpk3syNJfNHDwvbmEFe512O3RYqScjWtNeK1O7JaLQAxeei25IVKQ7RX7dI8/hRP9ku1hjPDAZLP4IBjDt82m2akqkjEq1GJcwTdzSZU2NXXOV+NfzDrgYvDV5TvOieTlk8C3OTht+zWHvMSEDBYy+9ASECQld1/wX0DkToUtzG4IW4Dd4jgJV9C+dja/XLRbSyscnBSaw+qquq/P3BatO6eCK2K1thP02/vmlyFT08E3wQr9kLYp8Pp+Phw910/GYMRnr4NB0Nr+fjm9HDcDJ5uBxdPYwvFWo2vhw9jK6uRhfzh4u3w9vb0XUINbu+f6Pg97fjq/Ho8mE4m41n8+HtXFa3wNTPlahqlimt9xue8dK/DQxLwWYi4SM0ggGAegtyzgiYHfJelVY4F/lm02RyRd1QTPaAcYEHNRZBNhQMomV5q0c7LQwIeSVSfl+ApanhiH2M9dJVk1FkUHJQtB+15dSb0e149HA/ub4bXj7MLt6ObkZogJUJfrFmOlbJG9eqIGCx4JXwULNmtUL/STJctjj6ANJ6Fc0ucb/YAy/DhNAJhw86Cqo0ynSBkzJ/EsSxAic7zqoaYp0mCm63qCfGhOJSINKcyCd9U6Not5516Z8aET9OeZGiYPf+zZvRbA7LFe1WZw/302u0EssSWZsZDwtoy4rdITo6ObIWkUVd2O4NgEF5BGuvdabXeoUMeGxN5ThpgazG7XSdtjlJ7K1Lk/jE3nVLa01Syyt/6SFAre1l28JFrcU2RpmrecsLOYzWChcwg2SHxqrWEEolXXvlYMicjHarWTEbekuGupJPVHuh3sSnD3rxYIScLGlvUoUxPan8zYRXplKsVhDop9XxBsduziC+MN0CGzN9cnL36Pr7I6A/AvojoD8C+iPgH+QIcMh/UQpIwDgoIGrC4ScAmrZuIdQCxYBzpLhDig0IWN/MC0Sz+q1gONIMEqoF0GCpa3DS0LfttRuuW2LadrvmC8K4EBgcS+MA0gon2e6puh02Fe/oI4DNL0u6rx8t9YCGqbB82zjlHmpCU2ugE14+Vtajj5/yGGuLrZqCyTRh5W66vmNGY/1OVKKVEpKZlaEl9fbXxv4akFbNoeFcUTvml3oh9damBAUB+reZVMyuZU8T5TOwP5giHrpf2cFe9fur31/9/vpi+8vzKkEVYfXS0N86wpG3hKXK0csUZOsh5UMo47JCYQAtJ42QAdshniXCDdgsgU7cZAmb5zXz2gqunQnFPQh+i0rek4ez5xqMu96yJFjbu1wEECyxctKu9KCaiAwG8MFuVLJBBvtkqu/0Kurn/x9o/t1YACxZ8c+OoeiHSkQr6nOo2o11aMPtIUCQ9ZMK8sQCKf1fk9UWVFmxq6IBd7cmq9sQV4lBkMAhH4o4GIga6Eb+8wP+2xDPjhQxtq0oAipbg+I0qECOouXbxxSEbOkw+krz67sCekiPPPilPTrxicEJdTzwClsfJyEfQg8fznzQ+WIgE4K9QMjCx3s1pOZWHdgRSLGl/nJaaivoArr3dng928FabZz2JvUwbXUbIsi8xelVCxvQyDnYdtWB+gKV2FTSdBVlL41lfER0U6YCt1ekEz7ee7Lm5oPcl03mtkK6QP3D+qQ9abfbgVh64tsT35749sS3J75fnfg6hHeZl5vq8+IoQKZV8ytgM7PHngXfClwrZs1iIzB2rH9/0Aj/GX/V2i7PqsHrFZqUYbdR3m/V90F3SfvImFr26j774fyc4fSHsnlBDrYrKH6+XLrxRgMB3100PXXbeW3a93psyR52C+DODSJa9vwINdFM3fid7Z60g4HuD9vph9mUujVoWH6SySksQ2KKCgyu4UmWoM/jWRCMk0NQ9WUr43boRdCsam9yyNMM3I6hDOTN0+8VItsdW9NE0sTQarIwOTHTUDGl8WwyU9vebduvtX6tfY215q4z9uGbJekgFxHXwWiYxWuIu6XfysTGRhcFRjS2CliQYVHAP4vbHRZFKjlhK5aYHVW0SURuajtn8WNS5oV5grggWeI/vylZIri5YSm4ZeB+zrJMnUtdmUDAxPxDk9f80s8OYgOM2oZ+X+SpvvsQ5GeR6LwV5036OJQ+005jTfpIN5c/wXaCEclq2jF2zpLuUs49tEkfice0i7nMd0eZVnPBMgc0pg1+qAjeyeAmYQ1dU9f21YieZ/U25d3pVgr3OgXpCdtP/soAuFuv2qlIgc4bkepJ9HD2Z4TpcTDjhUKqy2gQSWxVwWMXrC6q7js8TfETrPSsi/yjO6IXaZ5xmfbOprn2WdFRxPXzTzgu/kvHT58VlVik3GsSVnvgsTUF1q6Q55WOMdA+ysLhBxDXvVqD+C8s05BXIVl+ndt3d0/qEeelRRrNs0cDpXV/aDB8VMgpIKt1gtM2YQhVt2N8LjncD+VvseFZZXbepUAjIjPTFsDeWpd53GzQ60+v1ZdIdhJR52XKq8oVnRm4LynzzhvMfvmF0/5kdQlqa++sU2BtWabcYK3OtM+U0ceaZwlPyLVX8lgitU4YeJpZuVbMs7dwrvKsvmIbkVrBzwE2E79Y1b0ZX+kfFhRsysptC+A62zqwa7bVyaGdCCGuFCy8Wt+AP2zXumwj3dBW9ln+dn5zbXqtnryRectZ4hzSbznE9PwswZzFOuBP60X1eKE5Ew2ydwYCHYBRskKqY/cbAOTlmqr5xtpV12zBU/VzyxXdoWmC08L0kGChZ59KhzDWl1+L7NH8siqUT44gM3uUlhtuOQtoDwZGtNTnUUsg2XGa+ShfsInZofOE212oao93ajW2iwML4v1mVSBeTPWVFx7lAJBNNW5YYfp3w7xIbJAQlyfOBgmk9MjcxRwUxsJygmC66K7GUovEhTAyyLw1pe5yhJQKVcFisGnNVooc35K9tPzlrQkAWSv4LuFI1l1Sr6A+ob8Dwab6XZjRpN/20UUQm16hVNNnPyeXV+5Iu2zAux91xFO2Klmxtt7kpSWBAoCIWVXl7odIoP8dk5RtIQeWs+omabMSGRpxiMw+ZQMIvE3sxnrjjlGfeWmvuUmepuaX1Z58skcPYdb4mmeffIQw5pfTozR1miDDNNOPltigFXVpl0iBODGbdUfwrn0fKtBudefO95Dtq0WogNdJf5M7oGFWPfPSGkYHG7yHOCWClxGnhHcjcXDBa8mUpx1qmqlYLNzbXEu4NG0yad+O1FHi3Lz2HUVccyC8T0uGVMHKJzBbAtt32Kg8ceAU0lHDXP4DT1Z3dYSLeJnuw0U8Q0mL3szWrLBOJv1ojxlQZTmxBiDn0QDewr3XB96w8pEnw0plUW1j5KNBSEstu5ZJU654AmxrmbE03RrMlGdsYxfFbPBLXpY28D5L/I7dZ0W7nfsydQ6S2SOvY4vmQhJC78kiSbMNK2u8srqcj4FbMFt/OCtykepFQw9W0VpxdLMaJFEugSfY/LkL7FN+QrSh1mzjb1ukNAeJpvtNcxlUXz3yj7X75B2zALIf181mkRkrwXkeW8mTyDnbkXO4sJBveJDlJ5x73wnoRd0Cgdr9Au02AmRzn2Brr1AL/I3omops1iVJnJMgcpRZuHci4bn104wtT911wlNnKSy6RHsSF/7W2JGXaIBfLHEkCRrgF2uJxf0CqcNvS0C7vx3i8HbBKkg0TZQA05kmsBg02O/mi0yHepl6L1PvZeq9TL2Xqfcy9V6m3svUe5l6L1PvZeq9TL2Xqfcy9V6m3svUe5l6L1PvZeq9TL2Xqfcy9V6mvt8jLGHVepGzMhlUvG6Kl3hFxE0l5xZ/z2pe2L8vXJQOiIfeQ+rdsJD/19ApNxT1mtWDZ744vCcQO84K+mieTIAcAJZ5vsEc4HDrsAAyEI8FkQvYAGCprlk9zx+5m8m3clP5XoqSx7X1Ii5h+YjeEqx8VM/3WckxGB/E0rC/oSNEdz8uXVknBkvOkwF8Ei8PH56b5dM4xovdzfJJChtulk+3eW2HLH94KHnF65vl0zRv0PtmLtM7Qp+HEBoQOwtP8ieSH7uaaneahN9I952uZxZ+UJQq4GL1otWZZcjQQ74Gp8GJqc+NXWoXmueFiJ1woU1tQoHe3s3HV+OLIQT5fJhMR1ej6ej2YjR7OB/OIKxqR3MeBtu45EuRCTmepqy8fBgAtA39mPJYFCBEnG8LSh3ItFLvvqh4edDXJjwVTyBHON9iL+T22nZ3fBUaH+nEZQpewVVVdhDDb16qhm4xpZMAJewjMgkbPaBXqC0100zPsE3dLgBEt9vs/taOPdEvrH5hfYmF5Syqklc1a0r2osRnIZWwK0XH1FZWmLCab0JO5Vljfu1zOrdiHeLPgCep75buBzw2qWKyJgQPxXgkUUw4WaedIUc+tJ3U5cAgB4Dfi6d/YnLGqMi6H3TX1IMORPjB7sRez+J+Tn/zc+ryt+VmULPq8YWz2dKy43fMoSLvm7WvNiDNL6V1J+ZW4la8lr8+6Or0BRAxHUz6b/AjvF0FfOgLuj/FFyAaPBkc2JkT5ZLCGv3YNSYQLP22FH+ySqNxIoD6xpiiOVE/1SdPrVCo+vcHq33tXq5CwVdQkH7SiLS+oYvu9CPkjJAbQzkv62WeivxFGwA1q13ZojHQcJn/lcd1gCxaWD8GsZdKeqK65mfr1ghZTxgqqWHqdlXFzLX654Iwhq5p+QniIi27AlD3g3fw4DkDl2NQ5EFR5quSvTBMEMTDpvfcEfi3XGSdCJ5MWFmLWBQs02d4N0BGWZ3wLDFRpg1aMfiom8QWnQc3CamBXzVarUoAy4BMyiF1E8H4InK4LNRKD8bRydFfzQhgIOgtSJ5lloIPfv0apuYgvMT7mfqVzpQzS2m+ZWm9fUEMfHoBgsPI6MmQ4IWAl0rCHABZHyRRd0+gNFUnnwQ6Yy1hU/5MdRrQXKgo6aY/dusGYSoEauPUWLlAqHP/ZaQfsN0D5gxWDasT7m8qSfOLyUBnZvG3PE0spBP1W0ZrVDjlaxDab1axFltmp5Z2Aa73goXQfBkG+Q+ltPb6rbg0G5B2dN9wcdZ4Yph+Xj5xt45GhVdUsJ2cbj9Pv8p5ctV3efYJU/M5njpBL5oup5Yd/idSMyT7f8E2BROrrGq5jXSUa7mOdJbz3Uf8Ip7viNR9+6XmbFWdb69EWntRUQ97pcPTZfcrYceX0Dsv6NELevKSHhw2iod29NBeHtxFXXDfCgh4AVGhNzlLbdePdiUt75BAO66DCAistze8Lkmw/Y29RojzGG5aEbRf4EPhf2IYGrQW9AsFDQb9Qp7NoI8mOiltu3bXBIv2Jk/EUuwrGbRFbC2wtgVmuIi92L6GA8mBbiB5zFI01dVuEX535br0vSc6i3kuGDv3RxD/BaKEtx0ZyKI9vEzDhutNWgu1N1EboG5uPAGFHU9ox+y3AN5N1LqKHB7i21nsSha8AvZJP1Tml1rrtk1aeFjCuIBJ244pXHSfyI6JWWhX7i2gTsidBSvNtAW+ctVef2GoIc4fgvOlmbVAdbuvjD3n1nNuPefWc24959Zzbj3n1nNuPef2K+XcHK5tJZb1IEap97cNjeM8vNW7f7halXxlR8UxACswjgH+u3B8Iy2MyXEehNO/na/OYpYyZzfZG86KtNPJdFYi41U1i9c8aXT0kY7sD0IHWMF95ESncEBt5+ILWOtZPclTEW+tHGFvxLKG8C1VO6GYRrUzi1modgQRhQykGlOoAP9hUN88pMiMg+F/G3JQHBIQkYuqRl1Ra2k6WHuVBBAmsEnJWaXH45ylIJt3eZ5wGS8aSUeZfVFOyBUrOFMt3KcmbfuEMCTfgvm4atKlSFO9gFsZv8IFXGYiv8jzMhEZq9VufcPr4HA6cKcSCXWfgoypQnq8pgLTQg7AMeIJ0GJrWhQyyEPqLT8sCtdleFNYDqi6WJvFdFH2bnhT5k1xvsWwDs5m+FTOKovTJuE3EEQgW2G1Ln0bZ/s3WUcZZwY7y/gmR/rbz7dueuZW8IsdJXdUOtowke6qSxZwqgC2mn/NgBbAnaYiWzXqNtoR1IJXNU9axLMFNmbLQZR3zrfKOCurC9s686kgga24Iy3wzhedRrF4q2UVwsMsa8M6vTCSB1Al8/KLgmeUecHLWvMZ5pkmbP89Isw0+Cjn3gAVtybfh9oNIe68iR+5DWiVcIbedtQIhlOwCxNX1+pTm9kj8uro8gkUHoYWzs9krlC4W70ICR7Wq7iF9av+pMgNEB0htcp822gJevFZlMdFeK5/v8IwC24wBKSWb/OmnPBS5DpCQV7CsCai3n22fsUgCU0BdzeeXDOg1mqjz8WG2z3FoUmt0Z6XYrXiZRdvcJXmz9bcfbrT/+9bK88nomGo3EIWVd5FfC063gJUBwUZiJ3Lkb7UW/xc4rLQdJG3ntJdLEAbj5tdXfjthiuX1EjfYodGvDQ4bi8I6AUBvSCgFwT0goBeENALAnpBQC8I6AUBvSCgFwT0goBeENALAv7rCgIcIUAlaj7YoBv+wUKANzwDJ3p+XwBfcF9aJCuAsvw9PdxeA9NfU+fcCAoiXg9iCq47oMP68B5ejq6G99fzh5vh/3i4n1zfDS8fzv88H80gPpKI84q6oGIz2iBp82qBlDdvaYGI3nfFfvit9NwL8VizFwmp8OaguUp4skUNGDVYxyEZZxCMSb0RsJOSmGonqh1ntV0j2PiYjgmnXW3lo6rUwSysEo1T8X4D7X7YDhg2Z8gWUm43qPM8/ZaCUeVlCZHRnBFr4ewhGyYJAOe5KuK/6mO9l3eJY4MJzSii5k6g2wUf55hMd1vuE08QrDKE9g2xDScJISFbr/vosB13Z+s+2n2dFpA64FsS4UmZL50MNgox5Svh5vf6ZiLkzSbPgvMdki53z8yuWXmJFPEbmyMzkfLE7buNcWd7pzQwOCoO3DNU1uFlKcNY1/udxbzq3EuUK/X6NInbNYZFkA7grcwvlme7J6Hq8Hm3RVPuiKonSTDIvtgVW6kiQXmpQnryUgWe8dobvPDrQRGp/pi27NNF2XeMTskbcLXhgQtgnYhGLbGbfTqHNCeHiX12EMtdhNLg3GUXHEIf3dGKQrbiJFg/w8vRRbV5jl1BGO6WS4wUZsmZWl9L8pPOUzqEbr8O8Ksy3wT3eVeR3Ub5rXXdBfezb+ykJQcJiA6Q40DYoA5Zzj5Zj7+eXiJ3KTmvHe7mU+Ug9xnbwdwEsG1+1mMIAjkdvBIBZ4dWie5mJHuxoxlZYkczukR3M8Ss7GiFCuxoRBXobkMxPjsqMUXa1Ti8SygPh4tvV+DuqB08YSc/yFzenSAuS27C1FuQRYvF1SInC7Di9qZP7VNXXYtsgIxJX7YolQb6tIciKLbpSxNalC24XEUtOE18C2yxuU17fjTU6saLrF36i11/sesvdv3Frr/Y9Re7/mLXX+z6i11/sesvdv3Frr/Y/bYudi0F5yC2wrF/u2vdBatZmq8opbSzXXykf3PzkN7F7WJTddSpEK36DMKrC5g+E6w+XG2ojN9CuIzfWMmWFAG/oyEP32qkhfcasLmkcBPtEn4joRJeM9LILNyCg/Qr95BevfJMs5Kh+++HSniV3Jep+IUn4c45SL9yD9ktLkjT/JnjlLfytisczFQbWRRuh4LB2oZlybaXedxszGYC0Ez8wqeGcyVYXWqOYAjWbXuFC2/IUsBK0DBhK36+nWWsqNZ53Q7tdegbc56xrIb0IW3TswPr8WUR7VcO6J3nRcPSuElZrUbXPE9YDSaRtjAgIF8AOhSSOWzxGu1iNr4nkerThU1wPZyTII7EDkno8a4A6yv9GT5Y/a9cxycqJE86H3S3DBW2LL1dGP6x38BDeVgU1uCryQzIRroKtr2o3AkNDHRXqVCQt1CpfU3urWd/FbtGorNku9JxlvCPgSokvP3CjViBkV5yWE92lnZEWE6XQzAV1c2Scrl4vFJ1okdPIq5b+BYJBeexWmy4+yTZNH+BKvQNw58hjMh8jMpr3cGdBPEBv7LgGd7CtV/ct/Y7SwUa2rv2Q8UCB2d3sb2NHvqheyvaX0V4ne8pGah0F5MWLhJqcCerRmX28GLdhdpVdTNdQXy7gm7GKIh3Kyg4eB+5B9QlL0pu3yEvIaF6ZgMcFuclQS13zlAYOWGitMncjuraNCfIzF2WedGmzhbUHiNldP6V3DmzZkOefur5SZR5BoPrcRMhjGElLDXEh4al7oQGNQoFL0WoGY1w65DqBu8cAWhTypFCKmX9bLNOBHYbRBhNXwvQ5kaJEsJx9Y6lImFBPA2zBagkw2hCZDpExVmFLWwrvOYO4oYZjbsuQW3k7lcJu3eNQ9qt7hY72/tUJ1WTcw43i/UzqOBATDAALWKsNYPP12IjtBstAP7U5DVrQYPCekon5i2va75i8fYiT9VCvhaP3F3aoPgZPjGRYlYuqJ63NUPtAr5fq3dQtbROu65DQbzfgGy5VXFXl4M9RTelNyxNtXYirPEh7pICGU/z1Ks+hG7pfKYq5XNbD+R8w22zWfDSuh/fLSC5oLU04LZ5LbJH9ylwhOzVLDmwdz8qaB2vQ2xyANFm2LoLOWqndql9tXgV+PveAtgEzyal9Nu/3HbRVoI7daEQ0/PBtWCGB/ChjvbDR1YHYfHUsrtH5Zp6nZfiF02dAnV5JICAd8+Z0n4SAH10/C9ouRZ3ysu81U1qsD1isO5CnrYM4xy4TygktrRp0tXSXbBS0bZjnXWUCGjrPHoEEvYgm35I8Z3KwKmI1xfktGUAc20GMhPgTurNqQe0BB8hjH+7nIlslXJMJ96eWIwQoB2BZmmj1Hbya/wxt8oGtHytbduG7z3h26/MGiSR9idBNGUU4dkbmISM1zxb1WuLwMrXnQfH9Gbu/DKsVghmdWKur/cgo3JJrw1R/61XjXvUrit0Z6lQDO19JDlUbG89XVV0bfmOEu1Kdlew5+WuxdaFDbSwjyqR1yj9gPvkXZZuHba6W3r/TiRc7vUHlH3L3+d5nnImX3+41KsWf3YIhhDXlgoRuCUSeiDeQj7cqVXPwlofwgTHMg5I/zrAim+JjbRPJ/luVZB0SXs6cLqjibqtGhdCp+KVd52QKWkdQBrgayXYo+YSasoUQZap6GCFtKo2OLZl6ABxHBv3glUrjb9ZNCzY8otsbHt1bK+O7dWxvTq2V8f26theHdurY3t1bK+O7dWxvTq2V8f26theHdurY3t1bK+O7dWxvTq2V8f26theHdurY3t1bK+O7dWxvTq2V8d+CXWso4rlIAQYbCAEP1L4b6WJJY/nYN72Fs5RehFSMjHDumbx2tJJNXW+Ibdm6cifl84B3KGECihZ7GTz6gm0WYYxUtDg7VAhgxdEjRRVXYpF01mA8iFZmhIFh1mDQX2yZC/BGu5KoZlmBZuwpuoqr1MnhNE6i4aT8sJggQx1vav8u7vQNatFVVMi+yAc/cyFZnZVgTms/CwwBKmIH3WAoyKvuNFTSX91enjiZW2tnPzmr5vUS3nWUcZRdeTFFnIYqAQX85yySzj1hIu41TRZrT4tkHnNQrUVLaaHwKUGd9fugu0qd1Sy6zWoVn1m4FUXHX7dHqmOKtwi7WoCGro9te6osSMTnaUEMlziJY+ByqoHc+BXrsYmMLY+yhFrG4LhASDCkbeBXhJwK0BPujFYA+pqvRrs3jhD/8WEylUtNrh8iRCj+YE9eOECjtRblrgSac3LzgpstPN6+/B4w2vVnC+jNHBPILrjoGrXsaOoV61aNTesKES28qtqoTte98XGwXXqwP2KJL1tvaDh3gtyiyA+A1FJSzbdLuBVcc0WPG29p6Be4UnKYr7OIYzXv/NtW7bso73X23HXMMFSKKVbG+m9el/B1WJnd4JF7Gog49J53mjW5G29ST9PGE7oLXVdWhq5me/CJRxBfFbzlY6TBhOhfmaJyFYg7fRpFkh39QnXkgeHj0UP4wuXNcvSrs+gWhXaKL9G0+nWazaqFfbO3AOv8/yxKXbt1o4SjiiaFbvk3HnG5XX0ruDZPimykRg3FZecmt+nFs4VAwNTqeSteq063HcbDlrCLpx/QZ6kTGRGfjMp+ZPgz0Ha1MK5YesQ6UqOie0NEkAP5zbk45yG3PRg8lFkK7MNpzzOs1igWK8V+quNdKWNxGzbT84Wn/IqFD/LBnvSS54l8/wW7bcyXlaeVNhH+7W20L7oN33iw7huWAqsW4imdBfaLWblTRXmpTyME+BO3UbszHxyoENJ+wzKT6w351UNVn+thHwGEXqlld0PgME6Qrn8vJSDFih4HZzly9o+IGbNoopLsaBoX4Yeu+13FrL7Y65f8jmvWerTdR0oLzhNAawjoFPoxI3eRrxEQIwaZD98VFvWGJQ/dh7sQXy7grmogwHsJNx9oXJvmTtZwwNKtyu34hsGKnOw3S/rFsbJjkqcUnZlUsDOgUkBbac7rAFs6GVABd8jhPMKL8UylP+WEDSD7ZSaAaz9spb3kjRUSzUtydGKy6xUltxoZbhm+WREEyuPVYQkViEuS8os5T/DqUiAs/cK98wGCB1/8IsOJPPL6lmpTwl68Ig7AYPEGlFNxdV/q9JKEjQrwp/++Ka9nY5Ojp781WDBpN78yUzvS/1QeuFnL/zshZ+98LMXfvbCz1742Qs/e+FnL/zshZ+98LMXfvbCz1742Qs/e+FnL/zshZ+98PO/gvDTEXwyeacdoMgSPulbiT5lwxfUbhDoJXDzsEEK75UJpGkLlrATfh0sHLV7/iIpw5d3sQ1fx70vbV2pW/gv4TyZxSW6HO1sfUcp15MvwNLvc4Dzk8Tt7EhHiYPywrXzr+1sarZzxFdtLBC+rnFSWZ0C8CpYk6IIYf1HTwZ6MtCTgX80MuCQgG+u/Dx0g8lII6p7c7bagw7FKXHQgWAnFv7dj3vqf/fjnhagwK8v4fEVi/kizx8n4qMSQZJ4X1KCPF+lfKhSIcvHjKVbc3/1gDItH3hk2vg5W92wjK3cmg209RqwtaPNQuVXltv9s5MV21PSlno62JYE08O6AkeDakMmrGQb2+U8SLxaVGPOVkEF+pytgrrzOVsFD765eJw7U0y30c7tEULbH/tnBv5wNxxcb5m+3XlDkAR2gLyFOeOI9xu/vZeaavR0qqdTPZ3q6dSvjE651yktjnzhRWrs06KXUS3790WeLcWqKVsBXENXsDyDKq3VQMBJmT+JBG5gec3sXgAyCJzxGsarsmH3sK5mzWbDFENOcBNfodU9D4V/Wr0zhaxeJBQTg6UWrCgwjClPnFEKh7c1UNtmbFhVvDaBbO0ZUY/OtgZ5tLTR00mLHcM8/9mZrZ1Iu7OmRGhPGnRwaxo0fam/AjTav39rhDfZGh6+kmt0eN670K25N3srcKv3kAdc6EE1ReuiDceLk1Xnz6JeYygTl0zvLtoKCryrqB9jmGbOKtyqLVAiXIk9FhfzYac4IzGRZez9AohZJoqC1174XbeUBI4+FiAGF3n2psybwlj+WcvObddGtewFbdQ+gz9luDZO9pr82UV3VbuzomC4XZjPF3RrT/m9DYQiELsl9jcaamZScpFVNQRTS3a2Fi4YaLSrYLvt5Hw7LIpx0j4/uowQQ3IgwljSIAugy69zm3q7Fo08ZVt7ifsbLsBkd32XNGq0wxBZAVl3VrlzrmQY1f1ztatgKDDrAXNFJWc1Sw+vd2dp19JzwzM7rOlL47Dqc5rCpLqmKER0rTINHf42kchLCgTY+pB9ZR1zSTRgT3lVuYHmDNwPyuZIh0thW/eb5+qr38VGH2tQRSYUYrR9GaPfaKI0427YVMRA1B2f/VLVNHWDEXE4iilpraJ4VUmmM4hgyRV7WjS1tP+yiaNno3nIK578+7BXXGtFeueA/ba7aLAnh2wLKbVHLkcy4SGpvov3K1itSr6CJYD0Fbk/z+A1UKTVTKhIp5WvvCPEa75h3Qa+bqnOyror2PnSk6gC8XDbJXZVr0p4zdyV+0/eXcW+hN6l5ht3C9/wcsXt8wsBd0+8LEXirDbgQ6dNBpHn3/GyNQYvem+v+gY6iWEIKWiVRYZCmAnbpjmzP1SGZ33H05w+rotH3l3Q7uct2/CqYDGXyQIkNFfmqvBLrpi7hCPpdsm5gvrE3CZrdNcyfTCnz11TF009dGOzyniYExGzqsq9MKUEbMXzTJmOClrZMUKDhAVG2fTBLmPff5UgoOsmKg/WXQu/q0hLx2bNj7NLfWRAgdc1sz624x7XXWxnW133NyxHvKR990KwNwyBBtolWnWHZ7S6yks/l8/+4u0O7Cl+aG8OrtivMjeaXEfQNEWjp42ovcdhO0isrZUtn0TMcR0DhTIGrwinqLUaVr9jpQDepbIrBaIkuSwDkOyVAYATQguIgsRkWCmGoo2Rjwbh8aoEKiGHyUcISMnSdGswU56xjV0UzQ+XvCxt4H2W+B27z4p2O/dl6pBAL+hr6o71rIbUTi5pItj8uQvs0yxC+FDN5FmUaF6KlZbYy4cuqiTRrphKAtuXSokISqfCOF80RSy1L+TzoQEr2C56KCOrupRgByoUlnUXvZWBV/fzsbsKhkK5HsDD3herkiVcS6LA5ZBucxi//VJUsAGTIHKUWThl8moaOt+O3Zi64SJBw1m/SMjqtmOQ2ug9LQRrb8lVeepuIp46+2SxU6IoC7SEhGCx64jVtAnvTpArlzLRYVsrNN4v1dKlwqtF62sCoHZ7yQ55BZrVHHLNswruqKl1tZLQ9k1ImT17r7cuEgTvuBYYu+Q24oPHiQRAzlL4sOP43YOmY19bKDvdaDrIVLODGFgWzHuAsA9faiTQK+B6BVyvgOsVcL0CrlfA9Qq4XgHXK+B6BVyvgOsVcL0CrlfA9Qq4XgHXK+B6BVyvgOsVcL0CrlfA9Qq4XgHXK+B6BVyvgPt0BZyjfHvOy8dlmj+/UPVGcZMgRKSlgvEimwcilJeJ+WXYDXiqroUr+fxZdiwgFDWotmgt+JqP8m6iwXccuB9OU2HaHqAa0/L+tDBuEMoVhKJr51e3Q2asmQbDT+sKAo/W2PmBNMLd8VFurL66KYIj4mGcl2yeh061YBU+yq5DQd0n+amxM/GahFmAlZkv6SaqP1BvLqvAizTU/SbpN0m/SXacIguRQqi+Qc0+frNgVGGLBGT1lNztk1XZVM3oI98UtaqsrcUOlmqpnDtK+Wpn2rU3LGtYOmcfJcMVUJ2Hy7X15l3l/Ibdnjk2AE366Ffg46XsYH9/ugv6HdpR0mlaMfb7pqmjXKuHneUcZWuLXgfHOUCQAyN5QKqGr6Sk5Xu63FXkUyOQfJP4aTRxTphhAqFRxThxyUJIW/eG1zuHJYj/KooIiheya1N1lHCjirjoMDRoDuUXChpF+YU82ycfHbR0an1C204pXMQmB0GlyS6J8u6h7SqyM6S3e7xLWuIuORoAd+EFJEdugQBv4BdoS6nCMx/GBRrYscgXXUeakq6Ezx2J7aCxmnkJ9DsJkiJiZgLQNLQt1HU9hGgCQ6rBgQZedHPoGaOeMeoZo54x6hmjnjHqGaOeMfpHZYwcpijLzY5/oUgVElhcbjO2ETHaUfpC1TaufS6tWZbxtHLSPCmgIUztmmzI3TKYTNCiuHHaJKDCoTQalc5/1a73Jl/IhEnGqstkwrq1BsuCbNHc21mhDtwx1UKEMwgECrzuvmmvQ5PsKJQAyXoPp3e7N4x9vwr+AVeBswIqnr9o3luT+O98+5wrdQmkeQKjRDP8RmvgdBJ4ihnPWwFc2+jQJzroQLqwHTW7KKgI+motH7dcqHUXdUAVoR5Csp0YUxnu6KtfKNibdiFXS5KTXbJ+lAFbSU9iWW3M0sbKMEcBXMvWeBtgG+D35KUX9X4t9mvx77QWnXUY5xtyVjl4MZ5f3715uLi7uRndzmcPw8nkYXx5dHL0Znp3P5kFEJ8pXUqSC+rilLO4ZbYVQtvTENaJZ/E6L82YDzPh+P0Whf6BEb2tkhYEPGfc9efr2s0z2sU5brKJyK1qm3qdl+csWfGqDTHDds7ix6TMC/O0KvMmS/znNyUDBqD24eONDkl+DpxHuVsul+bx44cmry2ycp7mKzXgSit8nuePTsbO87zUV0b6fZGnWuhBkJ9FUq8r3wtWVt2SHDnYDidbjfXFWJRU2V4jbdFUoEyrmWAZv7G3Iun8CgvXqtzB+ZVClPlSGXFJlq1Ve6hQq5lwoXZ7T6oz51vyFQs01yoTaC1Qxm9M5YftGDQX3WrCR3u1o6wEBDTW6mzq2pYI0fOs3qa86rSRKVwpEhjHtJ/8DQlwp16epvisuH8ePy7yj273wJMbd54NSlNWVGKRcr9satMx/djqiLX95Eg5D0RtAiCSltW2BFHioZt6G3gY+4bjwBy79SDKFRypIiG5mMQ5xvwuLFj+rUgSngVAwdJk/x8AhUvLzeW9YHwXbEiwBs+twIcG3/FkfR6Jcj2zPfJlWXvp/ZM3Zcz13DS7ZwZEbQ7gPtu0h0wBg1UEZZESFxBBOhgnaAIlH3aEznJtucvbAtFfZ3HDB8sm2pncFMYLgOBg2p7yIcrmYAI6iiA9+5aqiYumqvONzg5yyePcDn9inj0eiPaeOTW4+xYhxyBtDWBC47HjcL/kFSVNpd+1c+FpOacL9JGzRC0GYBPpyzxucGkbQv0i/YrDL34NdUtWlyyLuce0KvBoueSxrZmxOhNIpyPUN8KvSwc+Q0rgP3vTfZVn9RXbiHRrvZxn9Uz8YlX3Znylf1hQMDovty2A6/3rwK7ZNm+MCii0XmywZ1Iq4fN1yVni+xg7yI4aFdKp1+G1385vrs0HqSdv0N5yljgM81suVmtVQweT2Mkgfqqmy9wF8Kf1onq80FcNDbJ3CgIdQEa+b2oLhaG0pDsoRLhwRyGlg4FMztmqVUg5K1yweM2DwDe8Pt962j/zy5s1vIwbonDNtlwRS1qWwN6ZUSRY6NnnzkIYa3ZkDmf5y6pQPjkJo7LHCeWudstZQHvCgJtUJ9f5Vh/+rWMmXK5lZt0u0tKThor4dtyoJJ7kVfggDpawGQEoAHN1myf80lHjWtLv6zwvPAoKIJt6gtTc+OmzwpXaABsY2qYO3PWzT4R2+s9sh//M3bcSEGC9O131rXgC+26Ke2+J+2+ItzrnmRpiq48AsnbJHYcDUf4uzFfTb/sAJ4hN4O9ATuDf3iaXV+5ETPRGgV8aWLJVyYq1LRAtuebTJIiXG1FZPMIkZdsFix+dEZukzUpkyF6KzGYgAgiUauzGeuM1yQVQM3vhTfI0Nb+s9uSTPUYIs0bRPPtUJoQxv5wepanTRCli57TacSPfdRsnK4DQlnYwbf1/mLfuMCqYqpxx5DS+S3bYUcKVGhepIFeONmJrbj877k0dRgpTsVi4UoepiNfO3XlGEXsknxoUHa9ZYdE4/WhXO3vkdWztg1ma196TtX5mG1bWKH5wTzMDt2Cu43kuUt1LerCK1oqTcLqGv21p4Rw8h92WEWQ98o+1++RRHADZj+tms8jMlXCex+b1++lY/1CGH3hXDa1tD9M29XBoiwMKGHbsqMfngSqL+99VQjNA1maWIV940n31MkVkbeOkAxFkxt6JhOfWTzO6+IjaksYqnteWYz9rie/BPMWXMS98Ga+EBQSyEmMxyxISOtY0qiWllBiXnIFtDKv5Ki8FGcpYAqyPtQWhn/LkJCdiAlmCAm1oY0nUNcx/9vkdbYxjnle8Dj3QjeXo5GjtjAjY5lgNVxLU5s4kosVwHZ0cWbsBnsLjW/gj+MGm6KDDYoqelSFyDPY/mdtS4222Z5GseP1iBWyv+OoVX73iq1d89YqvXvHVK756xVev+OoVX73iq1d89YqvXvHVK756xVev+OoVX73iq1d89YqvXvHVK756xVev+OoVX785xdffTjzd1n8cMc38nf3H0QZFIaDd+gv0YyWqGjiPWVMuWcwlHIQL5H4rSq51ZiLHf1WxmZR50sSkI3srVWwXeWld1EEDx7KkzEUC70Bo8ZRf8gJfOYvzkg9KSlEyYM5LRSmeWLyFl4iRpywfZ/+v+Yyz6Dqva8EjliXRVDzxqIT4AWWUZ1HCIX0AYuI8hQxIUZbXa5GtfopY9J5m+n10P72ORBUt4bzgSZSKR3hnG+X1mpfR3XwYMcgweUoDmnGeVLc4JiigOzqry4bDFxbFg4BzzhlYWJNHXaOLo2jG5uTomS+OOod8x2gUxQCaPotg1VdRnqXbqF6LKmJF8V0V5c9ZtIDORt/j92wk7xwdPxGtO5HorNkseAlPWZLySCQnUclTDuFNk5Oo4uUTj3IM+P8qWpb5JhLZoCjzmFdVRMNZRf/nf/3vKMvV4At5G+dldQLgpuJlBG2fqLlQc8OTKC8jkOZUG1HXPDmNbqE8W/Goqkso+ToqaUySQclZlWfRcDKGYjWPRB0lPBUL3I3pNkpyXkW3d/MIVLgVj8aXV8PXw9vL6d348mF8+Ro2bvr6bjaQQ3AWsQSkEzj1rc5Ha17y6Dlv0iQi2hSxaCmyFS+LUmSwlwcsSwZ1yWJQCkZysqJlntdYguajzJ+pZ1leR3H+BINd5VG9ZnW04GmerapIZBGLKl4w+JJIb+Bt9CzqdSRqms+ExymjA6lzZS5ZWuHSBLXrQwmyy8RbnjEIz1Ik8fBjRmkhiZaaewL4mDYVQU0RoJAzvrIpqUTCY8EaPN9LYgJMZeS62mwAWdUMeUn8b2quiG+CfxawWVRxKRb8mj9hl59ZHa9vKVsf/p7J2uRDXnyhnSeJHa7FGS5FqOM/jh759ujs6HZ2I+IyL9Z5xjG8/CWHfqpbX9WsVrwC7cjZ0RSnIML5oOnc5k0ZbfT7p0d/+8vJTqoKryJx3LD4G3cLL+apGZY435yyokj5acXjphT19pQ2zinWNBAQyl/SR/cIKKwbKFJzxJwa8Ol0dHE3vXwY3l+O7/adBdbqPouG73CI6JN4Gb2OUAKhnk+jITUW4XaJ7Hai4wSuLmXeVCeRPJFenUb0KoxuxIAIlECdskhkNWxcDjQ2qliWLPKP0fFSpDyClVrD7n31k6ZyKWdPvMIXJHVpMkguaKrgWVJFYv85Y33uw8Lcdr/Ief4N1lL0vIYxYngUDHDj8ySqaJvDQQwc0JNccnCqTYCwQOfux+biDnytmX1cIf2ucXfNSajE1d10BCZLt5cPs9H03fhidGi5h5vxxfRu8vbutuOVyd1s/nB7Nx9fjS+G8/Hd7Qwo6jIvOU2ZTOcEMWyw/2agoFxFWJoLSJh0dHYk8lNltHUKbOKptbWv/HqPOto6OrNb+tvhtMTaXGfEUoVWbBVt2DaCa4/IGrW4zZs8+SkSdzN4VW51XC6mQASMCPKoijBhUWbvGPNdkRwmWm8sKoB5qeDSEdkBjvbRkAUr4zzhD1VM5lBfl3ZcsA0v2Z7ddF/xJKrzCLoU/WkaQf8qHBfZ2eqUJu9FG+JieDOaDnEdcgY5TZ31pV5YszJ5ZiU/jbGnkmkBPlPxUPuGs+K//73HWbGmXl/nK5G9EwwDNU1YVcmYLTburi5sCOSEURn9DJykkvBww+WPqZwj/Vjx2mtCs23wICPKqdff8RLiM2HjSKIEr0y8UgvYApBIwgJo2YECvMGEiupJZkJQj9QP2K1NpswxnvJH/mV5tR2HwTnN1gtupQvzhkU69L0FRD+Kqv3HUU0053Y2oaIXfjHIl4UWoqnIwGQEV9HJkbo6yCUHMoQSbi7Yn+7aJlRqWBRXcjwZXBagswf0BRemNBb9+j36y8kRXP1mbMnrLQ6WFCwBnZjwsoKikSBhcSKrI9pQRuNLvFVQ5UdnR9KWNtqwjK1w/o/gkw+rEb8bbnzyw3dXiyvTOSdoRZxFIEEG7k5kkn8DEg/HxHdVxLGNYyBhhdyXcMPNMz6AVYUU7lVkmMjvqoiWJp4OPEtO4DSJ11HJ66bMKskyRSI5jchKAq6ThoEExpRX0SqnOuFGSfVEdZ7jtZzujCTdWDYlyjdQDgDrpLL6ARdMtV+jdZ4m0TGQzJOoWOd1Xp1EqTQs/j//6/97tfewEfmG16WIK59CPjGRgpib5IZLUW6+0YXtisV8fHngidRkIP83wwwnL1QQjS/3XtfOzbe/+Oy6n40ezsd3N6P5dHwB37qTRLkNdXM4puCZ+oqoqtm2siRmUoSjCdwAFwnP6nKL1yae7J1zWJm8fICTxpt1uvJ/cZHYr50af3XaFyBSNAkDmISziEWyKrhjGZlbnUeAh90OHTqNhkkSEXmU50L0OoLgcpFYSga2XkeF5FAMbQIyo26yoPJDcrLZK5qKWcqzhJW+WAqZDqUAIqG/egpLpuCSiCWqDpmTjC+LlXwbKnMhv636GSjzXZZuhzGISvfQHZgAjl8Ck4N3SjVKp3jEteq/atL0oKpn6/wZp4oWjlu5bLSjjS9T825qqRo78Kb+1b7/sFt7ITctit5LUkecqsqqT77BDy8fLobXo9vL4TR8z/55Op6PTJk9B0Nsj2n3saCKnUW4Q/5d1NEx3Ft/+JfvibEY4A34dbRs0jRiONivoteRmgN1ZWnL16zvib6P3M6HJG4DuXl58uqUOlPhAWWdT57kTOkM9pAceTTFLE1bnEhWPdNNilgSlLfvFILXdIcBW4emUGpErPnkKF8usbKSx1w88ZlYZSzF57+SsUuIPFW8vmnIhr7i9VRkK+De6GlWcPaIVVZYl5R504MSeqsnKTmXQCUzl6TxVyYPn7P0EYhcwfMi5WFxYdKg7ofBPk0PISFp9aUlfZ/Yzb+fvLxFEpQYbYC0IdaDtJMgpNVZ9MPZD6BUTOnKQsIrUFtFP/PFdH5xGs3X3B6Gqi452wCLUXBeDup8AP+R5grSx5FwjbR9TZHmDH4vtribLWUX8KCihpd4BjelBOuoQNKViJLHNag46e5EitqClbWIRcGyOjq+nF/PBrPpfPLq9OhEfQvtEJil49nlJOIfYzRVegWNQD3DyeS7KirJNEVQP1BN6fXtO1Jyeh2GaxLo9UCfDEq9+JHX8I08SwowdjuNfl6zmsPYKcIFOeDhhgW9wUEVVfQMFzegZUqDmIgqTvOqKXm0aSqpNfwJ34kZvW+UCt9VeDVLcbDQCCGOxhN10QUZmh6N2fz+loi6yKJZDcfhD6cR7h8QZ2agLq/Yhg8yXkNGUqwyzyK16J54dDucI/RqOL4GVLXd0N3iNfWshBKga5/fT29Bk8y2+hOX4iMHdYdaGlUDiYQ49LrkqL4u82a1xm97L2IOEl1eVu+j2E4oH1VpXu+n+CjV8xWfBcgDga0W8aNlul2UoHrlyhIZ5JF/mn4zjvEFktKaPXJ5IY9EVomEq4XlsnATKHItFiUrtwdWDUOiqkY9P1K7lOqQcthD+LMv9TUvIqZquj+Jjn45gfFu4gqvnWmBDE5R9Rotx6qI2fczvHrf3V7/Ge5fctEm0QZ0mrBtNAWFexxZaJQ/4R6K8mwg+SX5mqq1UkrJvRsnFcUiZy2jgTWr5sSCgL2J/IlcIv7+2uYuultnEVigIRE7sT6XxBeecclrx7IEWFuylalLsVpJmlxtq5pvQFpXgw4HVCPR8Q9//P7VT5qrtQxsSNWzzOMGlvDxD//8/atDTVb23orJqa9q2xIF2FHYrJ1MJSvj9bciXrLTezb8lcjoLGdJojgqQ2PUl+9n9NQQHUiLvnznPvWKKA/jRZ4/ftYl8e52PryYz/ZeAO2B2rGpZLEzJP7Hr4iFU03ifes4b+pBvtQWX3czLMvLVz9FtNKOX8lrnxpueVMM3wrlB3SYXVyie1Nc0/j7Yetl9cc/i4/RdDSb75VCg2HGA3XX21Vy/yAbgJxlXm6v8nKEoT++0N7RC/SARQM9rU5J18yJeJ0C2RkghTVLpnsuoYYBfesZKa3xvMDjRDI6cmKi4/ux4n0m+EL0OpoNr14hES14OUCDllXJslra7znEzVqUEb6fRNh9tJSJ8wIYupChzF4KiLV4E5WSItE6c8h2lu67+gz6ouTOHWcaNJ4MC1H5MlwtFB6qQpPxhUSDH+lcbHhVs01Bn1DJ7f278z/8ePoDCYgD01idwbANqjgv7NkDEStNhCu5PzZie+COX/tT9ooubE5/QicU7H7JnCTRgsdgyweN1a9hEqTUF0wXwDoyGdZgoiBn3mXeiGYKPEll9fTFdFYqsmDWES48+blKmMxWfO+CWeVJXvsLJmfJhMnTEc1Y8UzMkm+ma36DvXqBqnmlX+je3ljmDEd4BYJ5nq1ExoF0VtHodj6ejq7/HLZ/1pyfUvH45rksY+m2FjE9qZsfX6EeIF8q61NcRSWXF+eSg4FKQGMEyhe4AocWWJ2rBUYXY71gRF3xdBmVHCMvRWyRNzV+ZwHXx+MKhusEFBDYKZFnr0AA+MTTyrkzSkUmGO6xchvVHIguKLDkfVOvbvwAuubDL7gh4wCjpXTB4sfqjIZZujbQy6l4gqUDvDpDwQJPXs+m40Ehsown0ekvotAW5axWxxrJnkF1wxMSI03KHISCyr/pFJbsQym9EB6g+WO5Zy1Rw3R0dT8bzWAMsTIwBGLxI9YIo8WiDVjAwjxXa/bjH/4YzabjKBHA5sDCACHENmLlBmW8r+UmfP3MF6+kObKo4DNhTFgWNdkTGIsALVdjEFPqstMItlcVpTioGQ78xfDi7UjKaPJyC9t+kOTPGXwZKHtPQPCCecroZEedNsg6m+IVTYN27zFz8X00LIpoBoql6MfTP5z+eGamRxtgMZFFby5nyNop3Tl8CHgNFSXEGUCdOwwnCBzWokDSiZw/TPB3i21UgNAWNsV3aLqNIj0SsHDpbx3NBS8Hf4j+bRbB5uClGozo+Henvzv9+OoEF0UGhuepiAUIquDcKKD9gugErD5BpyYar6MoKd8UYOJFt5YMDEhFVp9FSEJgKS+XIhYs1TRTXsejFQO1//nd/G00GECAhgEuBpiSwaBg9Tpa8DXwtYmoYAIeAPaQqyxrcsZ5tMjzGjoI65FETTBENj1f0F6CmmH0wVILb0LDy0tYi6I+jcZLRP0TVPZPuNDw+NjwKONwLML7opaW9JIugNAUw24oSobOCGbyZbOV+IWfRaCmhSHCKaHiLEmq6D//5cfo5hyvwRle74CWSD+G4//8w+9P/wXQsqrvo//84Y+n/wqQ2bNY1jjGp8uSbTjM6Sv8xP/88Ud6CdxjI7WEo9fRf/7xX09/DwiRVTXEaUC5mJqWY1Zu/vj7wdO/Mhycn6Lhm4lSiZ5WYE4AM43iuASGXr0Ho7nZMCCAr+QSFVWUF/VAoNANPwiWp6hAPqYO5XyJth4gZcvybJAXtGaR+smvBTFBRrLOvYr7NYR8in0OOWXbL3Rkvuie8258Ph3OR/u6zFnasjI4SJHzQYaJCV6d2RP/OS8fwfLu29yf3+J3zNas3G95zBK6kVY1L6qTaM1ZWUdgcX4S8YyXK9qkz9R/KcODTO08olbQ0hKUoVgLWlzD1cORG1JJMtfbp1dlT0QhdIvbvEGKBop7aMxufN/1OeHk6F+e0tQ+ilpP9g5eiyp/uZ0NNUKX6uHFfPwO9ZN30/Fo9nB+P70dXYb1sPZ7l+PZfHjbZUxtlxz9j9H0Yjw7oOTb0XA6f8ANsLfsbD6azHYWI8XrJ3wfvXjQB1JR/YV/OTmSK0t023XLV2nyrMgEU0bWM3woF+eRisZpjHQEMiNkfkoNKHdYM9MfVQvw6Xe3D7O3dz8/TEbTm/FsBjbqMMDju9vhNZAZNJrc18l3gj+bjuLOsPpYs3LFaw34ch9rhtsSRFtzMJvDcnk3Htmf93A/G76BSTtkqE6p0ClhTsNV/cXxBm6/rG7Ep29Hw+v5W3uocYD/QmRXKKnT5nSV56uUn6p6WFFUcqAwvsce8dba7PovYA0maYixBpPWX38X49wrUWeuXe7X6s1O4zR5YsCBstQ9sizUJF6arllGaqDhdBry7HP3VSy//6Ca29ITWhhn8sxRBi1gsyLbvZBKzmPJgb06lafUm0bABS/j0R9Ofzj9HXbwDS5SZAW/q/waijwV8TZa5PUaBCELdOIANoz6QDockJCw5ImXtUBcXkYVT1EdLeoT8nSACgxTrDTAsno06QXiRPcRu24QiQG/bPVS1QP3U6+7luso9Gqjbm742kWeVTnqNUp1T+yk9/9ky2202c5PwIGjXQ50mK5Z9ZpX3Cpd6bsq6fjJNIbjRwDzDm77JCaOEp4JBgprM5EZ3iuUhOB5zdEAAAZBiTWfGdS5BM0M3m/eBxjA9xGZ/VTR+wyigdSAz3jyHr+dFD2oCsAucNL9RJXYFOlW2z1mOdwdi5RU63BPN920OBwzG7VTxLrUy5sorO3xJXbBkt/MeVVfpRAtjS5H1V4+XmzEA5DStr/vXYGBQOOmLEnjvc4rFaM6B9zX1t9B3wbQt7MI2oNRJhMOxc3h6nkCBaflXv4s6ngdHcMi5eUr2D5Qz9nr19GaZUm+XCqZllK60NbQJ8FPjv86ijfIGIM98ow4ZCCzYEfCNtVeeaNghX/lKIpzgfd3smeXLs4OnwuC7UxU6zkoI3WoB1icbPvM0vQCjRskSPG5+HSf0Zs8sd6VVsHxmkSb6udVXqJ7j8ngXlIcnm8m9xwPJy+ResJg7l7Pj3wb0kQnooI9/dWXrGr+LJItyp2cZ4MqLjnPIlUCVyEKRpQ6+llkSf78GhXFsOAl5QXhADgXM7IaeuTbqi7zR06iV63jxidQc59FSC8ykJDlC1rLaEkDtA54ieSEpDHgNY+dG9+MogUnKSAKbW/3RFz4KaDh+RT1NQhHH5hmgZ0Z4xiYS9knklH2l12Wjs/w7WzWFHhOXIsnxV4j87n/Qmm9sX35tTLgDtvtNjuZ3t3czUeXbf/ZXdsGxnmghnDn9kGjsAcgiOC5tFtWgq4FRHTo7xBjyxRNiQZRSmjyoeEN9AvZZXoAiaV6GGX4z1bSNUXFv5RGdff6U2kP3O80TrfKZtaGoN0sRBDS52JYaAR9z7NhkujfFylnpX66VlpKeLhVesoVxliTA0GPcmF2yJ9+NcEtVA6Jn9c8G2f3Fd9v0CXNxeSLWtaUcVYugHWCsHX7LTx08orDLDxU8S/XvZNvNQifakli1vknmZEMLy5Gs9nD1fh29HB9RzQnTKNkyYu74XRmlT3USi7NLUbEs5PbQ+HsNdB9PKtiZ5G9cOBmkA1ENgA5+etIgW/Q96PEgxqcMat1rsxRj83+Jx2ACYOgXPzzppJGzmhIjLvxlW/fEhpZ0GEFh3Ff2BG6R5FCpimfwPDW0C28PsIdbzaaDEFWaN/uzqL3amSsYAbvTw84LLx3vnKEgK+4vQKbeJg+s201zJJDm5ORPrDFMm9qFeZBq6wrdYU2I3Zo/BJnhR9CDU+CYCvsaU8uf6XkclfZ8+HFv8t4K7vLf0YAl90Vd4Rv+Xz63h0Bxqz9/fFfVNlTtbZeEgBGN/Sp582nypMnpK+1Nu/fVZRr9cOSs8pORtY0vlDWGjgxzpRAsIqG1z8P/zxDx+G8FL/QBkdvHiUbRIW9Pqvet8LjfA83anXEBqLhHHcuihO8Gv93VfWJCpwDunJ5lYf8QlGerXI4S+0oOtrL52422LAsIQNK7Y6DrkUwPFMcjKiKy6YGGQ2v7A/QJG3N2ZNIt2cyRoR1y8azHda8NATJYrBWIcvNJYMo1JHch8QLSCkA2maZ0SBnnmN+ujqNviutI2sNES3pxCKlMUksBNqUfCeNbli0As2xiKPvxAbcu2Vh/rEAbU0W8+9Oo9HHAgTITMprUYwBkrtnUaHhlLfcHTurtleDMmFgxicMtwOZHpUbloIfkBFPvK62WQzW++MldFc8cZIzP3IOy6hEYyAYUnQOs4wi8fY7SBYReQqQ3E95Trw6iSC3nBx6f5u/NptJBkAAySzOAp78GZrEEdczINekSJvW7GO00Cr3oZDR133RljQ4kbdSO46r44Ka0R1RhVssRAwLZZxN6AeAwHwDHZvAfQ6cpWkFEOxJ5PJeqywk6cJ+adqvOH+U/+Z5y1f1T/KeD26r1KXqUUgnVLoyq3COyhlV36WbzId9PUnQp0ePoxQGLxYAfU6otdHlePgwuR7+GfiCl5zXuw63jf6O7puUuyTPLEL2GqKgKGmnKkDBymTMRRmqU4VcVI+o3zNUStFsh9JWcqbRKBj7MEgxrhnQPiQWTtCKBYRoXbIm3ev7t8kDgqC2cdAwrUXdYH6HFa9loprdDuC8uJCCMlBiwPNbAUL27YzXTfFrl+rc5Acw//iBlqERRflAEs1T/kRTpxyfsw4zoi93F5A+OBuIpgSnKV5+g83vFizRt894hmm//vLye8B8/G48//MD+Fy/uR2/SBRSYaunMJwoZ5WBAlym+WTv+wtWQhifT3xbjuHLxTFyN30h5vg3Yt/weWYINGQkmKKFFx1f3Ex4QvMXfR9d3AD1wadXTiBIWqFKXHU8//NkhIZeDxd397fz0TR6HSFsMh3NZvfTkXq+Gb65Hc3HFw9X49H15atTWZFUab8slsbJUWi5o8peeSyAb5BrAvvDP3+PH0KWyei8ikbWNQd/EFz1yFvrVSx9FGhnAzuHvC3saxDhSRsB0sKjOl+r5LFx4p8TDiuX65aqqAaOt2SoWq7XjCQ0z2uwbqBjTFsbSFriWPYvto4wkbhkM4tnysqBLD3eIwE//o+ItthZ9J2s9Lvob6/eUw+H17M77fJr3XYwRBxGWUO+0pAa0nJTPUpdDY71T9wYCOPnigzMPjY5hgfYbHJwzSEGPKthWPD3olnBB9/m1rijUbu2goexmIlNk7IaAtWVVKOaVS4R1WlEwSOtQ0DRvggNQVgaKZKD8/zePnCPX50ytd7fY+B92OMy6rlqXM6yfqa7TQ3+C3g3MY4s5B+Cy1ee4RHYt+PKlR1PmEC1KC+iOq9ZSnJefYJT6AWGbr9SWfsKhlF6foIul4ywsYbZ/G46UncILOA6rpy1lzrdTyA6BjYP0xVLc3u8jUK0fNgpZASkjWe4DPdHfhjSoIhcCwRYtTdCLhgZZ4aMUWirUygjHMUsj/6aL2A2WQouH2Bnjs72EGI2ydCmpKQ1Ro4maCkAzZI10XeVJYoeTsYnGGmD7M65GprQMQFX9was742ZPMQk1J8Nr5fokbKUy/XVqW+qJHekjupPN1VZP3UUFlipNnCttsR7MlF6b1nYnCA9Ql8z6RggdxEE5UcfAjIeUQZNC77NgRoH6J/yLoGWnMEh+T8sPhd83DFGr85syzIlz6jkhbjy1pLyjYJlQouqgSUd/fDPUQJ+gHe30fztKLocwSXiRC8u2QKjoHE/6QUrHeAheAhatdHqRIrLlJBAGegkKrykCh0QSW43QlV+FUkPrqUoUU+x0OxddGzgSK5faY8TAiYUFQTjtzBwKYJAMsZALDg+ZLkVva8M230W/U+8TxZkNvs/j97Tkc7SFG8xKloM0HcaTuULScc7nPiDim76uCIWORaEqCORqF8Qyd2cofujuefZA1XywMS+W0qGu+ALhljYb8dzl11i74bjPfdG+zvOgFXiJciMOp0Sj8nU8gquhHSEwJ08hWCDMmwhGrohcRmOX+msInAVbE2AWlBEttQ8GQ9DR/ZEs57keSmJeCVSnoHEaImxb+y1Eqd549kzWl5dvIpZiixOnXsO6mm6UY1X0g5SJvQAEZ3K4dFKEmIpEo39kJx43Eo31xGYDb7h2XAcvY7e8I3IRHTLshzt5YZjmLRXRDYhuhBP0GyItJJIFy2L6036KOqzFc+YGPzT+4gY/yjhBWTQyWJ0hhss2CPXvn3kVmRIqkrJSEZPSQJtNZh+R109zG2CUqggmQAmB0Mi7dscBc8emjLttGH8JuaK0MigKdMzPB+I+5eSWwokYsTYaBsDPnaDKl7zDRCbqobBu57BepfSjj+R/fsMi1TRMdhenhZQ9BUoieUCYNH/JQ3l/28IVyiWcFQuMBQtjLYcBGnyxXGZQceQk2bZd5BPBhYrgxj06JN3LLInVgpgmH/4w6vT6BysjfE2AAaUAxLP7/AQU9Y1RbL0JkRUQyuU7zeZlCJZoi0eCKJA/a0944lngyBcKEsqyrwmmZFyqiVzY5b4RMObWmCYLGbAclc+OqHWZTKh6O3w9nJGB+/dxf3N6HYeze+i4e3d/O1oCkHFLG9pcLk2Nq3wRZSqigTK5YaMlWEEj1+910drFknnFXDJiMjRQkdchfRVZHOYoD2gjjAGCDxwKVyZppqUFgrl2MjF4AuGR5OdilMmNlhSLdvXRbIExgc/pUav2wW4JaOPM14v0dGf5PNInNWc4OkuKPq1UhcQM3ZCX44WDFags+e8rNfRhsEV8ER/6ftJsgTnm/fRxd3N5O4WRvpYhcgGqgN3dDAs1hHdFryu0UE3h8BQexc2RmFqx9wB77buuDvgKDhX8bW+kfTODuk1TJJDUyuAl54MsaUiy5qYXp8XMWx33YeZJHyNr/oMcwGqcyDrOiTuCr1BEXRMxg8vas7krQy0cuxcN9DOFytQLUbS4haTX7yS5kpA7O0FJ4/2vYNnBSE4jXbPsDrP8lxr6PDsh9AQv8ClN2WQCinbwqdY9YDDheT6jsfzm9ngv/3zH//1dxTnA6LG2t+FHMXTD4bdoS+nmDXR91KBgPc7nF/4Su96lmfRD7/7/vWP/+37fWwEKL4wQsMD6fx87+aGMjaCdxz/9QQmp5hweUlB4X4lLmmo55GpTv+uQlsaHTwantQA2SYNRMpf5I6G30ZBbNzK3sHpgf5aqNAvdT6wl0uD/aV4JtXQVbTY1pJe3M9GUziyKh4dM4qwJffHia0qf8qlFo2SSLAIQmFRXEBw6NFSrZIPqEniieYmQUVcYqQLiCnhy1kgUCurazrblRkEMBQq5Ki6wmBMVbRMwLg9MnaIuQHLgCFKYCZkdvfTaF6Kjatzp5gxlNIiJ9cG8k4vCtDtNGgOIIfrzLmTSR4Y8m+oW7KJlQSRPjDahNby41i+pli2oNOH77HFxDByA5vba03ae0kt3lsyFLobmQhNKgccsnSijqajP92Pp6NZ9B6X2Hv4yAW34tDIJB3KjZ6XyCIBnRN3s5Now2L4p68HwO7xhfRyq6L35lZ26nf4VHcXF4qMiqEELLI/p9FYMmKlIWYnKgYMeL0JZWRLfUaxt9/Ue8VyZiDvlEJCCgwldbzRMUqSXpOVAcaTekU8Hozq++jY7AQ5DCyFUZYRdlWEOZzzdvPh+ZqNLu6n4/mf9QBDyDiM1EwL6GZ8O59hqBt8AVf6MXAC1eun37+umoVSCb4m3TQVg0vhK3mdiNdw+wGlAQPlOEizszzbbsBcGFIho0xbiXd9TFTn4IMGktkFRFNGfYoSPtO6krF841RgpmrYx6wmKQZGCcGEhOrqjuYvS9qKtvyTeGUdtgV2jKI7Od2ZaDiwWjXqoqoazGKm7Y6ggyjOlndNgOGZDiOLJ3eklFYgTIG9zlltQpUSkWIQlaQumwqvAU3G6roUi6Y2UYb2M+xNtQ7mMx2mKehtTF5T/QSuGpdKx0Oq/HOWrKTin4Rdc5iNnYkm7BpQ+2/S0wdjiQAZbVKuelGpRr/obcHnc1lRDXj2JMo8w9DGZ0cysIbMlXSAeQzs0ZoPbFONfcYyE5gTh98/JNDHnr5+Ad+rPZrtQnX7C3ButIqcpDJ/Fx6J+qFv3TKLjMXYhAu8lKVpKswuA/8lITuWFY8vX7l2O+TVjHtni2ICfInuGyC/vBIlBwe1E/0rYmmVyxPLcB1yoEBwRloO/rEuWchXca8NnjR7ewCaU+a+qJFykZrEEKnKDI+7GL7qq0u6ZAcHsoNnKFOs7PTeMtm8FPPJ8jLoD/qJqnf1OXJCWtQMaONgWXIeraU2R0WrJ/tcnciH+NFMVR4JsmtNwYX1ttPlupXQ++Z+NieRI0p/zqL3skK6Er9HLXBRKEPK4yJtUDLEF82KHN9f6QDylNe7wuAJpCxei6Kg0wNcr0sV/kqeUCkHj3xMr1lWUUES7U3F0yd1/oEEjOtPxIRpOfI/GAfNCWrAaynWh8swRkwncggXU4plxsv9PuQof+APMsTlbvUPHLC2M+UXDHW6u48Qj2p316jIN+gKpUF5SARTZuStPC4oo8CLvJfM5Wtv00DnzqJKZke3WD5ZjtK84xVEMVo6A4JMhsGKArkunS+eZ2WepicqaCfEPC/JbJwiVZ9GY4hEAS1i+xWZnVCcDOCwFA0jHW+WW0omGUqP7EH2L9yC83i9b8HG+SoTv/C7DH0z8MPt3O7gQ6cy2eCDzmQjn7Ac0g+0EP6C4pkvlsBGCSFVhH28sNLNHM86EdcyIa8tX53h8E1pgA5zwqIcCRB0l8wxsQYZWpl/rPfaPFKTXzoxzq/r838t+ek/lW8MCdf+HtkIKVv61xKB0dydRfprPS+RqkHPWkplMcDYo7P5HLnF0iwZNBxrUvTzGCgrADocKYyOrt0Kh40OHPsYQqI+n+XwmjVpupN8Yp6JB1LkVS2/j4y8KEq+LHm1nq3zso6bb5a8ayZKceCGLJtMSefwuEGOE96HIPKq26f7cq7TaAzkaJxF4S6gmAOkFpSAVGejLIqIRqySilFk5qCGfRNds+qxCoSIoAglsUp73S0FsNmxjpRuFzIEZvKNJm8KBiGgCf28lIilqsYl3Lr2L1jnZyWY1HUq2RYY++CtJbGytOmcjHtPSf2Be6ydcOmcofHHfzcJE3VvouODZkKKdiHH4km0Y3RRhv/Dv1jGQf89YirPl0kOYMwhW4rFDsO1vTsEDFTaUa7S7d0TL8mpDAVq5lH58Xx1dhu7doYnQpo3pS2ChxBwWU2iCGSzN3yTa8c9jtoRGC5R83awpvtxK0TTt4qa1LQMAFNO/HDG4scFpPDsGtRPHMRGnFkRrLC516qxSLoLmpFQSwvSvrhqa/fW72ZaujBR82GtKisjZNuk2QYG4W9F7n+mC/p+s41nvoCv+swQFd2jJOs/U0cO3yx4AkfQz3wB5iggWaikWIFsFyNWLkSNum4VMB/iIYPFDCqyWXQO5WCpKCtaY/zyE6lcmjpXOqj9JlnP4uMDK8RXZVqgjZhVa9FKoOOaf6GdA0/m+YRtN1882fIBMee+hO6dui6DIv49efErAUI6EUwNLnv5iY5J6m0Z7DIdPOdlil44Gw5mcseQoAoYjNckBnxdlAJc0QdFyrIK5XAVr+uUBBagfJY1unk4aDYjuXJ+AgVyEiVgKpZSliCk0+IXqoasgicMMg0rw29GwcxJgQymiqkjI9l3iMG6LVJWgzrvsA3ykoW5e9dAKrcK1600VYRYFGwLWldM95BRoLFlyj8OKGMGhXeuajBCNpCToxWEmzyqCowGAJ1LxSobiJpvKnD0gyeVv5Il6Lx6pn/BGCQQIZ/+v16KNL1hH39GIMTPBx+QozP1AyQEHwfqlY0piN1clfkz1KTKwvlbHp3Rf5pMJ7Da0Zn1EMAPVAWBUsscVUH1tshXJSvWW43BvH/41YDnH+sh/j45WoBxRDkoWSKaCrtVZryc0qNCQ2v0AyAfB9WaJfhV9EO3ksNwYxBv9evkiFUQAmGAHAKMPD5i/G4lrKKFBlmgK16/Bhtx/rrMaxVa45cBcHkfj86OfhnjD0x2VVOv0gb6BGphKUc7O1qLJCFf/bwSen2I+BGdAkqRDGq+gQUOYv602WT02fjrtfwPStlmo55G0ir46G9/+/8B+zJdcI08CAA="
|
|
5697
|
+
sha256: "4eaaa642d5d3c8ee88c924ebb1af02db4b9d5d450492efa20a2651a71153b7e0",
|
|
5698
|
+
data: "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"
|
|
5697
5699
|
};
|
|
5698
5700
|
}
|
|
5699
5701
|
});
|
|
@@ -6876,9 +6878,9 @@ function compileV2(html, profile, options) {
|
|
|
6876
6878
|
if (!row) error(el2, "HHP-BINDING-SCOPE", "Item bindings require a keyed list template.");
|
|
6877
6879
|
return raw;
|
|
6878
6880
|
}
|
|
6879
|
-
const
|
|
6880
|
-
if (!info4?.paths.has(
|
|
6881
|
-
return `$service:${serviceName}.${
|
|
6881
|
+
const relative17 = statePath(raw);
|
|
6882
|
+
if (!info4?.paths.has(relative17)) error(el2, "HHP-BINDING-PATH", `Unknown controller state path ${relative17}.`);
|
|
6883
|
+
return `$service:${serviceName}.${relative17}`;
|
|
6882
6884
|
}
|
|
6883
6885
|
function coerce(raw, field) {
|
|
6884
6886
|
if (field.schema.type === "boolean") return raw === "" || raw === "true" ? true : raw === "false" ? false : raw;
|
|
@@ -7708,6 +7710,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
|
|
|
7708
7710
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
7709
7711
|
var init_bindings = __esm({
|
|
7710
7712
|
"../../core/ts/src/bindings.ts"() {
|
|
7713
|
+
"use strict";
|
|
7711
7714
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
7712
7715
|
BINDING_SIGIL_RE = new RegExp(
|
|
7713
7716
|
`^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -10249,7 +10252,8 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10249
10252
|
}
|
|
10250
10253
|
return value;
|
|
10251
10254
|
});
|
|
10252
|
-
}
|
|
10255
|
+
},
|
|
10256
|
+
...opts.wixApiSession ? { identityBound: opts.wixApiSession.identityBound, session: opts.wixApiSession.session } : {}
|
|
10253
10257
|
};
|
|
10254
10258
|
const dispatchHost = (action, params) => {
|
|
10255
10259
|
if (action === "himi.open" && params && typeof params.screenId === "string") {
|
|
@@ -25433,10 +25437,10 @@ var init_preview = __esm({
|
|
|
25433
25437
|
}
|
|
25434
25438
|
},
|
|
25435
25439
|
kill: (pid, signal) => process.kill(pid, signal),
|
|
25436
|
-
portFree: (port) => new Promise((
|
|
25440
|
+
portFree: (port) => new Promise((resolve65) => {
|
|
25437
25441
|
const s2 = createServer2();
|
|
25438
|
-
s2.once("error", () =>
|
|
25439
|
-
s2.listen(port, "127.0.0.1", () => s2.close(() =>
|
|
25442
|
+
s2.once("error", () => resolve65(false));
|
|
25443
|
+
s2.listen(port, "127.0.0.1", () => s2.close(() => resolve65(true)));
|
|
25440
25444
|
}),
|
|
25441
25445
|
sleep: (ms2) => new Promise((r2) => setTimeout(r2, ms2)),
|
|
25442
25446
|
servingIdentity: async (origin) => {
|
|
@@ -29427,7 +29431,7 @@ async function injectRequest(listener, request) {
|
|
|
29427
29431
|
req.headers.host ??= url.host;
|
|
29428
29432
|
if (body && body.length > 0) req.push(body);
|
|
29429
29433
|
req.push(null);
|
|
29430
|
-
return await new Promise((
|
|
29434
|
+
return await new Promise((resolve65, reject) => {
|
|
29431
29435
|
const streamed = () => {
|
|
29432
29436
|
queueMicrotask(() => {
|
|
29433
29437
|
req.emit("close");
|
|
@@ -29443,7 +29447,7 @@ async function injectRequest(listener, request) {
|
|
|
29443
29447
|
else headers2.set(name, value);
|
|
29444
29448
|
}
|
|
29445
29449
|
const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
|
|
29446
|
-
|
|
29450
|
+
resolve65(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
|
|
29447
29451
|
}, streamed);
|
|
29448
29452
|
res.on("inject-error", reject);
|
|
29449
29453
|
try {
|
|
@@ -35580,12 +35584,12 @@ function finalizeRecording(key2, rec) {
|
|
|
35580
35584
|
if (rec.finalize) return rec.finalize;
|
|
35581
35585
|
rec.finalize = (async () => {
|
|
35582
35586
|
clearTimeout(rec.autoStop);
|
|
35583
|
-
await new Promise((
|
|
35587
|
+
await new Promise((resolve65) => {
|
|
35584
35588
|
let done = false;
|
|
35585
35589
|
const finish2 = () => {
|
|
35586
35590
|
if (!done) {
|
|
35587
35591
|
done = true;
|
|
35588
|
-
|
|
35592
|
+
resolve65();
|
|
35589
35593
|
}
|
|
35590
35594
|
};
|
|
35591
35595
|
rec.child.once("close", finish2);
|
|
@@ -35696,7 +35700,7 @@ var init_preview2 = __esm({
|
|
|
35696
35700
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
35697
35701
|
defaultRunner2 = {
|
|
35698
35702
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
35699
|
-
return new Promise((
|
|
35703
|
+
return new Promise((resolve65, reject) => {
|
|
35700
35704
|
const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
35701
35705
|
const out2 = [];
|
|
35702
35706
|
const err = [];
|
|
@@ -35718,7 +35722,7 @@ var init_preview2 = __esm({
|
|
|
35718
35722
|
child.stderr.on("data", (b2) => err.push(b2));
|
|
35719
35723
|
child.on("error", (e2) => settle(reject, e2));
|
|
35720
35724
|
child.on("close", (code) => {
|
|
35721
|
-
if (code === 0) settle(
|
|
35725
|
+
if (code === 0) settle(resolve65, Buffer.concat(out2));
|
|
35722
35726
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
35723
35727
|
});
|
|
35724
35728
|
});
|
|
@@ -38031,12 +38035,12 @@ function createRicosHostSession(o2) {
|
|
|
38031
38035
|
flush() {
|
|
38032
38036
|
if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
|
|
38033
38037
|
const requestId2 = newId();
|
|
38034
|
-
return new Promise((
|
|
38038
|
+
return new Promise((resolve65) => {
|
|
38035
38039
|
const timer = t2.setTimeout(() => {
|
|
38036
38040
|
flushes.delete(requestId2);
|
|
38037
|
-
|
|
38041
|
+
resolve65(null);
|
|
38038
38042
|
}, flushMs);
|
|
38039
|
-
flushes.set(requestId2, { resolve:
|
|
38043
|
+
flushes.set(requestId2, { resolve: resolve65, timer });
|
|
38040
38044
|
o2.send({ v: 1, type: "requestContent", requestId: requestId2 });
|
|
38041
38045
|
});
|
|
38042
38046
|
},
|
|
@@ -38095,7 +38099,7 @@ async function runRicosImageUpload(o2) {
|
|
|
38095
38099
|
};
|
|
38096
38100
|
session.insertMediaPlaceholder(requestId2);
|
|
38097
38101
|
try {
|
|
38098
|
-
const entry = await new Promise((
|
|
38102
|
+
const entry = await new Promise((resolve65) => {
|
|
38099
38103
|
let done = false;
|
|
38100
38104
|
let unsub = () => {
|
|
38101
38105
|
};
|
|
@@ -38104,7 +38108,7 @@ async function runRicosImageUpload(o2) {
|
|
|
38104
38108
|
done = true;
|
|
38105
38109
|
t2.clearTimeout(timer);
|
|
38106
38110
|
queueMicrotask(() => unsub());
|
|
38107
|
-
|
|
38111
|
+
resolve65(v2);
|
|
38108
38112
|
};
|
|
38109
38113
|
const timer = t2.setTimeout(() => finish2(null), o2.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
|
|
38110
38114
|
unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v2) => {
|
|
@@ -38626,10 +38630,10 @@ async function runMediaFieldUpload(o2) {
|
|
|
38626
38630
|
}, o2.timeoutMs ?? MEDIA_FIELD_UPLOAD_TIMEOUT_MS);
|
|
38627
38631
|
const bounded2 = (p2) => {
|
|
38628
38632
|
if (expired) return Promise.reject(new Deadline());
|
|
38629
|
-
return new Promise((
|
|
38633
|
+
return new Promise((resolve65, reject) => {
|
|
38630
38634
|
const stop = () => reject(new Deadline());
|
|
38631
38635
|
onExpire.push(stop);
|
|
38632
|
-
p2.then(
|
|
38636
|
+
p2.then(resolve65, reject).finally(() => {
|
|
38633
38637
|
onExpire = onExpire.filter((f2) => f2 !== stop);
|
|
38634
38638
|
});
|
|
38635
38639
|
});
|
|
@@ -38652,7 +38656,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38652
38656
|
const before = deps.value(urlPath);
|
|
38653
38657
|
let uploadUrl;
|
|
38654
38658
|
try {
|
|
38655
|
-
uploadUrl = await bounded2(new Promise((
|
|
38659
|
+
uploadUrl = await bounded2(new Promise((resolve65, reject) => {
|
|
38656
38660
|
let done = false;
|
|
38657
38661
|
let unsub = () => {
|
|
38658
38662
|
};
|
|
@@ -38660,7 +38664,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38660
38664
|
if (done || typeof v2 !== "string" || v2 === "" || v2 === before) return;
|
|
38661
38665
|
done = true;
|
|
38662
38666
|
queueMicrotask(() => unsub());
|
|
38663
|
-
|
|
38667
|
+
resolve65(v2);
|
|
38664
38668
|
});
|
|
38665
38669
|
onExpire.push(() => {
|
|
38666
38670
|
if (!done) {
|
|
@@ -38675,7 +38679,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38675
38679
|
if (typeof now === "string" && now !== "" && now !== before) {
|
|
38676
38680
|
done = true;
|
|
38677
38681
|
queueMicrotask(() => unsub());
|
|
38678
|
-
|
|
38682
|
+
resolve65(now);
|
|
38679
38683
|
return;
|
|
38680
38684
|
}
|
|
38681
38685
|
}
|
|
@@ -39121,7 +39125,7 @@ var init_controls = __esm({
|
|
|
39121
39125
|
}, [selectedId]);
|
|
39122
39126
|
const current = local != null && tabs.some((t2) => t2.id === local) ? local : selectedId;
|
|
39123
39127
|
const selIdx = Math.max(0, tabs.findIndex((t2) => t2.id === (current ?? tabs[0]?.id)));
|
|
39124
|
-
const
|
|
39128
|
+
const select2 = (i2) => {
|
|
39125
39129
|
if (pages2) setLocal(tabs[i2]?.id);
|
|
39126
39130
|
const act = actOf(tabs[i2], props.onChange ?? props.onSelect);
|
|
39127
39131
|
if (ctx.onAction && act) ctx.onAction(withSelection(act, { selectedId: String(tabs[i2]?.id ?? i2) }));
|
|
@@ -39134,7 +39138,7 @@ var init_controls = __esm({
|
|
|
39134
39138
|
else if (e2.key === "End") ni2 = tabs.length - 1;
|
|
39135
39139
|
else return;
|
|
39136
39140
|
e2.preventDefault();
|
|
39137
|
-
if (ni2 !== selIdx)
|
|
39141
|
+
if (ni2 !== selIdx) select2(ni2);
|
|
39138
39142
|
};
|
|
39139
39143
|
const pagerRef = React5.useRef(null);
|
|
39140
39144
|
const settle = React5.useRef(void 0);
|
|
@@ -39151,7 +39155,7 @@ var init_controls = __esm({
|
|
|
39151
39155
|
const el2 = pagerRef.current;
|
|
39152
39156
|
if (!el2 || !el2.clientWidth) return;
|
|
39153
39157
|
const i2 = Math.round(el2.scrollLeft / el2.clientWidth);
|
|
39154
|
-
if (i2 >= 0 && i2 < tabs.length && i2 !== selIdx)
|
|
39158
|
+
if (i2 >= 0 && i2 < tabs.length && i2 !== selIdx) select2(i2);
|
|
39155
39159
|
}, 120);
|
|
39156
39160
|
};
|
|
39157
39161
|
const accent = C2("accentPrimary", "#116DFF");
|
|
@@ -39166,7 +39170,7 @@ var init_controls = __esm({
|
|
|
39166
39170
|
role: "tab",
|
|
39167
39171
|
"aria-selected": on4,
|
|
39168
39172
|
tabIndex: on4 ? 0 : -1,
|
|
39169
|
-
onClick: () =>
|
|
39173
|
+
onClick: () => select2(i2),
|
|
39170
39174
|
style: { all: "unset", display: "flex", gap: 6, alignItems: "center", minWidth: 44, minHeight: 44, padding: "10px 0", fontFamily: FONT(ctx), fontWeight: 600, fontSize: pxToRem(14), cursor: "pointer", color: on4 ? activeLabel : C2("textSecondary", "#777"), borderBottom: on4 ? `2px solid ${activeTint}` : "2px solid transparent", marginBottom: -1 },
|
|
39171
39175
|
children: [
|
|
39172
39176
|
asText2(t2.label),
|
|
@@ -39209,7 +39213,7 @@ var init_controls = __esm({
|
|
|
39209
39213
|
const awaitingBinding = isBinding(props.selectedId) && resolvedSel == null;
|
|
39210
39214
|
const selId = ctx.empty || awaitingBinding ? null : resolvedSel ?? opts[0]?.id;
|
|
39211
39215
|
const selIdx = Math.max(0, opts.findIndex((o2) => o2.id === selId));
|
|
39212
|
-
const
|
|
39216
|
+
const select2 = (i2) => {
|
|
39213
39217
|
const act = actOf(opts[i2], props.onChange ?? props.onSelect);
|
|
39214
39218
|
if (ctx.onAction && act) ctx.onAction(withSelection(act, { selectedId: String(opts[i2]?.id ?? i2) }));
|
|
39215
39219
|
};
|
|
@@ -39219,7 +39223,7 @@ var init_controls = __esm({
|
|
|
39219
39223
|
else if (e2.key === "ArrowLeft" || e2.key === "ArrowUp") ni2 = (selIdx - 1 + opts.length) % opts.length;
|
|
39220
39224
|
else return;
|
|
39221
39225
|
e2.preventDefault();
|
|
39222
|
-
if (ni2 !== selIdx)
|
|
39226
|
+
if (ni2 !== selIdx) select2(ni2);
|
|
39223
39227
|
};
|
|
39224
39228
|
return /* @__PURE__ */ jsx6("div", { role: "radiogroup", onKeyDown, style: { display: "flex", background: seg.outlined ? "transparent" : C2("surfaceTertiary", "#eee"), borderRadius: radius(seg.trackRadius, "md", 8), padding: seg.trackPadding, width: "100%", boxSizing: "border-box", ...wrap }, children: opts.map((o2, i2) => {
|
|
39225
39229
|
const on4 = o2.id === selId;
|
|
@@ -39236,7 +39240,7 @@ var init_controls = __esm({
|
|
|
39236
39240
|
role: "radio",
|
|
39237
39241
|
"aria-checked": on4,
|
|
39238
39242
|
tabIndex: on4 || selId == null && i2 === 0 ? 0 : -1,
|
|
39239
|
-
onClick: () =>
|
|
39243
|
+
onClick: () => select2(i2),
|
|
39240
39244
|
style: { all: "unset", flex: 1, minWidth: 44, minHeight: seg.height - 2 * seg.trackPadding, textAlign: "center", padding: "7px 4px", borderRadius: outerR, fontFamily: FONT(ctx), fontWeight: 600, fontSize: pxToRem(13), cursor: "pointer", boxSizing: "border-box", background: on4 ? C2("surfacePrimary", "#fff") : seg.outlined ? C2(pickRole(ctx.tokens.colors, seg.roles.inactive), "#eee") : "transparent", color: on4 ? C2("textPrimary", "#111") : C2("textSecondary", "#777"), boxShadow: on4 && !seg.outlined ? "0 1px 3px rgba(0,0,0,.12)" : "none", ...outlinedShape },
|
|
39241
39245
|
children: [
|
|
39242
39246
|
on4 && seg.selectedCheck ? /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u2713 " }) : null,
|
|
@@ -40824,7 +40828,7 @@ async function fetchData(url, type = "text") {
|
|
|
40824
40828
|
}
|
|
40825
40829
|
return response.text();
|
|
40826
40830
|
}
|
|
40827
|
-
return new Promise((
|
|
40831
|
+
return new Promise((resolve65, reject) => {
|
|
40828
40832
|
const request = new XMLHttpRequest();
|
|
40829
40833
|
request.open("GET", url, true);
|
|
40830
40834
|
request.responseType = type === "bytes" ? "arraybuffer" : type;
|
|
@@ -40835,14 +40839,14 @@ async function fetchData(url, type = "text") {
|
|
|
40835
40839
|
if (request.status === 200 || request.status === 0) {
|
|
40836
40840
|
switch (type) {
|
|
40837
40841
|
case "bytes":
|
|
40838
|
-
|
|
40842
|
+
resolve65(new Uint8Array(request.response));
|
|
40839
40843
|
return;
|
|
40840
40844
|
case "blob":
|
|
40841
40845
|
case "json":
|
|
40842
|
-
|
|
40846
|
+
resolve65(request.response);
|
|
40843
40847
|
return;
|
|
40844
40848
|
}
|
|
40845
|
-
|
|
40849
|
+
resolve65(request.responseText);
|
|
40846
40850
|
return;
|
|
40847
40851
|
}
|
|
40848
40852
|
reject(new Error(request.statusText));
|
|
@@ -43774,7 +43778,7 @@ var init_pdf = __esm({
|
|
|
43774
43778
|
var defineProperty = Object.defineProperty;
|
|
43775
43779
|
var stringSlice = uncurryThis("".slice);
|
|
43776
43780
|
var replace = uncurryThis("".replace);
|
|
43777
|
-
var
|
|
43781
|
+
var join88 = uncurryThis([].join);
|
|
43778
43782
|
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
|
|
43779
43783
|
return defineProperty(function() {
|
|
43780
43784
|
}, "length", { value: 8 }).length !== 8;
|
|
@@ -43801,7 +43805,7 @@ var init_pdf = __esm({
|
|
|
43801
43805
|
}
|
|
43802
43806
|
var state = enforceInternalState(value);
|
|
43803
43807
|
if (!hasOwn(state, "source")) {
|
|
43804
|
-
state.source =
|
|
43808
|
+
state.source = join88(TEMPLATE, typeof name == "string" ? name : "");
|
|
43805
43809
|
}
|
|
43806
43810
|
return value;
|
|
43807
43811
|
};
|
|
@@ -43846,13 +43850,13 @@ var init_pdf = __esm({
|
|
|
43846
43850
|
var aCallable = __webpack_require__3(9306);
|
|
43847
43851
|
var $TypeError = TypeError;
|
|
43848
43852
|
var PromiseCapability = function(C2) {
|
|
43849
|
-
var
|
|
43853
|
+
var resolve65, reject;
|
|
43850
43854
|
this.promise = new C2(function($$resolve, $$reject) {
|
|
43851
|
-
if (
|
|
43852
|
-
|
|
43855
|
+
if (resolve65 !== void 0 || reject !== void 0) throw new $TypeError("Bad Promise constructor");
|
|
43856
|
+
resolve65 = $$resolve;
|
|
43853
43857
|
reject = $$reject;
|
|
43854
43858
|
});
|
|
43855
|
-
this.resolve = aCallable(
|
|
43859
|
+
this.resolve = aCallable(resolve65);
|
|
43856
43860
|
this.reject = aCallable(reject);
|
|
43857
43861
|
};
|
|
43858
43862
|
module.exports.f = function(C2) {
|
|
@@ -44220,8 +44224,8 @@ var init_pdf = __esm({
|
|
|
44220
44224
|
anObject(C2);
|
|
44221
44225
|
if (isObject3(x2) && x2.constructor === C2) return x2;
|
|
44222
44226
|
var promiseCapability = newPromiseCapability.f(C2);
|
|
44223
|
-
var
|
|
44224
|
-
|
|
44227
|
+
var resolve65 = promiseCapability.resolve;
|
|
44228
|
+
resolve65(x2);
|
|
44225
44229
|
return promiseCapability.promise;
|
|
44226
44230
|
};
|
|
44227
44231
|
},
|
|
@@ -46324,7 +46328,7 @@ var init_pdf = __esm({
|
|
|
46324
46328
|
var charAt = uncurryThis("".charAt);
|
|
46325
46329
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
46326
46330
|
var $Array = globalThis2.Array;
|
|
46327
|
-
var
|
|
46331
|
+
var join88 = uncurryThis([].join);
|
|
46328
46332
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
|
|
46329
46333
|
try {
|
|
46330
46334
|
var target = new Uint8Array2();
|
|
@@ -46370,7 +46374,7 @@ var init_pdf = __esm({
|
|
|
46370
46374
|
result[written++] = "=";
|
|
46371
46375
|
}
|
|
46372
46376
|
}
|
|
46373
|
-
return
|
|
46377
|
+
return join88(result, "");
|
|
46374
46378
|
}
|
|
46375
46379
|
});
|
|
46376
46380
|
},
|
|
@@ -46382,7 +46386,7 @@ var init_pdf = __esm({
|
|
|
46382
46386
|
var anUint8Array = __webpack_require__3(4154);
|
|
46383
46387
|
var notDetached = __webpack_require__3(5169);
|
|
46384
46388
|
var numberToString2 = uncurryThis(1.1.toString);
|
|
46385
|
-
var
|
|
46389
|
+
var join88 = uncurryThis([].join);
|
|
46386
46390
|
var $Array = Array;
|
|
46387
46391
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
46388
46392
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
|
|
@@ -46402,7 +46406,7 @@ var init_pdf = __esm({
|
|
|
46402
46406
|
var hex2 = numberToString2(this[i2], 16);
|
|
46403
46407
|
result[i2] = hex2.length === 1 ? "0" + hex2 : hex2;
|
|
46404
46408
|
}
|
|
46405
|
-
return
|
|
46409
|
+
return join88(result, "");
|
|
46406
46410
|
}
|
|
46407
46411
|
});
|
|
46408
46412
|
},
|
|
@@ -48075,11 +48079,11 @@ var init_pdf = __esm({
|
|
|
48075
48079
|
const mustRemoveAspectRatioPromise = _ImageManager._isSVGFittingCanvas;
|
|
48076
48080
|
const fileReader = new FileReader();
|
|
48077
48081
|
const imageElement = new Image();
|
|
48078
|
-
const imagePromise = new Promise((
|
|
48082
|
+
const imagePromise = new Promise((resolve65, reject) => {
|
|
48079
48083
|
imageElement.onload = () => {
|
|
48080
48084
|
data.bitmap = imageElement;
|
|
48081
48085
|
data.isSvg = true;
|
|
48082
|
-
|
|
48086
|
+
resolve65();
|
|
48083
48087
|
};
|
|
48084
48088
|
fileReader.onload = async () => {
|
|
48085
48089
|
const url = data.svgUrl = fileReader.result;
|
|
@@ -48765,13 +48769,13 @@ var init_pdf = __esm({
|
|
|
48765
48769
|
return;
|
|
48766
48770
|
}
|
|
48767
48771
|
const {
|
|
48768
|
-
resolve:
|
|
48772
|
+
resolve: resolve65,
|
|
48769
48773
|
promise
|
|
48770
48774
|
} = Promise.withResolvers();
|
|
48771
48775
|
const onEditorsRendered = (evt) => {
|
|
48772
48776
|
if (evt.pageNumber === pageNumber) {
|
|
48773
48777
|
this._eventBus.off("editorsrendered", onEditorsRendered);
|
|
48774
|
-
|
|
48778
|
+
resolve65();
|
|
48775
48779
|
}
|
|
48776
48780
|
};
|
|
48777
48781
|
this._eventBus.on("editorsrendered", onEditorsRendered, internalOpt);
|
|
@@ -53809,8 +53813,8 @@ var init_pdf = __esm({
|
|
|
53809
53813
|
if (this.isSyncFontLoadingSupported) {
|
|
53810
53814
|
return;
|
|
53811
53815
|
}
|
|
53812
|
-
await new Promise((
|
|
53813
|
-
const request = this._queueLoadingCallback(
|
|
53816
|
+
await new Promise((resolve65) => {
|
|
53817
|
+
const request = this._queueLoadingCallback(resolve65);
|
|
53814
53818
|
this._prepareFontLoadEvent(font, request);
|
|
53815
53819
|
});
|
|
53816
53820
|
}
|
|
@@ -70850,7 +70854,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
70850
70854
|
input.type = "file";
|
|
70851
70855
|
input.accept = SupportedImageMimeTypes.join(",");
|
|
70852
70856
|
const signal = this._uiManager._signal;
|
|
70853
|
-
this.#bitmapPromise = new Promise((
|
|
70857
|
+
this.#bitmapPromise = new Promise((resolve65) => {
|
|
70854
70858
|
input.addEventListener("change", async () => {
|
|
70855
70859
|
if (!input.files || input.files.length === 0) {
|
|
70856
70860
|
this.remove();
|
|
@@ -70865,13 +70869,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
70865
70869
|
});
|
|
70866
70870
|
this.#getBitmapFetched(data);
|
|
70867
70871
|
}
|
|
70868
|
-
|
|
70872
|
+
resolve65();
|
|
70869
70873
|
}, {
|
|
70870
70874
|
signal
|
|
70871
70875
|
});
|
|
70872
70876
|
input.addEventListener("cancel", () => {
|
|
70873
70877
|
this.remove();
|
|
70874
|
-
|
|
70878
|
+
resolve65();
|
|
70875
70879
|
}, {
|
|
70876
70880
|
signal
|
|
70877
70881
|
});
|
|
@@ -125161,7 +125165,7 @@ var init_renderNode = __esm({
|
|
|
125161
125165
|
media.currentTime = Math.max(0, Math.min(seconds, Number.isFinite(media.duration) ? media.duration : seconds));
|
|
125162
125166
|
setPosition(media.currentTime);
|
|
125163
125167
|
}, []);
|
|
125164
|
-
const
|
|
125168
|
+
const select2 = React9.useCallback((next) => {
|
|
125165
125169
|
if (resolvedItems.length === 0) return;
|
|
125166
125170
|
const normalized = (next % resolvedItems.length + resolvedItems.length) % resolvedItems.length;
|
|
125167
125171
|
const nextItem = resolvedItems[normalized];
|
|
@@ -125212,10 +125216,10 @@ var init_renderNode = __esm({
|
|
|
125212
125216
|
seek(Number(detail.value ?? 0));
|
|
125213
125217
|
break;
|
|
125214
125218
|
case "next":
|
|
125215
|
-
|
|
125219
|
+
select2(index + 1);
|
|
125216
125220
|
break;
|
|
125217
125221
|
case "previous":
|
|
125218
|
-
|
|
125222
|
+
select2(index - 1);
|
|
125219
125223
|
break;
|
|
125220
125224
|
case "setRate": {
|
|
125221
125225
|
const next = Number(detail.value ?? 1);
|
|
@@ -125240,7 +125244,7 @@ var init_renderNode = __esm({
|
|
|
125240
125244
|
};
|
|
125241
125245
|
window.addEventListener("himalaya-media-command", listener);
|
|
125242
125246
|
return () => window.removeEventListener("himalaya-media-command", listener);
|
|
125243
|
-
}, [sessionId, index, play, pause, seek,
|
|
125247
|
+
}, [sessionId, index, play, pause, seek, select2, toggleFullscreen]);
|
|
125244
125248
|
React9.useEffect(() => {
|
|
125245
125249
|
const listener = () => {
|
|
125246
125250
|
const value = document.fullscreenElement === hostRef.current;
|
|
@@ -125296,10 +125300,10 @@ var init_renderNode = __esm({
|
|
|
125296
125300
|
seek(Number(raw.seconds ?? raw.positionSeconds ?? 0));
|
|
125297
125301
|
return;
|
|
125298
125302
|
case "media.next":
|
|
125299
|
-
|
|
125303
|
+
select2(index + 1);
|
|
125300
125304
|
return;
|
|
125301
125305
|
case "media.previous":
|
|
125302
|
-
|
|
125306
|
+
select2(index - 1);
|
|
125303
125307
|
return;
|
|
125304
125308
|
case "media.fullscreen":
|
|
125305
125309
|
void toggleFullscreen();
|
|
@@ -125342,14 +125346,14 @@ var init_renderNode = __esm({
|
|
|
125342
125346
|
return `${Math.floor(safe / 60)}:${String(Math.floor(safe % 60)).padStart(2, "0")}`;
|
|
125343
125347
|
};
|
|
125344
125348
|
const builtInControls = /* @__PURE__ */ jsxs7("div", { "data-media-controls": "builtIn", style: { display: "grid", gridTemplateColumns: "auto auto 1fr auto auto", gap: 10, alignItems: "center", width: "100%", padding: "10px 12px", boxSizing: "border-box", color: foreground, background: "linear-gradient(transparent,rgba(0,0,0,.82))" }, children: [
|
|
125345
|
-
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Previous", onClick: () =>
|
|
125349
|
+
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Previous", onClick: () => select2(index - 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25C0\u25C0" }),
|
|
125346
125350
|
/* @__PURE__ */ jsx10("button", { "aria-label": status === "playing" ? "Pause" : "Play", onClick: () => status === "playing" ? pause() : void play(), style: { width: 38, height: 38, borderRadius: "50%", color: background, background: foreground, border: 0, fontSize: 18 }, children: status === "playing" ? "\u275A\u275A" : "\u25B6" }),
|
|
125347
125351
|
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [
|
|
125348
125352
|
/* @__PURE__ */ jsx10("span", { style: { fontSize: pxToRem(11), whiteSpace: "nowrap" }, children: time(position) }),
|
|
125349
125353
|
/* @__PURE__ */ jsx10("input", { "aria-label": "Media position", type: "range", min: 0, max: Math.max(duration2, 1), step: 0.1, value: Math.min(position, Math.max(duration2, 1)), onChange: (event) => seek(Number(event.currentTarget.value)), style: { width: "100%", accentColor: accent } }),
|
|
125350
125354
|
/* @__PURE__ */ jsx10("span", { style: { fontSize: pxToRem(11), whiteSpace: "nowrap" }, children: time(duration2) })
|
|
125351
125355
|
] }),
|
|
125352
|
-
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Next", onClick: () =>
|
|
125356
|
+
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Next", onClick: () => select2(index + 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25B6\u25B6" }),
|
|
125353
125357
|
props.fullscreen !== "disabled" && /* @__PURE__ */ jsx10("button", { "aria-label": "Fullscreen", onClick: () => void toggleFullscreen(), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u26F6" })
|
|
125354
125358
|
] });
|
|
125355
125359
|
const customControls = chrome === "custom" ? slot("controls") : null;
|
|
@@ -125391,7 +125395,7 @@ var init_renderNode = __esm({
|
|
|
125391
125395
|
return;
|
|
125392
125396
|
}
|
|
125393
125397
|
if (props.loop === "all" || index + 1 < items.length) {
|
|
125394
|
-
|
|
125398
|
+
select2(index + 1);
|
|
125395
125399
|
return;
|
|
125396
125400
|
}
|
|
125397
125401
|
setStatus("ended");
|
|
@@ -127707,7 +127711,7 @@ var init_renderNode = __esm({
|
|
|
127707
127711
|
const currentRef = React9.useRef(current);
|
|
127708
127712
|
const itemsPath = props.itemsPath ?? props.items_path;
|
|
127709
127713
|
const boundRail = !!itemsPath && !!items[0] && !!ctx.provider;
|
|
127710
|
-
const
|
|
127714
|
+
const select2 = (index) => {
|
|
127711
127715
|
if (index === currentRef.current) return;
|
|
127712
127716
|
currentRef.current = index;
|
|
127713
127717
|
setCurrent(index);
|
|
@@ -127724,7 +127728,7 @@ var init_renderNode = __esm({
|
|
|
127724
127728
|
const timer = setInterval(() => {
|
|
127725
127729
|
const next = (currentRef.current + 1) % pages2.length;
|
|
127726
127730
|
if (rail.current) rail.current.scrollLeft = next * rail.current.clientWidth;
|
|
127727
|
-
|
|
127731
|
+
select2(next);
|
|
127728
127732
|
}, interval);
|
|
127729
127733
|
return () => clearInterval(timer);
|
|
127730
127734
|
}, [props.autoplayIntervalMs, props.__pager, boundRail, pages2.length, props.onChange, ctx]);
|
|
@@ -127741,10 +127745,10 @@ var init_renderNode = __esm({
|
|
|
127741
127745
|
event.preventDefault();
|
|
127742
127746
|
const index = event.key === "Home" ? 0 : event.key === "End" ? pages2.length - 1 : Math.max(0, Math.min(pages2.length - 1, currentRef.current + (event.key === "ArrowRight" ? 1 : -1)));
|
|
127743
127747
|
if (rail.current) rail.current.scrollLeft = index * rail.current.clientWidth;
|
|
127744
|
-
|
|
127748
|
+
select2(index);
|
|
127745
127749
|
},
|
|
127746
127750
|
onScroll: (event) => {
|
|
127747
|
-
if (!boundRail && event.currentTarget.clientWidth > 0)
|
|
127751
|
+
if (!boundRail && event.currentTarget.clientWidth > 0) select2(Math.max(0, Math.min(pages2.length - 1, Math.round(event.currentTarget.scrollLeft / event.currentTarget.clientWidth))));
|
|
127748
127752
|
},
|
|
127749
127753
|
style: { display: "flex", overflowX: "auto", scrollSnapType: boundRail ? void 0 : "x mandatory", gap: boundRail ? 12 : void 0, width: "100%" },
|
|
127750
127754
|
children: boundRail ? /* @__PURE__ */ jsx10(BoundList, { ctx, itemsPath, template: items[0], renderRow: (template, itemCtx) => /* @__PURE__ */ jsx10("div", { style: { flex: "0 0 auto" }, children: renderNode(template, itemCtx) }) }) : pages2.map((page, index) => /* @__PURE__ */ jsx10("div", { style: { minWidth: "100%", scrollSnapAlign: "start" }, children: renderNode(page, ctx) }, page?.id ?? index))
|
|
@@ -129145,13 +129149,13 @@ __export(render_descriptor_exports, {
|
|
|
129145
129149
|
stabilizePngPage: () => stabilizePngPage,
|
|
129146
129150
|
withRetry: () => withRetry2
|
|
129147
129151
|
});
|
|
129148
|
-
function a11ySemantics(type, props, modifiers, ancestorHidden,
|
|
129152
|
+
function a11ySemantics(type, props, modifiers, ancestorHidden, resolve65) {
|
|
129149
129153
|
if (!A11Y_MODIFIER_KEYS.some((k2) => modifiers[k2] !== void 0)) return void 0;
|
|
129150
129154
|
const literal = (v2) => typeof v2 === "string" && v2.trim() !== "" && !isDynamicValue(v2) ? v2 : void 0;
|
|
129151
129155
|
const spoken = (v2) => {
|
|
129152
129156
|
const lit = literal(v2);
|
|
129153
|
-
if (lit !== void 0 || !
|
|
129154
|
-
const r2 =
|
|
129157
|
+
if (lit !== void 0 || !resolve65 || typeof v2 !== "string" || !isDynamicValue(v2)) return lit;
|
|
129158
|
+
const r2 = resolve65(v2);
|
|
129155
129159
|
if (r2 === v2) return void 0;
|
|
129156
129160
|
return typeof r2 === "string" && r2.trim() !== "" ? r2 : typeof r2 === "number" ? String(r2) : void 0;
|
|
129157
129161
|
};
|
|
@@ -129165,7 +129169,7 @@ function a11ySemantics(type, props, modifiers, ancestorHidden, resolve63) {
|
|
|
129165
129169
|
if (name !== void 0 && exposure === "exposed") out2.name = name;
|
|
129166
129170
|
const hint = spoken(modifiers.accessibilityHint);
|
|
129167
129171
|
if (hint !== void 0) out2.hint = hint;
|
|
129168
|
-
const value = spoken(modifiers.accessibilityValue) ?? controlState(role, props,
|
|
129172
|
+
const value = spoken(modifiers.accessibilityValue) ?? controlState(role, props, resolve65);
|
|
129169
129173
|
if (value !== void 0) out2.value = value;
|
|
129170
129174
|
if (typeof modifiers.headingLevel === "number") out2.headingLevel = modifiers.headingLevel;
|
|
129171
129175
|
if (exposure !== "exposed") out2.exposure = exposure;
|
|
@@ -129186,13 +129190,13 @@ function a11ySemantics(type, props, modifiers, ancestorHidden, resolve63) {
|
|
|
129186
129190
|
}
|
|
129187
129191
|
return out2;
|
|
129188
129192
|
}
|
|
129189
|
-
function controlState(role, props,
|
|
129193
|
+
function controlState(role, props, resolve65) {
|
|
129190
129194
|
if (role !== "toggle" && role !== "checkbox" && role !== "radio") return void 0;
|
|
129191
129195
|
if (role === "checkbox" && props.indeterminate === true) return "mixed";
|
|
129192
129196
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && isDynamicValue(props.value) ? props.value : void 0;
|
|
129193
129197
|
let on4;
|
|
129194
129198
|
if (binding2 !== void 0) {
|
|
129195
|
-
const v2 =
|
|
129199
|
+
const v2 = resolve65 ? resolve65(binding2) : void 0;
|
|
129196
129200
|
if (v2 === true || v2 === 1 || v2 === "true" || v2 === "1") on4 = true;
|
|
129197
129201
|
else if (v2 === false || v2 === 0 || v2 === "false" || v2 === "0") on4 = false;
|
|
129198
129202
|
else return void 0;
|
|
@@ -129522,7 +129526,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
129522
129526
|
const browser = globalThis;
|
|
129523
129527
|
browser.document.documentElement.style.colorScheme = selected;
|
|
129524
129528
|
await browser.document.fonts?.ready;
|
|
129525
|
-
await new Promise((
|
|
129529
|
+
await new Promise((resolve65) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve65())));
|
|
129526
129530
|
}, scheme);
|
|
129527
129531
|
}
|
|
129528
129532
|
async function renderPngBatch(items) {
|
|
@@ -132143,7 +132147,7 @@ async function handleWebWix(req, res, state) {
|
|
|
132143
132147
|
}
|
|
132144
132148
|
if (match) {
|
|
132145
132149
|
const mocked = match.rule.response;
|
|
132146
|
-
if (mocked.delayMs) await new Promise((
|
|
132150
|
+
if (mocked.delayMs) await new Promise((resolve65) => setTimeout(resolve65, mocked.delayMs));
|
|
132147
132151
|
const payload = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
132148
132152
|
recordStream("mock", mocked.status, match.rule.id, mocked.headers);
|
|
132149
132153
|
res.statusCode = mocked.status;
|
|
@@ -132208,14 +132212,14 @@ async function handleWebWix(req, res, state) {
|
|
|
132208
132212
|
const chunk = await reader.read();
|
|
132209
132213
|
if (chunk.done) break;
|
|
132210
132214
|
if (chunk.value && !res.write(chunk.value)) {
|
|
132211
|
-
await new Promise((
|
|
132215
|
+
await new Promise((resolve65) => {
|
|
132212
132216
|
let settled = false;
|
|
132213
132217
|
const finish2 = () => {
|
|
132214
132218
|
if (settled) return;
|
|
132215
132219
|
settled = true;
|
|
132216
132220
|
res.off("drain", finish2);
|
|
132217
132221
|
res.off("close", finish2);
|
|
132218
|
-
|
|
132222
|
+
resolve65();
|
|
132219
132223
|
};
|
|
132220
132224
|
if (res.destroyed || !res.writable) finish2();
|
|
132221
132225
|
else {
|
|
@@ -132370,7 +132374,7 @@ async function handleWebWix(req, res, state) {
|
|
|
132370
132374
|
}
|
|
132371
132375
|
if (match) {
|
|
132372
132376
|
const mocked = match.rule.response;
|
|
132373
|
-
if (mocked.delayMs) await new Promise((
|
|
132377
|
+
if (mocked.delayMs) await new Promise((resolve65) => setTimeout(resolve65, mocked.delayMs));
|
|
132374
132378
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
132375
132379
|
record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
|
|
132376
132380
|
return reply(200, { status: mocked.status, body: responseBody ?? "" });
|
|
@@ -133409,8 +133413,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
133409
133413
|
}
|
|
133410
133414
|
async function serveStatic(req, res, root, prefix) {
|
|
133411
133415
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
133412
|
-
const
|
|
133413
|
-
const safe = normalize3(
|
|
133416
|
+
const relative17 = requested.replace(prefix, "").replace(/^\//, "");
|
|
133417
|
+
const safe = normalize3(relative17).replace(/^(\.\.[\/\\])+/, "");
|
|
133414
133418
|
const fullPath = resolve38(root, safe);
|
|
133415
133419
|
if (!fullPath.startsWith(root)) {
|
|
133416
133420
|
return send(res, 403, "forbidden");
|
|
@@ -134574,12 +134578,12 @@ var init_query = __esm({
|
|
|
134574
134578
|
});
|
|
134575
134579
|
|
|
134576
134580
|
// ../../core/dev-server/src/crawl-input.ts
|
|
134577
|
-
function resolved(v2,
|
|
134578
|
-
if (typeof v2 === "string") return v2.startsWith("$service:") ?
|
|
134581
|
+
function resolved(v2, resolve65) {
|
|
134582
|
+
if (typeof v2 === "string") return v2.startsWith("$service:") ? resolve65(v2) : v2;
|
|
134579
134583
|
if (Array.isArray(v2)) {
|
|
134580
134584
|
const out2 = v2.flatMap((el2) => {
|
|
134581
134585
|
if (typeof el2 !== "string" || !el2.startsWith("$service:")) return [el2];
|
|
134582
|
-
const r2 =
|
|
134586
|
+
const r2 = resolve65(el2);
|
|
134583
134587
|
return Array.isArray(r2) ? r2 : [r2];
|
|
134584
134588
|
});
|
|
134585
134589
|
return out2;
|
|
@@ -134593,9 +134597,9 @@ function hasRowBinding(props) {
|
|
|
134593
134597
|
return itemToken(v2) || Array.isArray(v2) && v2.some(itemToken);
|
|
134594
134598
|
});
|
|
134595
134599
|
}
|
|
134596
|
-
function declaredOptionIds(props,
|
|
134600
|
+
function declaredOptionIds(props, resolve65) {
|
|
134597
134601
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
134598
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
134602
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve65) : void 0;
|
|
134599
134603
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
134600
134604
|
if (!Array.isArray(raw)) return [];
|
|
134601
134605
|
const out2 = [];
|
|
@@ -134638,24 +134642,24 @@ function seedTokens(state, limit = 48) {
|
|
|
134638
134642
|
walk2(state, 0);
|
|
134639
134643
|
return out2;
|
|
134640
134644
|
}
|
|
134641
|
-
function synthesizeInput(control,
|
|
134645
|
+
function synthesizeInput(control, resolve65, tokens2) {
|
|
134642
134646
|
const id = `${control.type}.${control.callback}`;
|
|
134643
134647
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
134644
134648
|
if (!row) return null;
|
|
134645
134649
|
const props = control.props;
|
|
134646
134650
|
if (hasRowBinding(props)) return null;
|
|
134647
134651
|
if (row.from === "declared-options") {
|
|
134648
|
-
const ids = declaredOptionIds(props,
|
|
134652
|
+
const ids = declaredOptionIds(props, resolve65);
|
|
134649
134653
|
if (!ids.length) return null;
|
|
134650
134654
|
if (row.encoding === "string-array") {
|
|
134651
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
134655
|
+
const currentRaw2 = resolved(props.selectedIds, resolve65);
|
|
134652
134656
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x2) => typeof x2 === "string");
|
|
134653
134657
|
const pick4 = ids.find((o2) => !current3.includes(o2));
|
|
134654
134658
|
if (pick4 === void 0) return null;
|
|
134655
134659
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
134656
134660
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
134657
134661
|
}
|
|
134658
|
-
const currentRaw = resolved(props.selectedId,
|
|
134662
|
+
const currentRaw = resolved(props.selectedId, resolve65);
|
|
134659
134663
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
134660
134664
|
const pick3 = ids.find((o2) => o2 !== current2);
|
|
134661
134665
|
if (pick3 === void 0) return null;
|
|
@@ -134663,7 +134667,7 @@ function synthesizeInput(control, resolve63, tokens2) {
|
|
|
134663
134667
|
}
|
|
134664
134668
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
134665
134669
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
|
|
134666
|
-
const bound = binding2 === void 0 ? void 0 :
|
|
134670
|
+
const bound = binding2 === void 0 ? void 0 : resolve65(binding2);
|
|
134667
134671
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
134668
134672
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
134669
134673
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -137283,6 +137287,7 @@ __export(build_exports2, {
|
|
|
137283
137287
|
bundleNameFromUrl: () => bundleNameFromUrl,
|
|
137284
137288
|
collectComponentTypes: () => collectComponentTypes,
|
|
137285
137289
|
contentReleaseId: () => contentReleaseId,
|
|
137290
|
+
countingHostAnswers: () => countingHostAnswers,
|
|
137286
137291
|
countingWixCall: () => countingWixCall,
|
|
137287
137292
|
declaresHostProvidedIdentity: () => declaresHostProvidedIdentity,
|
|
137288
137293
|
gitSha: () => gitSha,
|
|
@@ -137656,17 +137661,39 @@ async function buildRelease(app, dest, opts = {}) {
|
|
|
137656
137661
|
}
|
|
137657
137662
|
function countingWixCall(base) {
|
|
137658
137663
|
let returned = 0;
|
|
137664
|
+
const failed3 = [];
|
|
137659
137665
|
return {
|
|
137660
137666
|
call: async (method, path2, body) => {
|
|
137661
|
-
|
|
137667
|
+
let out2;
|
|
137668
|
+
try {
|
|
137669
|
+
out2 = await base(method, path2, body);
|
|
137670
|
+
} catch (e2) {
|
|
137671
|
+
failed3.push(`${String(method).toUpperCase()} ${String(path2).split("?")[0]}`);
|
|
137672
|
+
throw e2;
|
|
137673
|
+
}
|
|
137662
137674
|
returned += 1;
|
|
137663
137675
|
return out2;
|
|
137664
137676
|
},
|
|
137665
|
-
returned: () => returned
|
|
137677
|
+
returned: () => returned,
|
|
137678
|
+
failed: () => [...failed3]
|
|
137679
|
+
};
|
|
137680
|
+
}
|
|
137681
|
+
function countingHostAnswers(host) {
|
|
137682
|
+
let answered = 0;
|
|
137683
|
+
const { wixCall } = host;
|
|
137684
|
+
if (!wixCall) return { host, answered: () => answered };
|
|
137685
|
+
return {
|
|
137686
|
+
host: { ...host, wixCall: (method, path2, body) => {
|
|
137687
|
+
const answer = wixCall(method, path2, body);
|
|
137688
|
+
if (answer !== void 0) answered += 1;
|
|
137689
|
+
return answer;
|
|
137690
|
+
} },
|
|
137691
|
+
answered: () => answered
|
|
137666
137692
|
};
|
|
137667
137693
|
}
|
|
137668
137694
|
async function liveRenderServices(bundleJs, opts) {
|
|
137669
|
-
const
|
|
137695
|
+
const declared = declaredCapabilitiesOf(opts.descriptor);
|
|
137696
|
+
const bus = withHostAnswers(hostDispatch(opts.localDbSchema, declared), declared, opts.host);
|
|
137670
137697
|
const appear = rootOnAppear(opts.descriptor);
|
|
137671
137698
|
const fired = appear ? parseWorkerAction(appear.actionId) : null;
|
|
137672
137699
|
if (fired) {
|
|
@@ -137689,16 +137716,46 @@ async function liveRenderServices(bundleJs, opts) {
|
|
|
137689
137716
|
}
|
|
137690
137717
|
}
|
|
137691
137718
|
}
|
|
137719
|
+
if (opts.host) await settleUnawaitedWork();
|
|
137692
137720
|
return { services: snapshot(w2).state, calls: w2.calls, errors: w2.errors };
|
|
137693
137721
|
} finally {
|
|
137694
137722
|
w2.dispose();
|
|
137695
137723
|
}
|
|
137696
137724
|
}
|
|
137725
|
+
if (opts.host) return loadAndSettle(bundleJs, liveBootOptions(opts, bus));
|
|
137697
137726
|
return loadBundleServicesLive(bundleJs, liveBootOptions(opts, bus));
|
|
137698
137727
|
}
|
|
137728
|
+
async function settleUnawaitedWork() {
|
|
137729
|
+
for (let turn = 0; turn < SETTLE_TURNS; turn++) await new Promise((resolve65) => setTimeout(resolve65, 0));
|
|
137730
|
+
}
|
|
137731
|
+
async function loadAndSettle(bundleJs, options) {
|
|
137732
|
+
const w2 = await bootBundleWorker(bundleJs, options);
|
|
137733
|
+
try {
|
|
137734
|
+
await settleUnawaitedWork();
|
|
137735
|
+
return { services: snapshot(w2).state, calls: w2.calls, errors: w2.errors };
|
|
137736
|
+
} finally {
|
|
137737
|
+
w2.dispose();
|
|
137738
|
+
}
|
|
137739
|
+
}
|
|
137740
|
+
function withHostAnswers(bus, declared, host) {
|
|
137741
|
+
if (!host) return bus;
|
|
137742
|
+
return (action, params) => {
|
|
137743
|
+
const capability = /^capability\.([^.]+)\./.exec(action)?.[1];
|
|
137744
|
+
const answer = capability === void 0 || declared.has(capability) ? host.dispatch(action, params) : void 0;
|
|
137745
|
+
return answer === void 0 ? bus(action, params) : Promise.resolve(answer);
|
|
137746
|
+
};
|
|
137747
|
+
}
|
|
137748
|
+
function memoryStorage() {
|
|
137749
|
+
const items = /* @__PURE__ */ new Map();
|
|
137750
|
+
return { getItem: (key2) => items.get(key2) ?? null, setItem: (key2, value) => void items.set(key2, value) };
|
|
137751
|
+
}
|
|
137699
137752
|
function liveBootOptions(opts, bus) {
|
|
137753
|
+
const { host } = opts;
|
|
137754
|
+
const wixCall = host?.wixCall ? async (method, path2, body) => host.wixCall(method, path2, body) ?? opts.wixCall(method, path2, body) : opts.wixCall;
|
|
137700
137755
|
return {
|
|
137701
|
-
wixCall
|
|
137756
|
+
wixCall,
|
|
137757
|
+
...host ? { storage: memoryStorage() } : {},
|
|
137758
|
+
...host?.wixApiSession ? { wixApiSession: host.wixApiSession } : {},
|
|
137702
137759
|
input: opts.input,
|
|
137703
137760
|
budgetMs: opts.budgetMs,
|
|
137704
137761
|
// The capability arms, but NOT the signed-in-member arm. `hostDispatch` answers
|
|
@@ -137816,6 +137873,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137816
137873
|
let base2;
|
|
137817
137874
|
let liveCalls;
|
|
137818
137875
|
let liveReturned;
|
|
137876
|
+
let liveFailed;
|
|
137819
137877
|
let liveErrors;
|
|
137820
137878
|
let mockCalls;
|
|
137821
137879
|
let mockBootFailed;
|
|
@@ -137826,16 +137884,20 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137826
137884
|
base2 = null;
|
|
137827
137885
|
} else {
|
|
137828
137886
|
const counting = countingWixCall(await ensureLiveWixCall());
|
|
137887
|
+
const host = collect2.render.host ? countingHostAnswers(collect2.render.host) : void 0;
|
|
137829
137888
|
const live3 = await liveRenderServices(bundleJs, {
|
|
137830
137889
|
wixCall: counting.call,
|
|
137831
137890
|
input,
|
|
137832
137891
|
budgetMs: collect2.render.loadBudgetMs ?? LIVE_LOAD_BUDGET_MS,
|
|
137833
137892
|
localDbSchema: appLocalDbSchema,
|
|
137834
|
-
descriptor
|
|
137893
|
+
descriptor,
|
|
137894
|
+
...host ? { host: host.host } : {}
|
|
137835
137895
|
});
|
|
137836
137896
|
base2 = live3.services;
|
|
137837
137897
|
liveCalls = [...live3.calls];
|
|
137838
137898
|
liveReturned = counting.returned();
|
|
137899
|
+
if (host) liveReturned += host.answered();
|
|
137900
|
+
liveFailed = counting.failed();
|
|
137839
137901
|
liveErrors = live3.errors;
|
|
137840
137902
|
}
|
|
137841
137903
|
} else if (collect2?.render?.mocks && collect2.render.hydrate !== false && bundleName && readBundle(bundleName)) {
|
|
@@ -137884,7 +137946,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137884
137946
|
services[svc] = { ...services[svc] ?? {}, ...st2 };
|
|
137885
137947
|
}
|
|
137886
137948
|
}
|
|
137887
|
-
return { services, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved: mockUnserved ?? [] } : {}, ...mockBootFailed ? { mockBootFailed } : {} };
|
|
137949
|
+
return { services, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed?.length ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved: mockUnserved ?? [] } : {}, ...mockBootFailed ? { mockBootFailed } : {} };
|
|
137888
137950
|
};
|
|
137889
137951
|
checkRegistry(preloaded.module.actions);
|
|
137890
137952
|
const contentManifestPath2 = join47(preloaded.dir, "himalaya.content.json");
|
|
@@ -138179,9 +138241,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
138179
138241
|
lint.push({ screenId, ok: report3.ok, issues: report3.issues });
|
|
138180
138242
|
}
|
|
138181
138243
|
if (collect2?.render && (!collect2.render.screenId || collect2.render.screenId === screenId)) {
|
|
138182
|
-
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed } = await renderServicesFor(bundleName, descriptor, screenId);
|
|
138244
|
+
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, screenId);
|
|
138183
138245
|
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
138184
|
-
renders.push({ screenId, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138246
|
+
renders.push({ screenId, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138185
138247
|
}
|
|
138186
138248
|
}
|
|
138187
138249
|
const wantedRender = collect2?.render?.screenId;
|
|
@@ -138207,9 +138269,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
138207
138269
|
});
|
|
138208
138270
|
lint.push({ screenId: wantedRender, ok: report3.ok, issues: report3.issues });
|
|
138209
138271
|
}
|
|
138210
|
-
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
138272
|
+
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
138211
138273
|
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
138212
|
-
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138274
|
+
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138213
138275
|
}
|
|
138214
138276
|
}
|
|
138215
138277
|
for (const t2 of preloaded.module.screens.templated ?? []) {
|
|
@@ -138580,7 +138642,7 @@ function declaresHostProvidedIdentity(auth) {
|
|
|
138580
138642
|
const config = auth?.config;
|
|
138581
138643
|
return typeof config === "object" && config !== null && config.hostProvided === true;
|
|
138582
138644
|
}
|
|
138583
|
-
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
|
|
138645
|
+
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL, SETTLE_TURNS;
|
|
138584
138646
|
var init_build3 = __esm({
|
|
138585
138647
|
"../release-build/build.ts"() {
|
|
138586
138648
|
init_site_view_metadata();
|
|
@@ -138622,6 +138684,7 @@ var init_build3 = __esm({
|
|
|
138622
138684
|
requireFromHere = createRequire2(import.meta.url);
|
|
138623
138685
|
SOURCEMAP_ON_DEMAND_PATH = join47(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
|
|
138624
138686
|
BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
|
|
138687
|
+
SETTLE_TURNS = 20;
|
|
138625
138688
|
}
|
|
138626
138689
|
});
|
|
138627
138690
|
|
|
@@ -152744,7 +152807,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
152744
152807
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
152745
152808
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
152746
152809
|
const hostname3 = url.hostname.replace(/^\[|\]$/g, "");
|
|
152747
|
-
return await new Promise((
|
|
152810
|
+
return await new Promise((resolve65, reject) => {
|
|
152748
152811
|
let settled = false;
|
|
152749
152812
|
const finish2 = (fn2) => {
|
|
152750
152813
|
if (settled) return;
|
|
@@ -152781,7 +152844,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
152781
152844
|
}
|
|
152782
152845
|
const responseHeaders = new Headers();
|
|
152783
152846
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
152784
|
-
|
|
152847
|
+
resolve65(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
152785
152848
|
}));
|
|
152786
152849
|
});
|
|
152787
152850
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -153081,7 +153144,7 @@ function createLocalTestSandbox() {
|
|
|
153081
153144
|
}
|
|
153082
153145
|
})();
|
|
153083
153146
|
`;
|
|
153084
|
-
return await new Promise((
|
|
153147
|
+
return await new Promise((resolve65, reject) => {
|
|
153085
153148
|
const { port1, port2 } = new MessageChannel();
|
|
153086
153149
|
const serializableContext = {
|
|
153087
153150
|
auth: context.auth,
|
|
@@ -153157,7 +153220,7 @@ function createLocalTestSandbox() {
|
|
|
153157
153220
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
153158
153221
|
return;
|
|
153159
153222
|
}
|
|
153160
|
-
if (message.ok) finish2(() =>
|
|
153223
|
+
if (message.ok) finish2(() => resolve65({ value: message.value, durationMs: Date.now() - started }));
|
|
153161
153224
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
153162
153225
|
});
|
|
153163
153226
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -155056,12 +155119,12 @@ function createLoginSession(deps) {
|
|
|
155056
155119
|
current = pending;
|
|
155057
155120
|
const out2 = [];
|
|
155058
155121
|
const err = [];
|
|
155059
|
-
return new Promise((
|
|
155122
|
+
return new Promise((resolve65) => {
|
|
155060
155123
|
let answered = false;
|
|
155061
155124
|
const answer = () => {
|
|
155062
155125
|
if (answered) return;
|
|
155063
155126
|
answered = true;
|
|
155064
|
-
|
|
155127
|
+
resolve65(current);
|
|
155065
155128
|
};
|
|
155066
155129
|
let child;
|
|
155067
155130
|
try {
|
|
@@ -155184,9 +155247,9 @@ async function startMcpServer(opts) {
|
|
|
155184
155247
|
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login }),
|
|
155185
155248
|
...opts.workspace ? { workspaceBoundary: opts.workspace } : {}
|
|
155186
155249
|
};
|
|
155187
|
-
const closed = new Promise((
|
|
155188
|
-
stdin.once("end",
|
|
155189
|
-
stdin.once("close",
|
|
155250
|
+
const closed = new Promise((resolve65) => {
|
|
155251
|
+
stdin.once("end", resolve65);
|
|
155252
|
+
stdin.once("close", resolve65);
|
|
155190
155253
|
});
|
|
155191
155254
|
const handle = serveStdio(
|
|
155192
155255
|
() => {
|
|
@@ -155566,10 +155629,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
155566
155629
|
for (const source of Object.values(files)) visit(source);
|
|
155567
155630
|
return { modules, unsupported };
|
|
155568
155631
|
}
|
|
155569
|
-
function sdkSubpathReader(
|
|
155632
|
+
function sdkSubpathReader(resolve65) {
|
|
155570
155633
|
return (sub) => {
|
|
155571
155634
|
try {
|
|
155572
|
-
return readFileSync79(
|
|
155635
|
+
return readFileSync79(resolve65(`@wix/himalaya/${sub}`), "utf8");
|
|
155573
155636
|
} catch {
|
|
155574
155637
|
return null;
|
|
155575
155638
|
}
|
|
@@ -155647,7 +155710,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
155647
155710
|
const token = mintToken2(payload);
|
|
155648
155711
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
155649
155712
|
if (unusable) throw new Error(unusable);
|
|
155650
|
-
return await new Promise((
|
|
155713
|
+
return await new Promise((resolve65, reject) => {
|
|
155651
155714
|
let settled = false;
|
|
155652
155715
|
let url = "";
|
|
155653
155716
|
const server = createServer5();
|
|
@@ -155699,7 +155762,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
155699
155762
|
}
|
|
155700
155763
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
155701
155764
|
const report3 = body.result;
|
|
155702
|
-
finish2(() =>
|
|
155765
|
+
finish2(() => resolve65({ report: report3, url }));
|
|
155703
155766
|
})();
|
|
155704
155767
|
});
|
|
155705
155768
|
server.on("error", (e2) => finish2(() => reject(e2)));
|
|
@@ -158605,6 +158668,15 @@ function retryAfterMs(header, nowMs) {
|
|
|
158605
158668
|
const ms2 = /^\d+$/.test(trimmed) ? Number(trimmed) * 1e3 : Date.parse(trimmed) - nowMs;
|
|
158606
158669
|
return Number.isFinite(ms2) ? Math.min(Math.max(ms2, 0), MAX_RETRY_WAIT_MS) : void 0;
|
|
158607
158670
|
}
|
|
158671
|
+
function assetUploadUrl(operation, size) {
|
|
158672
|
+
const url = new URL(operation.url);
|
|
158673
|
+
const appleHost = url.hostname === "apple.com" || url.hostname.endsWith(".apple.com");
|
|
158674
|
+
const inFile = Number.isInteger(operation.offset) && Number.isInteger(operation.length) && operation.offset >= 0 && operation.length > 0 && operation.offset + operation.length <= size;
|
|
158675
|
+
if (url.protocol !== "https:" || !appleHost || url.username || url.password || operation.method !== "PUT" || !inFile) {
|
|
158676
|
+
throw new AscError("refused", `refusing an asset upload operation Apple would not issue (${operation.method} ${url.origin})`);
|
|
158677
|
+
}
|
|
158678
|
+
return url;
|
|
158679
|
+
}
|
|
158608
158680
|
function backoffMs(attempt) {
|
|
158609
158681
|
return Math.min(BASE_BACKOFF_MS * 2 ** (attempt - 1), MAX_RETRY_WAIT_MS);
|
|
158610
158682
|
}
|
|
@@ -158667,7 +158739,7 @@ var init_iap_client = __esm({
|
|
|
158667
158739
|
this.options = options;
|
|
158668
158740
|
this.fetchImpl = options.fetchImpl ?? ((input, init) => globalThis.fetch(input, init));
|
|
158669
158741
|
this.now = options.now ?? Date.now;
|
|
158670
|
-
this.sleep = options.sleep ?? ((ms2) => new Promise((
|
|
158742
|
+
this.sleep = options.sleep ?? ((ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2)));
|
|
158671
158743
|
}
|
|
158672
158744
|
fetchImpl;
|
|
158673
158745
|
now;
|
|
@@ -158694,6 +158766,32 @@ var init_iap_client = __esm({
|
|
|
158694
158766
|
async patch(path2, body) {
|
|
158695
158767
|
return this.write("PATCH", this.resolve(path2), body);
|
|
158696
158768
|
}
|
|
158769
|
+
async delete(path2) {
|
|
158770
|
+
await this.write("DELETE", this.resolve(path2));
|
|
158771
|
+
}
|
|
158772
|
+
async uploadParts(operations, bytes2) {
|
|
158773
|
+
for (const [i2, operation] of operations.entries()) {
|
|
158774
|
+
const where = `upload of part ${i2 + 1} of ${operations.length} to Apple's asset storage`;
|
|
158775
|
+
const response = await this.putPart(operation, bytes2, where);
|
|
158776
|
+
if (response.status >= 500) throw new AscError("server", `${where} \u2192 ${response.status}`, response.status);
|
|
158777
|
+
if (!response.ok) throw new AscError("invalid", `${where} \u2192 ${response.status} \u2014 the reserved upload was refused; make a new plan, which reserves a fresh one`, response.status);
|
|
158778
|
+
}
|
|
158779
|
+
}
|
|
158780
|
+
async putPart(operation, bytes2, where) {
|
|
158781
|
+
const url = assetUploadUrl(operation, bytes2.length);
|
|
158782
|
+
const headers2 = Object.fromEntries(operation.requestHeaders.filter((h2) => h2.name.toLowerCase() !== "authorization").map((h2) => [h2.name, h2.value]));
|
|
158783
|
+
try {
|
|
158784
|
+
return await this.fetchImpl(url.href, {
|
|
158785
|
+
method: "PUT",
|
|
158786
|
+
headers: headers2,
|
|
158787
|
+
body: bytes2.slice(operation.offset, operation.offset + operation.length),
|
|
158788
|
+
redirect: "error",
|
|
158789
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
158790
|
+
});
|
|
158791
|
+
} catch (e2) {
|
|
158792
|
+
throw new AscError("network", `${where} failed before a response: ${this.scrub(e2.message)}`);
|
|
158793
|
+
}
|
|
158794
|
+
}
|
|
158697
158795
|
resolve(pathOrUrl) {
|
|
158698
158796
|
const url = new URL(pathOrUrl, ASC_ORIGIN);
|
|
158699
158797
|
const allowed2 = url.origin === ASC_ORIGIN && !url.username && !url.password && /^\/v[12]\//.test(url.pathname);
|
|
@@ -158818,6 +158916,20 @@ function toVersion(resource) {
|
|
|
158818
158916
|
function toLocalization(resource) {
|
|
158819
158917
|
return { id: resource.id, locale: attr(resource, "locale"), name: attr(resource, "name"), description: attr(resource, "description") };
|
|
158820
158918
|
}
|
|
158919
|
+
function toReviewScreenshot(resource) {
|
|
158920
|
+
const attributes = resource.attributes ?? {};
|
|
158921
|
+
const delivery = attributes.assetDeliveryState ?? {};
|
|
158922
|
+
const errors = (delivery.errors ?? []).map((e2) => [e2.code, e2.description].filter((part2) => typeof part2 === "string").join(": "));
|
|
158923
|
+
const checksum = attr(resource, "sourceFileChecksum");
|
|
158924
|
+
return {
|
|
158925
|
+
id: resource.id,
|
|
158926
|
+
fileName: attr(resource, "fileName"),
|
|
158927
|
+
fileSize: typeof attributes.fileSize === "number" ? attributes.fileSize : 0,
|
|
158928
|
+
...checksum ? { checksum } : {},
|
|
158929
|
+
state: typeof delivery.state === "string" ? delivery.state : "",
|
|
158930
|
+
errors
|
|
158931
|
+
};
|
|
158932
|
+
}
|
|
158821
158933
|
function toManualPrice(price, included) {
|
|
158822
158934
|
const point = included.find((r2) => r2.type === "inAppPurchasePricePoints" && r2.id === relatedId(price, "inAppPurchasePricePoint"));
|
|
158823
158935
|
const date = (name) => typeof price.attributes?.[name] === "string" ? price.attributes[name] : null;
|
|
@@ -158839,7 +158951,7 @@ async function readOptional(read) {
|
|
|
158839
158951
|
function createIapApi(client2) {
|
|
158840
158952
|
return new AppStoreConnectIapApi(client2);
|
|
158841
158953
|
}
|
|
158842
|
-
var APPLE_PRODUCT_TYPES, PRICE_POINT_PAGE, INITIAL_PRICE_REF, PAGE, linkage, related, enc, AppStoreConnectIapApi;
|
|
158954
|
+
var APPLE_PRODUCT_TYPES, PRICE_POINT_PAGE, INITIAL_PRICE_REF, PAGE, linkage, related, enc, AppStoreConnectIapApi, SCREENSHOTS, SCREENSHOT_TYPE, ReviewScreenshotEndpoints;
|
|
158843
158955
|
var init_iap_api = __esm({
|
|
158844
158956
|
"../store-release/iap-api.ts"() {
|
|
158845
158957
|
init_iap_client();
|
|
@@ -158853,7 +158965,9 @@ var init_iap_api = __esm({
|
|
|
158853
158965
|
AppStoreConnectIapApi = class {
|
|
158854
158966
|
constructor(client2) {
|
|
158855
158967
|
this.client = client2;
|
|
158968
|
+
this.screenshots = new ReviewScreenshotEndpoints(client2);
|
|
158856
158969
|
}
|
|
158970
|
+
screenshots;
|
|
158857
158971
|
async readApp(appId2) {
|
|
158858
158972
|
const app = requireSingle(await this.client.get(`/v1/apps/${enc(appId2)}?fields[apps]=bundleId`), "app");
|
|
158859
158973
|
return { id: app.id, bundleId: attr(app, "bundleId") };
|
|
@@ -158973,6 +159087,50 @@ var init_iap_api = __esm({
|
|
|
158973
159087
|
}
|
|
158974
159088
|
});
|
|
158975
159089
|
}
|
|
159090
|
+
async readReviewScreenshot(resourceId) {
|
|
159091
|
+
return this.screenshots.read(resourceId);
|
|
159092
|
+
}
|
|
159093
|
+
async reserveReviewScreenshot(resourceId, file2) {
|
|
159094
|
+
return this.screenshots.reserve(resourceId, file2);
|
|
159095
|
+
}
|
|
159096
|
+
async uploadReviewScreenshotParts(reservation, bytes2) {
|
|
159097
|
+
await this.client.uploadParts(reservation.uploadOperations, bytes2);
|
|
159098
|
+
}
|
|
159099
|
+
async commitReviewScreenshot(screenshotId, checksum) {
|
|
159100
|
+
return this.screenshots.commit(screenshotId, checksum);
|
|
159101
|
+
}
|
|
159102
|
+
async deleteReviewScreenshot(screenshotId) {
|
|
159103
|
+
await this.screenshots.delete(screenshotId);
|
|
159104
|
+
}
|
|
159105
|
+
};
|
|
159106
|
+
SCREENSHOTS = "/v1/inAppPurchaseAppStoreReviewScreenshots";
|
|
159107
|
+
SCREENSHOT_TYPE = "inAppPurchaseAppStoreReviewScreenshots";
|
|
159108
|
+
ReviewScreenshotEndpoints = class {
|
|
159109
|
+
constructor(client2) {
|
|
159110
|
+
this.client = client2;
|
|
159111
|
+
}
|
|
159112
|
+
async read(resourceId) {
|
|
159113
|
+
const screenshot = await readOptional(() => this.client.get(`/v2/inAppPurchases/${enc(resourceId)}/appStoreReviewScreenshot`));
|
|
159114
|
+
return screenshot && toReviewScreenshot(screenshot);
|
|
159115
|
+
}
|
|
159116
|
+
async reserve(resourceId, file2) {
|
|
159117
|
+
const doc = await this.client.post(SCREENSHOTS, {
|
|
159118
|
+
data: { type: SCREENSHOT_TYPE, attributes: file2, relationships: { inAppPurchaseV2: related("inAppPurchases", resourceId) } }
|
|
159119
|
+
});
|
|
159120
|
+
const reservation = requireSingle(doc, "review screenshot reservation");
|
|
159121
|
+
const operations = reservation.attributes?.uploadOperations;
|
|
159122
|
+
if (!Array.isArray(operations) || !operations.length) throw new AscError("server", "App Store Connect reserved the review screenshot without upload operations");
|
|
159123
|
+
return { id: reservation.id, uploadOperations: operations };
|
|
159124
|
+
}
|
|
159125
|
+
async commit(screenshotId, checksum) {
|
|
159126
|
+
const doc = await this.client.patch(`${SCREENSHOTS}/${enc(screenshotId)}`, {
|
|
159127
|
+
data: { type: SCREENSHOT_TYPE, id: screenshotId, attributes: { uploaded: true, sourceFileChecksum: checksum } }
|
|
159128
|
+
});
|
|
159129
|
+
return toReviewScreenshot(requireSingle(doc, "review screenshot"));
|
|
159130
|
+
}
|
|
159131
|
+
async delete(screenshotId) {
|
|
159132
|
+
await this.client.delete(`${SCREENSHOTS}/${enc(screenshotId)}`);
|
|
159133
|
+
}
|
|
158976
159134
|
};
|
|
158977
159135
|
}
|
|
158978
159136
|
});
|
|
@@ -159057,6 +159215,7 @@ function readItem(reader, value, index) {
|
|
|
159057
159215
|
const price = readPrice(reader, obj3, path2);
|
|
159058
159216
|
const reviewNote = reader.optionalText(obj3, "reviewNote", path2);
|
|
159059
159217
|
if (reviewNote) reader.maxLength(reviewNote, `${path2}.reviewNote`, APPLE_LIMITS.reviewNote);
|
|
159218
|
+
const reviewScreenshot = obj3.reviewScreenshot === void 0 ? void 0 : reader.text(obj3, "reviewScreenshot", path2, SCREENSHOT_PATH);
|
|
159060
159219
|
return {
|
|
159061
159220
|
...readSubject(reader, obj3, path2, type),
|
|
159062
159221
|
classification: reader.literal(obj3, "classification", path2, "digital", "physical goods and unclassified products are never registered as in-app purchases"),
|
|
@@ -159065,6 +159224,7 @@ function readItem(reader, value, index) {
|
|
|
159065
159224
|
type,
|
|
159066
159225
|
referenceName: limitedText(reader, obj3, "referenceName", path2, APPLE_LIMITS.referenceName),
|
|
159067
159226
|
...reviewNote === void 0 ? {} : { reviewNote },
|
|
159227
|
+
...reviewScreenshot === void 0 ? {} : { reviewScreenshot },
|
|
159068
159228
|
localizations: readLocalizations(reader, obj3, path2),
|
|
159069
159229
|
price,
|
|
159070
159230
|
territories: readTerritories(reader, obj3, path2, price.baseTerritory)
|
|
@@ -159127,7 +159287,7 @@ function sha256Digest(value) {
|
|
|
159127
159287
|
function manifestDigest(manifest) {
|
|
159128
159288
|
return sha256Digest(manifest);
|
|
159129
159289
|
}
|
|
159130
|
-
var IapManifestError, APPLE_APP_ID, TEAM_ID, BUNDLE_ID, PRODUCT_ID, TERRITORY, CURRENCY2, AMOUNT, LOCALE, CREDENTIAL_SHAPES, MANIFEST_KEYS, TARGET_KEYS, ITEM_KEYS, WIX_KEYS, UNLOCK_KEYS, LOCALIZATION_KEYS, PRICE_KEYS, PRODUCT_TYPES, PRICE_RULES, APPLE_LIMITS, childPath, ManifestReader;
|
|
159290
|
+
var IapManifestError, APPLE_APP_ID, TEAM_ID, BUNDLE_ID, PRODUCT_ID, TERRITORY, CURRENCY2, AMOUNT, LOCALE, SCREENSHOT_PATH, CREDENTIAL_SHAPES, MANIFEST_KEYS, TARGET_KEYS, ITEM_KEYS, WIX_KEYS, UNLOCK_KEYS, LOCALIZATION_KEYS, PRICE_KEYS, PRODUCT_TYPES, PRICE_RULES, APPLE_LIMITS, childPath, ManifestReader;
|
|
159131
159291
|
var init_iap_manifest = __esm({
|
|
159132
159292
|
"../store-release/iap-manifest.ts"() {
|
|
159133
159293
|
IapManifestError = class extends Error {
|
|
@@ -159146,6 +159306,7 @@ var init_iap_manifest = __esm({
|
|
|
159146
159306
|
CURRENCY2 = { pattern: /^[A-Z]{3}$/, hint: "an ISO 4217 currency code such as USD" };
|
|
159147
159307
|
AMOUNT = { pattern: /^\d+(\.\d+)?$/, hint: 'an exact decimal string such as "0.99"' };
|
|
159148
159308
|
LOCALE = { pattern: /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/, hint: "a locale such as en-US" };
|
|
159309
|
+
SCREENSHOT_PATH = { pattern: /\.(png|jpe?g)$/i, hint: "a path to a .png, .jpg or .jpeg file" };
|
|
159149
159310
|
CREDENTIAL_SHAPES = [
|
|
159150
159311
|
/-----BEGIN [A-Z ]*PRIVATE KEY-----/,
|
|
159151
159312
|
/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/,
|
|
@@ -159162,6 +159323,7 @@ var init_iap_manifest = __esm({
|
|
|
159162
159323
|
"type",
|
|
159163
159324
|
"referenceName",
|
|
159164
159325
|
"reviewNote",
|
|
159326
|
+
"reviewScreenshot",
|
|
159165
159327
|
"localizations",
|
|
159166
159328
|
"price",
|
|
159167
159329
|
"territories"
|
|
@@ -159311,8 +159473,16 @@ var init_iap_pricing = __esm({
|
|
|
159311
159473
|
});
|
|
159312
159474
|
|
|
159313
159475
|
// ../store-release/iap-result.ts
|
|
159314
|
-
|
|
159476
|
+
import { basename as basename18 } from "node:path";
|
|
159477
|
+
function missingMetadataRequirement(screenshotState, itemNamesFile) {
|
|
159478
|
+
if (screenshotState === void 0) return MISSING_SCREENSHOT;
|
|
159479
|
+
const leftover = LEFTOVER_STATES[screenshotState];
|
|
159480
|
+
if (!leftover) return MISSING_AFTER_SCREENSHOT;
|
|
159481
|
+
return leftover.problem + (itemNamesFile ? leftover.fix : ADD_FILE_FIRST);
|
|
159482
|
+
}
|
|
159483
|
+
function remainingRequirements(observed, itemNamesFile = true) {
|
|
159315
159484
|
if (!observed) return ["the product does not exist in App Store Connect yet"];
|
|
159485
|
+
if (observed.state === "MISSING_METADATA") return [observed.reviewScreenshotRead ? missingMetadataRequirement(observed.reviewScreenshot?.state, itemNamesFile) : MISSING_UNREAD];
|
|
159316
159486
|
const requirement = STATE_REQUIREMENTS[observed.state];
|
|
159317
159487
|
return requirement ? [requirement] : [];
|
|
159318
159488
|
}
|
|
@@ -159333,6 +159503,10 @@ function mappingFor(target, item, appleResourceId) {
|
|
|
159333
159503
|
function metadataVersion(observed) {
|
|
159334
159504
|
return observed?.versions.find((v2) => v2.id === observed.metadataVersionId);
|
|
159335
159505
|
}
|
|
159506
|
+
function screenshotReport(path2, observed) {
|
|
159507
|
+
const held = observed?.reviewScreenshot;
|
|
159508
|
+
return { requested: basename18(path2), ...held ? { observed: { fileName: held.fileName, state: held.state } } : {} };
|
|
159509
|
+
}
|
|
159336
159510
|
function itemResult(input) {
|
|
159337
159511
|
const { target, item, observed } = input;
|
|
159338
159512
|
const version4 = metadataVersion(observed);
|
|
@@ -159351,7 +159525,8 @@ function itemResult(input) {
|
|
|
159351
159525
|
...observed?.availability ? { observed: observed.availability.territories, availableInNewTerritories: observed.availability.availableInNewTerritories } : {}
|
|
159352
159526
|
},
|
|
159353
159527
|
localizations: { requested: item.localizations.map((l2) => l2.locale), observed: observed?.localizations.map((l2) => l2.locale) ?? [] },
|
|
159354
|
-
|
|
159528
|
+
...item.reviewScreenshot ? { reviewScreenshot: screenshotReport(item.reviewScreenshot, observed) } : {},
|
|
159529
|
+
remainingRequirements: [...input.requirements ?? [], ...remainingRequirements(observed, item.reviewScreenshot !== void 0)],
|
|
159355
159530
|
lastReadAt: input.readAt.toISOString()
|
|
159356
159531
|
}
|
|
159357
159532
|
};
|
|
@@ -159368,12 +159543,11 @@ function iapResult(args) {
|
|
|
159368
159543
|
items: args.items
|
|
159369
159544
|
};
|
|
159370
159545
|
}
|
|
159371
|
-
var COMPLETE_OUTCOMES, STATE_REQUIREMENTS;
|
|
159546
|
+
var COMPLETE_OUTCOMES, STATE_REQUIREMENTS, MISSING_SCREENSHOT, MISSING_UNREAD, REFUSED_SCREENSHOT, MISSING_AFTER_SCREENSHOT, UNFINISHED_SCREENSHOT, LEFTOVER_STATES, ADD_FILE_FIRST;
|
|
159372
159547
|
var init_iap_result = __esm({
|
|
159373
159548
|
"../store-release/iap-result.ts"() {
|
|
159374
159549
|
COMPLETE_OUTCOMES = /* @__PURE__ */ new Set(["created", "updated", "reused"]);
|
|
159375
159550
|
STATE_REQUIREMENTS = {
|
|
159376
|
-
MISSING_METADATA: "App Store Connect reports MISSING_METADATA \u2014 usually the App Review screenshot, which this command does not upload",
|
|
159377
159551
|
READY_TO_SUBMIT: "submit the product for App Review with an app version \u2014 this command never submits",
|
|
159378
159552
|
DEVELOPER_ACTION_NEEDED: "resolve the App Review feedback in App Store Connect",
|
|
159379
159553
|
REJECTED: "resolve the App Review rejection in App Store Connect",
|
|
@@ -159385,6 +159559,16 @@ var init_iap_result = __esm({
|
|
|
159385
159559
|
WAITING_FOR_UPLOAD: "waiting for its hosted content to be uploaded",
|
|
159386
159560
|
PROCESSING_CONTENT: "Apple is still processing its hosted content"
|
|
159387
159561
|
};
|
|
159562
|
+
MISSING_SCREENSHOT = 'App Store Connect reports MISSING_METADATA and the product has no App Review screenshot \u2014 add "reviewScreenshot" to the item and apply, or upload one in App Store Connect';
|
|
159563
|
+
MISSING_UNREAD = 'App Store Connect reports MISSING_METADATA \u2014 check the product in App Store Connect; when it lacks the App Review screenshot, add "reviewScreenshot" to the item and apply';
|
|
159564
|
+
REFUSED_SCREENSHOT = "App Store Connect reports MISSING_METADATA \u2014 Apple could not process the review screenshot";
|
|
159565
|
+
MISSING_AFTER_SCREENSHOT = "App Store Connect still reports MISSING_METADATA \u2014 Apple may still be processing the review screenshot; if it stays, check the product in App Store Connect";
|
|
159566
|
+
UNFINISHED_SCREENSHOT = "App Store Connect reports MISSING_METADATA \u2014 the review screenshot upload is unfinished";
|
|
159567
|
+
LEFTOVER_STATES = {
|
|
159568
|
+
FAILED: { problem: REFUSED_SCREENSHOT, fix: "; replace the file and apply again" },
|
|
159569
|
+
AWAITING_UPLOAD: { problem: UNFINISHED_SCREENSHOT, fix: "; rerun plan and apply to replace it" }
|
|
159570
|
+
};
|
|
159571
|
+
ADD_FILE_FIRST = ' \u2014 add "reviewScreenshot" to the item first, then plan and apply';
|
|
159388
159572
|
}
|
|
159389
159573
|
});
|
|
159390
159574
|
|
|
@@ -159428,6 +159612,99 @@ var init_iap_price_status = __esm({
|
|
|
159428
159612
|
}
|
|
159429
159613
|
});
|
|
159430
159614
|
|
|
159615
|
+
// ../store-release/screenshot-display-types.ts
|
|
159616
|
+
function displayTypeForSize(w2, h2) {
|
|
159617
|
+
const key2 = `${Math.min(w2, h2)}x${Math.max(w2, h2)}`;
|
|
159618
|
+
const map = {
|
|
159619
|
+
"1320x2868": "APP_IPHONE_67",
|
|
159620
|
+
// 6.9" → 6.7"/6.9" combined slot
|
|
159621
|
+
"1290x2796": "APP_IPHONE_67",
|
|
159622
|
+
// 6.7"
|
|
159623
|
+
"1242x2688": "APP_IPHONE_65",
|
|
159624
|
+
// 6.5"
|
|
159625
|
+
"1284x2778": "APP_IPHONE_65",
|
|
159626
|
+
"1206x2622": "APP_IPHONE_61",
|
|
159627
|
+
// 6.3"/6.1"
|
|
159628
|
+
"1179x2556": "APP_IPHONE_61",
|
|
159629
|
+
"2048x2732": "APP_IPAD_PRO_129",
|
|
159630
|
+
"2064x2752": "APP_IPAD_PRO_3GEN_129"
|
|
159631
|
+
};
|
|
159632
|
+
return map[key2] ?? null;
|
|
159633
|
+
}
|
|
159634
|
+
var init_screenshot_display_types = __esm({
|
|
159635
|
+
"../store-release/screenshot-display-types.ts"() {
|
|
159636
|
+
}
|
|
159637
|
+
});
|
|
159638
|
+
|
|
159639
|
+
// ../store-release/iap-review-screenshot.ts
|
|
159640
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
159641
|
+
import { basename as basename19, resolve as resolve56 } from "node:path";
|
|
159642
|
+
function pngSize(bytes2) {
|
|
159643
|
+
const signed = PNG_SIGNATURE.every((b2, i2) => bytes2[i2] === b2);
|
|
159644
|
+
if (!signed || bytes2.length < 24 || bytes2.toString("ascii", 12, 16) !== "IHDR") return void 0;
|
|
159645
|
+
return { format: "png", width: bytes2.readUInt32BE(16), height: bytes2.readUInt32BE(20) };
|
|
159646
|
+
}
|
|
159647
|
+
function jpegSize(bytes2) {
|
|
159648
|
+
if (bytes2[0] !== 255 || bytes2[1] !== 216) return void 0;
|
|
159649
|
+
for (let at2 = 2; at2 + 9 <= bytes2.length && bytes2[at2] === 255; at2 += 2 + bytes2.readUInt16BE(at2 + 2)) {
|
|
159650
|
+
if (JPEG_SOF_MARKERS.has(bytes2[at2 + 1])) return { format: "jpeg", height: bytes2.readUInt16BE(at2 + 5), width: bytes2.readUInt16BE(at2 + 7) };
|
|
159651
|
+
}
|
|
159652
|
+
return void 0;
|
|
159653
|
+
}
|
|
159654
|
+
function readImageSize(bytes2) {
|
|
159655
|
+
const buffer = Buffer.from(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
159656
|
+
return pngSize(buffer) ?? jpegSize(buffer);
|
|
159657
|
+
}
|
|
159658
|
+
function md5Hex(bytes2) {
|
|
159659
|
+
return createHash38("md5").update(bytes2).digest("hex");
|
|
159660
|
+
}
|
|
159661
|
+
function isAppStoreScreenshotSize(file2) {
|
|
159662
|
+
return displayTypeForSize(file2.width, file2.height) !== null;
|
|
159663
|
+
}
|
|
159664
|
+
function screenshotNotes(file2) {
|
|
159665
|
+
const size = `${file2.width}\xD7${file2.height}`;
|
|
159666
|
+
const notes = [`review screenshot ${file2.fileName} (${size} ${file2.format.toUpperCase()})`];
|
|
159667
|
+
if (!isAppStoreScreenshotSize(file2)) notes.push(`${size} is not an App Store screenshot size this tool knows \u2014 Apple may refuse it; a full-size iPhone screenshot is safest`);
|
|
159668
|
+
return notes;
|
|
159669
|
+
}
|
|
159670
|
+
function readReviewScreenshot(path2, source) {
|
|
159671
|
+
if (!source.readBytes) throw new Error("this run cannot read files");
|
|
159672
|
+
const absolute = resolve56(source.manifestDir ?? process.cwd(), path2);
|
|
159673
|
+
let bytes2;
|
|
159674
|
+
try {
|
|
159675
|
+
bytes2 = source.readBytes(absolute);
|
|
159676
|
+
} catch (e2) {
|
|
159677
|
+
throw new Error(`cannot read ${absolute}: ${e2.message}`);
|
|
159678
|
+
}
|
|
159679
|
+
const size = readImageSize(bytes2);
|
|
159680
|
+
if (!size) throw new Error(`${absolute} is not a PNG or JPEG image`);
|
|
159681
|
+
return { ...size, path: absolute, fileName: basename19(absolute), bytes: bytes2, checksum: md5Hex(bytes2) };
|
|
159682
|
+
}
|
|
159683
|
+
function loadReviewScreenshots(manifest, source, indices = manifest.items.map((_2, i2) => i2)) {
|
|
159684
|
+
const files = /* @__PURE__ */ new Map();
|
|
159685
|
+
const problems = [];
|
|
159686
|
+
for (const i2 of indices) {
|
|
159687
|
+
const path2 = manifest.items[i2].reviewScreenshot;
|
|
159688
|
+
if (path2 === void 0) continue;
|
|
159689
|
+
try {
|
|
159690
|
+
files.set(i2, readReviewScreenshot(path2, source));
|
|
159691
|
+
} catch (e2) {
|
|
159692
|
+
problems.push(`items[${i2}].reviewScreenshot: ${e2.message}`);
|
|
159693
|
+
}
|
|
159694
|
+
}
|
|
159695
|
+
if (problems.length) throw new IapManifestError("the manifest", problems);
|
|
159696
|
+
return files;
|
|
159697
|
+
}
|
|
159698
|
+
var PNG_SIGNATURE, JPEG_SOF_MARKERS;
|
|
159699
|
+
var init_iap_review_screenshot = __esm({
|
|
159700
|
+
"../store-release/iap-review-screenshot.ts"() {
|
|
159701
|
+
init_iap_manifest();
|
|
159702
|
+
init_screenshot_display_types();
|
|
159703
|
+
PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
159704
|
+
JPEG_SOF_MARKERS = /* @__PURE__ */ new Set([192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207]);
|
|
159705
|
+
}
|
|
159706
|
+
});
|
|
159707
|
+
|
|
159431
159708
|
// ../store-release/iap-plan.ts
|
|
159432
159709
|
function priceNote(price, target) {
|
|
159433
159710
|
if (price.rule !== "atLeast") return CONDITIONAL_PRICE_NOTE;
|
|
@@ -159567,6 +159844,47 @@ function availabilityDiff(item, observed) {
|
|
|
159567
159844
|
function metadataDiffs(item, observed, target = exactTarget(item.price)) {
|
|
159568
159845
|
return [...localizationDiffs(item, observed), ...priceDiff(item, observed, target), ...availabilityDiff(item, observed)];
|
|
159569
159846
|
}
|
|
159847
|
+
function screenshotMatches(observed, checksum) {
|
|
159848
|
+
return observed?.checksum === checksum && observed.state !== "FAILED";
|
|
159849
|
+
}
|
|
159850
|
+
function describeScreenshotGap(observed, fileName) {
|
|
159851
|
+
if (!observed) return "the review screenshot is not uploaded";
|
|
159852
|
+
if (observed.state === "AWAITING_UPLOAD") return "the review screenshot is not uploaded \u2014 an unfinished upload is waiting";
|
|
159853
|
+
if (observed.state === "FAILED") return `Apple could not process the review screenshot: ${observed.errors.join("; ") || "no reason given"}`;
|
|
159854
|
+
return `the review screenshot differs from ${fileName}`;
|
|
159855
|
+
}
|
|
159856
|
+
function screenshotUnmet(planned2, observed) {
|
|
159857
|
+
if (!planned2 || !observed || screenshotMatches(observed.reviewScreenshot, planned2.checksum)) return [];
|
|
159858
|
+
return [describeScreenshotGap(observed.reviewScreenshot, planned2.fileName)];
|
|
159859
|
+
}
|
|
159860
|
+
async function withReviewScreenshot(api2, observed) {
|
|
159861
|
+
if (observed.reviewScreenshotRead) return observed;
|
|
159862
|
+
const reviewScreenshot = await api2.readReviewScreenshot(observed.resourceId);
|
|
159863
|
+
return { ...observed, reviewScreenshotRead: true, ...reviewScreenshot ? { reviewScreenshot } : {} };
|
|
159864
|
+
}
|
|
159865
|
+
function isScreenshotLeftover(held) {
|
|
159866
|
+
return LEFTOVER_SCREENSHOT_STATES.has(held.state);
|
|
159867
|
+
}
|
|
159868
|
+
function screenshotOp(observed, checksum) {
|
|
159869
|
+
return { kind: observed.reviewScreenshot ? "replaceReviewScreenshot" : "uploadReviewScreenshot", checksum };
|
|
159870
|
+
}
|
|
159871
|
+
async function planReviewScreenshot(api2, plan, file2) {
|
|
159872
|
+
if (!file2) return plan;
|
|
159873
|
+
const planned2 = { ...plan, notes: [...plan.notes, ...screenshotNotes(file2)], reviewScreenshot: { fileName: file2.fileName, checksum: file2.checksum } };
|
|
159874
|
+
if (plan.decision === "conflict") return plan.observed ? { ...planned2, observed: await withReviewScreenshot(api2, plan.observed) } : planned2;
|
|
159875
|
+
if (plan.decision === "create") return { ...planned2, ops: [...plan.ops, { kind: "uploadReviewScreenshot", checksum: file2.checksum }] };
|
|
159876
|
+
const observed = await withReviewScreenshot(api2, observationOf(plan));
|
|
159877
|
+
const [gap] = screenshotUnmet(planned2.reviewScreenshot, observed);
|
|
159878
|
+
if (!gap) return { ...planned2, observed };
|
|
159879
|
+
if (isLocked(observed)) {
|
|
159880
|
+
return { ...planned2, observed, decision: "conflict", ops: [], conflicts: [`${plan.productId} is ${observed.state} and this command never changes a live or in-review product: ${gap}`] };
|
|
159881
|
+
}
|
|
159882
|
+
return { ...planned2, observed, decision: "update", ops: [...plan.ops, screenshotOp(observed, file2.checksum)] };
|
|
159883
|
+
}
|
|
159884
|
+
function observationOf(plan) {
|
|
159885
|
+
if (!plan.observed) throw new Error(`internal: the plan for existing product ${plan.productId} has no observation`);
|
|
159886
|
+
return plan.observed;
|
|
159887
|
+
}
|
|
159570
159888
|
function isLocked(observed) {
|
|
159571
159889
|
return !EDITABLE_PRODUCT_STATES.has(observed.state) || observed.versions.some((v2) => LOCKED_VERSION_STATES.has(v2.state));
|
|
159572
159890
|
}
|
|
@@ -159671,11 +159989,15 @@ async function planItem(pricing, api2, item, products, today) {
|
|
|
159671
159989
|
}
|
|
159672
159990
|
async function planItemsAt(context, manifest, indices = manifest.items.map((_2, i2) => i2)) {
|
|
159673
159991
|
const pricing = context.pricing ?? new PriceGrid(context.api);
|
|
159992
|
+
const screenshots = loadReviewScreenshots(manifest, context, indices);
|
|
159674
159993
|
return withAccessContext(context.identity, manifest.target, async () => {
|
|
159675
159994
|
await verifyTarget(context.api, manifest, context.identity);
|
|
159676
159995
|
const products = await discoverProducts(context, manifest);
|
|
159677
159996
|
const plans = /* @__PURE__ */ new Map();
|
|
159678
|
-
for (const i2 of indices)
|
|
159997
|
+
for (const i2 of indices) {
|
|
159998
|
+
const planned2 = await planItem(pricing, context.api, manifest.items[i2], products, isoDay(context.now()));
|
|
159999
|
+
plans.set(i2, await planReviewScreenshot(context.api, planned2, screenshots.get(i2)));
|
|
160000
|
+
}
|
|
159679
160001
|
return plans;
|
|
159680
160002
|
});
|
|
159681
160003
|
}
|
|
@@ -159695,6 +160017,7 @@ async function planIap(manifest, context) {
|
|
|
159695
160017
|
target: manifest.target,
|
|
159696
160018
|
manifestDigest: manifestDigest(manifest),
|
|
159697
160019
|
manifest,
|
|
160020
|
+
...context.manifestDir ? { manifestDir: context.manifestDir } : {},
|
|
159698
160021
|
items
|
|
159699
160022
|
});
|
|
159700
160023
|
}
|
|
@@ -159705,13 +160028,18 @@ function verifyOps(plan, manifest) {
|
|
|
159705
160028
|
if (itemPlan2.productId !== item.productId || !Array.isArray(itemPlan2.ops)) throw planError(`plan item ${i2} does not match manifest product ${item.productId}`);
|
|
159706
160029
|
for (const op of itemPlan2.ops) {
|
|
159707
160030
|
const locales = item.localizations.map((l2) => l2.locale);
|
|
159708
|
-
const knownShape = OP_KINDS.has(op.kind) && Object.keys(op).every((k2) => k2 === "kind" || k2 === "locale" && LOCALE_OPS.has(op.kind) || op.kind === "changePrice" && (k2 === "from" || k2 === "to"));
|
|
160031
|
+
const knownShape = OP_KINDS.has(op.kind) && Object.keys(op).every((k2) => k2 === "kind" || k2 === "locale" && LOCALE_OPS.has(op.kind) || op.kind === "changePrice" && (k2 === "from" || k2 === "to") || k2 === "checksum" && SCREENSHOT_OPS.has(op.kind));
|
|
159709
160032
|
const localeOk = !LOCALE_OPS.has(op.kind) || locales.includes(op.locale);
|
|
159710
160033
|
const priceOk = op.kind !== "changePrice" || item.price.rule === "atLeast" && [op.from, op.to].every((v2) => typeof v2 === "string" && /^\d+(\.\d+)?$/.test(v2) && compareAmounts(v2, "0") > 0) && itemPlan2.observed?.priceSchedule !== void 0 && itemPlan2.targetPrice === op.to;
|
|
159711
|
-
|
|
160034
|
+
const screenshotOk = !SCREENSHOT_OPS.has(op.kind) || screenshotOpOk(op, item, itemPlan2);
|
|
160035
|
+
if (!knownShape || !localeOk || !priceOk || !screenshotOk) throw planError(`plan item ${item.productId} has an unknown operation ${JSON.stringify(op)}`);
|
|
159712
160036
|
}
|
|
159713
160037
|
});
|
|
159714
160038
|
}
|
|
160039
|
+
function screenshotOpOk(op, item, itemPlan2) {
|
|
160040
|
+
const { checksum } = op;
|
|
160041
|
+
return item.reviewScreenshot !== void 0 && typeof checksum === "string" && MD5_HEX.test(checksum) && itemPlan2.reviewScreenshot?.checksum === checksum;
|
|
160042
|
+
}
|
|
159715
160043
|
function verifyPlan2(doc) {
|
|
159716
160044
|
const plan = doc;
|
|
159717
160045
|
if (!plan || typeof plan !== "object" || plan.planVersion !== 1) throw planError("not a himi store iap plan (planVersion 1)");
|
|
@@ -159728,8 +160056,9 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159728
160056
|
const plans = await planItems({ ...context, pricing }, manifest);
|
|
159729
160057
|
const readAt2 = context.now();
|
|
159730
160058
|
const items = [];
|
|
159731
|
-
for (const [i2,
|
|
160059
|
+
for (const [i2, planned2] of plans.entries()) {
|
|
159732
160060
|
const item = manifest.items[i2];
|
|
160061
|
+
const p2 = planned2.observed ? { ...planned2, observed: await withAccessContext(context.identity, manifest.target, () => withReviewScreenshot(context.api, planned2.observed)) } : planned2;
|
|
159733
160062
|
const target = p2.observed ? await pricing.targetAmount(item.price, p2.observed.resourceId) : void 0;
|
|
159734
160063
|
const result = itemResult({
|
|
159735
160064
|
target: manifest.target,
|
|
@@ -159737,7 +160066,7 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159737
160066
|
observed: p2.observed,
|
|
159738
160067
|
outcome: STATUS_OUTCOMES[p2.decision],
|
|
159739
160068
|
conflicts: p2.conflicts,
|
|
159740
|
-
unmet: p2.observed ? metadataDiffs(item, p2.observed, target) : [],
|
|
160069
|
+
unmet: p2.observed ? [...metadataDiffs(item, p2.observed, target), ...screenshotUnmet(p2.reviewScreenshot, p2.observed)] : [],
|
|
159741
160070
|
readAt: readAt2
|
|
159742
160071
|
});
|
|
159743
160072
|
Object.assign(result.provisioning, await withAccessContext(context.identity, manifest.target, () => checkStatusPrice(item, p2.observed, pricing, catalog3)));
|
|
@@ -159745,7 +160074,7 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159745
160074
|
}
|
|
159746
160075
|
return iapResult({ target: manifest.target, identity: context.identity, items, generatedAt: readAt2 });
|
|
159747
160076
|
}
|
|
159748
|
-
var IapProvisionError, EDITABLE_VERSION_STATE, EDITABLE_PRODUCT_STATES, LOCKED_VERSION_STATES, OP_KINDS, LOCALE_OPS, CONDITIONAL_PRICE_NOTE, STATUS_OUTCOMES, isoDay, exactTarget, planError;
|
|
160077
|
+
var IapProvisionError, EDITABLE_VERSION_STATE, EDITABLE_PRODUCT_STATES, LOCKED_VERSION_STATES, SCREENSHOT_OPS, OP_KINDS, MD5_HEX, LOCALE_OPS, CONDITIONAL_PRICE_NOTE, STATUS_OUTCOMES, isoDay, exactTarget, LEFTOVER_SCREENSHOT_STATES, planError;
|
|
159749
160078
|
var init_iap_plan = __esm({
|
|
159750
160079
|
"../store-release/iap-plan.ts"() {
|
|
159751
160080
|
init_iap_api();
|
|
@@ -159754,6 +160083,7 @@ var init_iap_plan = __esm({
|
|
|
159754
160083
|
init_iap_pricing();
|
|
159755
160084
|
init_iap_result();
|
|
159756
160085
|
init_iap_price_status();
|
|
160086
|
+
init_iap_review_screenshot();
|
|
159757
160087
|
IapProvisionError = class extends Error {
|
|
159758
160088
|
constructor(reason, message) {
|
|
159759
160089
|
super(message);
|
|
@@ -159764,12 +160094,15 @@ var init_iap_plan = __esm({
|
|
|
159764
160094
|
EDITABLE_VERSION_STATE = "PREPARE_FOR_SUBMISSION";
|
|
159765
160095
|
EDITABLE_PRODUCT_STATES = /* @__PURE__ */ new Set(["MISSING_METADATA", "READY_TO_SUBMIT", "DEVELOPER_ACTION_NEEDED", "REJECTED"]);
|
|
159766
160096
|
LOCKED_VERSION_STATES = /* @__PURE__ */ new Set(["READY_FOR_REVIEW", "WAITING_FOR_REVIEW", "IN_REVIEW", "ACCEPTED", "APPROVED"]);
|
|
159767
|
-
|
|
160097
|
+
SCREENSHOT_OPS = /* @__PURE__ */ new Set(["uploadReviewScreenshot", "replaceReviewScreenshot"]);
|
|
160098
|
+
OP_KINDS = /* @__PURE__ */ new Set(["createProduct", "createVersion", "createLocalization", "updateLocalization", "setPrice", "changePrice", "setAvailability", ...SCREENSHOT_OPS]);
|
|
160099
|
+
MD5_HEX = /^[0-9a-f]{32}$/;
|
|
159768
160100
|
LOCALE_OPS = /* @__PURE__ */ new Set(["createLocalization", "updateLocalization"]);
|
|
159769
160101
|
CONDITIONAL_PRICE_NOTE = "the exact price point can only be looked up after the product exists \u2014 apply stops with a partial result if Apple has no point of exactly the requested amount";
|
|
159770
160102
|
STATUS_OUTCOMES = { create: "absent", update: "incomplete", reuse: "reused", conflict: "conflict" };
|
|
159771
160103
|
isoDay = (date) => date.toISOString().slice(0, 10);
|
|
159772
160104
|
exactTarget = (price) => price.rule === "atLeast" ? void 0 : price.amount;
|
|
160105
|
+
LEFTOVER_SCREENSHOT_STATES = /* @__PURE__ */ new Set(["AWAITING_UPLOAD", "FAILED"]);
|
|
159773
160106
|
planError = (message) => new IapProvisionError("plan", message);
|
|
159774
160107
|
}
|
|
159775
160108
|
});
|
|
@@ -159777,6 +160110,7 @@ var init_iap_plan = __esm({
|
|
|
159777
160110
|
// ../store-release/iap-apply.ts
|
|
159778
160111
|
function sameOp(a2, b2) {
|
|
159779
160112
|
if (a2.kind === "changePrice" && b2.kind === "changePrice") return a2.from === b2.from && a2.to === b2.to;
|
|
160113
|
+
if ("checksum" in a2 || "checksum" in b2) return "checksum" in a2 && "checksum" in b2 && a2.checksum === b2.checksum;
|
|
159780
160114
|
return a2.kind === b2.kind && ("locale" in a2 ? a2.locale : void 0) === ("locale" in b2 ? b2.locale : void 0);
|
|
159781
160115
|
}
|
|
159782
160116
|
function assertSameAccount(planned2, current) {
|
|
@@ -159797,9 +160131,19 @@ function driftOf(planned2, live3, today) {
|
|
|
159797
160131
|
const scheduleProblem = priceScheduleConflict(live3.observed?.priceSchedule, today);
|
|
159798
160132
|
if (scheduleProblem) return `${live3.productId}: ${scheduleProblem}`;
|
|
159799
160133
|
}
|
|
160134
|
+
const [plannedShot, liveShot] = [planned2.reviewScreenshot, live3.reviewScreenshot];
|
|
160135
|
+
if (plannedShot && liveShot && plannedShot.checksum !== liveShot.checksum) return `${live3.productId}: ${liveShot.fileName} changed since the plan was made`;
|
|
160136
|
+
if (replacesUnplannedScreenshot(planned2, live3)) return `${live3.productId}: a review screenshot was added in App Store Connect after the plan \u2014 make a new plan before replacing it`;
|
|
159800
160137
|
const unplanned = live3.ops.filter((op) => !planned2.ops.some((p2) => sameOp(p2, op)));
|
|
159801
160138
|
return unplanned.length ? `${live3.productId} now needs ${unplanned.map(describeOp).join(", ")}, which the plan did not list` : void 0;
|
|
159802
160139
|
}
|
|
160140
|
+
function replacesUnplannedScreenshot(planned2, live3) {
|
|
160141
|
+
if (!live3.ops.some((op) => op.kind === "replaceReviewScreenshot")) return false;
|
|
160142
|
+
const held = live3.observed?.reviewScreenshot;
|
|
160143
|
+
if (!held || isScreenshotLeftover(held)) return false;
|
|
160144
|
+
const seen = planned2.observed?.reviewScreenshot;
|
|
160145
|
+
return !seen || seen.id !== held.id || isScreenshotLeftover(seen);
|
|
160146
|
+
}
|
|
159803
160147
|
function assertNoDrift(plan, live3, today) {
|
|
159804
160148
|
const drift = [...live3].map(([i2, current]) => driftOf(plan.items[i2], current, today)).filter((d2) => d2 !== void 0);
|
|
159805
160149
|
if (!drift.length) return;
|
|
@@ -159852,6 +160196,50 @@ async function findLocalization(api2, versionId, locale, matchText) {
|
|
|
159852
160196
|
if (!found || matchText && (found.name !== matchText.name || found.description !== matchText.description)) return void 0;
|
|
159853
160197
|
return found;
|
|
159854
160198
|
}
|
|
160199
|
+
function plannedScreenshot(item, op, context) {
|
|
160200
|
+
const file2 = readReviewScreenshot(required(item.reviewScreenshot, "the review screenshot path"), context);
|
|
160201
|
+
if (!("checksum" in op) || file2.checksum !== op.checksum) throw new UnresolvedWriteError(`${file2.fileName} changed after the plan was made \u2014 make a new plan`);
|
|
160202
|
+
return file2;
|
|
160203
|
+
}
|
|
160204
|
+
async function reserveScreenshot(api2, resourceId, file2, overValid) {
|
|
160205
|
+
try {
|
|
160206
|
+
return await api2.reserveReviewScreenshot(resourceId, { fileName: file2.fileName, fileSize: file2.bytes.length });
|
|
160207
|
+
} catch (e2) {
|
|
160208
|
+
if (overValid && e2 instanceof AscError && e2.kind === "conflict") throw new UnresolvedWriteError(KEPT_EXISTING_SCREENSHOT);
|
|
160209
|
+
if (!(e2 instanceof AscError) || !AMBIGUOUS_WRITE_KINDS.has(e2.kind)) throw e2;
|
|
160210
|
+
throw new UnresolvedWriteError(`could not confirm the review screenshot reservation (${e2.message}). Make a new plan \u2014 it replaces an unfinished reservation.`);
|
|
160211
|
+
}
|
|
160212
|
+
}
|
|
160213
|
+
async function settledScreenshot(api2, resourceId, committed, sleep) {
|
|
160214
|
+
if (SETTLED_SCREENSHOT_STATES.has(committed.state)) return committed;
|
|
160215
|
+
const read = async () => {
|
|
160216
|
+
const current = await api2.readReviewScreenshot(resourceId);
|
|
160217
|
+
return current && SETTLED_SCREENSHOT_STATES.has(current.state) ? current : void 0;
|
|
160218
|
+
};
|
|
160219
|
+
return await pollFor(read, sleep) ?? committed;
|
|
160220
|
+
}
|
|
160221
|
+
async function uploadScreenshot(context, resourceId, file2) {
|
|
160222
|
+
const { api: api2, sleep } = context;
|
|
160223
|
+
const current = await api2.readReviewScreenshot(resourceId);
|
|
160224
|
+
if (current && screenshotMatches(current, file2.checksum)) return { state: "reconciled", resourceId: current.id };
|
|
160225
|
+
const reservation = await reserveScreenshot(api2, resourceId, file2, current !== void 0 && !isScreenshotLeftover(current));
|
|
160226
|
+
await api2.uploadReviewScreenshotParts(reservation, file2.bytes);
|
|
160227
|
+
const committed = async () => {
|
|
160228
|
+
const screenshot = await api2.readReviewScreenshot(resourceId);
|
|
160229
|
+
return screenshot?.id === reservation.id && screenshot.checksum === file2.checksum ? screenshot : void 0;
|
|
160230
|
+
};
|
|
160231
|
+
const { value, state } = await ensure({ write: () => api2.commitReviewScreenshot(reservation.id, file2.checksum), find: committed }, sleep);
|
|
160232
|
+
const settled = await settledScreenshot(api2, resourceId, value, sleep);
|
|
160233
|
+
if (settled.state === "FAILED") throw new UnresolvedWriteError(`Apple could not process the review screenshot: ${settled.errors.join("; ") || "no reason given"}`);
|
|
160234
|
+
return { state, resourceId: reservation.id };
|
|
160235
|
+
}
|
|
160236
|
+
async function deleteLeftoverScreenshot(context, resourceId) {
|
|
160237
|
+
const { api: api2, sleep } = context;
|
|
160238
|
+
const stale = await api2.readReviewScreenshot(resourceId);
|
|
160239
|
+
if (!stale || !isScreenshotLeftover(stale)) return;
|
|
160240
|
+
const gone = async () => (await api2.readReviewScreenshot(resourceId))?.id !== stale.id ? true : void 0;
|
|
160241
|
+
await ensure({ write: async () => (await api2.deleteReviewScreenshot(stale.id), true), find: gone }, sleep);
|
|
160242
|
+
}
|
|
159855
160243
|
function operationRunners(context, manifest) {
|
|
159856
160244
|
const { api: api2, sleep, pricing } = context;
|
|
159857
160245
|
const appId2 = manifest.target.appleAppId;
|
|
@@ -159917,6 +160305,13 @@ function operationRunners(context, manifest) {
|
|
|
159917
160305
|
const matches = async () => availabilityMatches(await readObservedAvailability(api2, resourceId), territories) ? true : void 0;
|
|
159918
160306
|
const { state } = await ensure({ write: async () => (await api2.createAvailability(resourceId, territories), true), find: matches }, sleep);
|
|
159919
160307
|
return { state };
|
|
160308
|
+
},
|
|
160309
|
+
uploadReviewScreenshot: async (run2, op) => uploadScreenshot(context, required(run2.resourceId, "the product id"), plannedScreenshot(run2.item, op, context)),
|
|
160310
|
+
replaceReviewScreenshot: async (run2, op) => {
|
|
160311
|
+
const resourceId = required(run2.resourceId, "the product id");
|
|
160312
|
+
const file2 = plannedScreenshot(run2.item, op, context);
|
|
160313
|
+
await deleteLeftoverScreenshot(context, resourceId);
|
|
160314
|
+
return uploadScreenshot(context, resourceId, file2);
|
|
159920
160315
|
}
|
|
159921
160316
|
};
|
|
159922
160317
|
}
|
|
@@ -159943,7 +160338,8 @@ async function runStep(runner2, run2, op, context, manifest) {
|
|
|
159943
160338
|
async function resumeFromApple(run2, remaining, context) {
|
|
159944
160339
|
const product = await context.api.readProduct(required(run2.resourceId, "the product id"));
|
|
159945
160340
|
if (!product) return { reason: "the product exists but cannot be read back yet \u2014 rerun apply later" };
|
|
159946
|
-
const
|
|
160341
|
+
const file2 = run2.item.reviewScreenshot === void 0 ? void 0 : readReviewScreenshot(run2.item.reviewScreenshot, context);
|
|
160342
|
+
const replanned = await planReviewScreenshot(context.api, await planForProduct(context.api, run2.item, product, context.pricing, context.now().toISOString().slice(0, 10)), file2);
|
|
159947
160343
|
if (replanned.decision === "conflict") return { reason: `the product already existed: ${replanned.conflicts.join("; ")}` };
|
|
159948
160344
|
const unplanned = replanned.ops.filter((op) => !remaining.some((r2) => sameOp(r2, op)));
|
|
159949
160345
|
if (unplanned.length) return { reason: `the product already existed and needs ${unplanned.map(describeOp).join(", ")}, which the plan did not list \u2014 make a new plan` };
|
|
@@ -159978,7 +160374,9 @@ async function readBack(run2, context, manifest) {
|
|
|
159978
160374
|
if (!run2.resourceId) return {};
|
|
159979
160375
|
try {
|
|
159980
160376
|
const product = await context.api.readProduct(run2.resourceId);
|
|
159981
|
-
|
|
160377
|
+
if (!product) return { failure: "Apple does not return it yet" };
|
|
160378
|
+
const observed = await observeProduct(context.api, product, context.now().toISOString().slice(0, 10));
|
|
160379
|
+
return { observed: run2.item.reviewScreenshot === void 0 ? observed : await withReviewScreenshot(context.api, observed) };
|
|
159982
160380
|
} catch (e2) {
|
|
159983
160381
|
return { failure: explainFailure(e2, context, manifest) };
|
|
159984
160382
|
}
|
|
@@ -159988,7 +160386,8 @@ async function unmetFor(item, observed, context) {
|
|
|
159988
160386
|
}
|
|
159989
160387
|
async function knownUnmetFor(item, planned2, context) {
|
|
159990
160388
|
if (!planned2.observed) return [];
|
|
159991
|
-
|
|
160389
|
+
const metadata2 = metadataDiffs(item, planned2.observed, planned2.targetPrice ?? await context.pricing.targetAmount(item.price));
|
|
160390
|
+
return [...metadata2, ...screenshotUnmet(planned2.reviewScreenshot, planned2.observed)];
|
|
159992
160391
|
}
|
|
159993
160392
|
async function applyItem(item, live3, context, manifest) {
|
|
159994
160393
|
const base = { target: manifest.target, item, readAt: context.now() };
|
|
@@ -160005,7 +160404,7 @@ async function applyItem(item, live3, context, manifest) {
|
|
|
160005
160404
|
};
|
|
160006
160405
|
const steps = await runOps(run2, live3.ops, context, manifest);
|
|
160007
160406
|
const { observed, failure } = await readBack(run2, context, manifest);
|
|
160008
|
-
const unmet = failure ? [`could not read the product back: ${failure}`] : await unmetFor(item, observed, context);
|
|
160407
|
+
const unmet = failure ? [`could not read the product back: ${failure}`] : [...await unmetFor(item, observed, context), ...screenshotUnmet(live3.reviewScreenshot, observed)];
|
|
160009
160408
|
const outcome = outcomeOf(live3.ops, steps, unmet);
|
|
160010
160409
|
return itemResult({ ...base, readAt: context.now(), observed, outcome, steps, unmet, appleResourceId: run2.resourceId });
|
|
160011
160410
|
}
|
|
@@ -160023,7 +160422,8 @@ function plannedResult(item, planned2, plan, context, manifest) {
|
|
|
160023
160422
|
async function applyIap(planDoc, applyContext) {
|
|
160024
160423
|
const plan = verifyPlan2(planDoc);
|
|
160025
160424
|
assertSameAccount(plan.identity, applyContext.identity);
|
|
160026
|
-
const
|
|
160425
|
+
const manifestDir = plan.manifestDir ?? applyContext.manifestDir;
|
|
160426
|
+
const context = { ...applyContext, ...manifestDir ? { manifestDir } : {}, pricing: applyContext.pricing ?? new PriceGrid(applyContext.api) };
|
|
160027
160427
|
const manifest = plan.manifest;
|
|
160028
160428
|
const refresh = plan.items.flatMap((planned2, i2) => needsRefresh(planned2) ? [i2] : []);
|
|
160029
160429
|
const live3 = await planItemsAt(context, manifest, refresh);
|
|
@@ -160046,23 +160446,26 @@ async function applyIap(planDoc, applyContext) {
|
|
|
160046
160446
|
}
|
|
160047
160447
|
return iapResult({ target: manifest.target, identity: context.identity, items, generatedAt: context.now() });
|
|
160048
160448
|
}
|
|
160049
|
-
var DEFERRED_REQUIREMENT, RECONCILE_READS, RECONCILE_BASE_WAIT_MS, AMBIGUOUS_WRITE_KINDS, UnresolvedWriteError, required;
|
|
160449
|
+
var DEFERRED_REQUIREMENT, RECONCILE_READS, RECONCILE_BASE_WAIT_MS, AMBIGUOUS_WRITE_KINDS, SETTLED_SCREENSHOT_STATES, UnresolvedWriteError, required, KEPT_EXISTING_SCREENSHOT;
|
|
160050
160450
|
var init_iap_apply = __esm({
|
|
160051
160451
|
"../store-release/iap-apply.ts"() {
|
|
160052
160452
|
init_iap_client();
|
|
160053
160453
|
init_iap_plan();
|
|
160054
160454
|
init_iap_pricing();
|
|
160455
|
+
init_iap_review_screenshot();
|
|
160055
160456
|
init_iap_result();
|
|
160056
160457
|
DEFERRED_REQUIREMENT = "deferred by --limit \u2014 rerun apply to continue; nothing was written for this product in this run";
|
|
160057
160458
|
RECONCILE_READS = 4;
|
|
160058
160459
|
RECONCILE_BASE_WAIT_MS = 1e3;
|
|
160059
160460
|
AMBIGUOUS_WRITE_KINDS = /* @__PURE__ */ new Set(["uncertain", "rateLimited", "conflict"]);
|
|
160461
|
+
SETTLED_SCREENSHOT_STATES = /* @__PURE__ */ new Set(["COMPLETE", "FAILED"]);
|
|
160060
160462
|
UnresolvedWriteError = class extends Error {
|
|
160061
160463
|
};
|
|
160062
160464
|
required = (value, what) => {
|
|
160063
160465
|
if (!value) throw new Error(`internal: ${what} is not known yet`);
|
|
160064
160466
|
return value;
|
|
160065
160467
|
};
|
|
160468
|
+
KEPT_EXISTING_SCREENSHOT = "Apple kept the existing review screenshot and refused a second one \u2014 replace it in App Store Connect (a review screenshot can be updated there but not removed)";
|
|
160066
160469
|
}
|
|
160067
160470
|
});
|
|
160068
160471
|
|
|
@@ -160186,11 +160589,11 @@ var init_credential_profile = __esm({
|
|
|
160186
160589
|
});
|
|
160187
160590
|
|
|
160188
160591
|
// ../store-release/iap-credentials.ts
|
|
160189
|
-
import { createHash as
|
|
160592
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
160190
160593
|
import { existsSync as existsSync73, readFileSync as readFileSync88, realpathSync as realpathSync12 } from "node:fs";
|
|
160191
160594
|
import { homedir as homedir10 } from "node:os";
|
|
160192
160595
|
function accountFingerprint(keyId, issuerId) {
|
|
160193
|
-
return `sha256:${
|
|
160596
|
+
return `sha256:${createHash39("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
|
|
160194
160597
|
}
|
|
160195
160598
|
function requireExplicitProfile(profileFlag, target) {
|
|
160196
160599
|
const profile = profileFlag?.trim();
|
|
@@ -160277,7 +160680,7 @@ var init_wix_payments_contract = __esm({
|
|
|
160277
160680
|
});
|
|
160278
160681
|
|
|
160279
160682
|
// ../store-release/iap-draft.ts
|
|
160280
|
-
import { createHash as
|
|
160683
|
+
import { createHash as createHash40 } from "node:crypto";
|
|
160281
160684
|
function fit(text9, max) {
|
|
160282
160685
|
const chars = [...text9];
|
|
160283
160686
|
return chars.length <= max ? text9 : `${chars.slice(0, max - 1).join("").trimEnd()}${ELLIPSIS}`;
|
|
@@ -160427,7 +160830,7 @@ var init_iap_draft = __esm({
|
|
|
160427
160830
|
TIER_DESCRIPTION = "Unlocks one item in the app";
|
|
160428
160831
|
ELLIPSIS = "\u2026";
|
|
160429
160832
|
entityKey = (entityType, entityId) => `${entityType}:${entityId}`;
|
|
160430
|
-
sha = (text9) =>
|
|
160833
|
+
sha = (text9) => createHash40("sha256").update(text9).digest("hex");
|
|
160431
160834
|
ENTITIES = { "&": "&", " ": " ", "<": "<", ">": ">", """: '"', "'": "'" };
|
|
160432
160835
|
MAX_SUFFIX = 24;
|
|
160433
160836
|
ReferenceNames = class {
|
|
@@ -160744,7 +161147,7 @@ var init_store_spec = __esm({
|
|
|
160744
161147
|
|
|
160745
161148
|
// src/iap-config-edit.ts
|
|
160746
161149
|
import { existsSync as existsSync74, readFileSync as readFileSync90 } from "node:fs";
|
|
160747
|
-
import { basename as
|
|
161150
|
+
import { basename as basename20, join as join75 } from "node:path";
|
|
160748
161151
|
import ts8 from "typescript";
|
|
160749
161152
|
function bindPurchasesAppInConfig(source, options) {
|
|
160750
161153
|
const fileName = options.fileName ?? "config.ts";
|
|
@@ -160831,14 +161234,14 @@ function withStoreBundle(dir, options) {
|
|
|
160831
161234
|
function previewIapConfigEdit(dir, options) {
|
|
160832
161235
|
const path2 = configEntry(dir);
|
|
160833
161236
|
if (!path2) return void 0;
|
|
160834
|
-
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${
|
|
160835
|
-
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync90(path2, "utf8"), { ...withStoreBundle(dir, options), fileName:
|
|
161237
|
+
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${basename20(path2)} is a symlink, so it would not be edited: add the purchases app in the file it points to.`] };
|
|
161238
|
+
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync90(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename20(path2) });
|
|
160836
161239
|
return { path: path2, changed, applied, conflicts, instructions };
|
|
160837
161240
|
}
|
|
160838
161241
|
async function applyIapConfigEdit(dir, options, validate4) {
|
|
160839
161242
|
const path2 = configEntry(dir);
|
|
160840
161243
|
if (!path2) return void 0;
|
|
160841
|
-
const fileName =
|
|
161244
|
+
const fileName = basename20(path2);
|
|
160842
161245
|
const refuse7 = (why) => ({ path: path2, changed: false, applied: [], conflicts: [], instructions: [why] });
|
|
160843
161246
|
if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: add the purchases app in the file it points to.`);
|
|
160844
161247
|
const original = readFileSync90(path2, "utf8");
|
|
@@ -161297,6 +161700,281 @@ var init_store_iap_connect = __esm({
|
|
|
161297
161700
|
}
|
|
161298
161701
|
});
|
|
161299
161702
|
|
|
161703
|
+
// src/store-iap-screenshots.ts
|
|
161704
|
+
import { dirname as dirname40, join as join76, relative as relative15 } from "node:path";
|
|
161705
|
+
function purchaseScreensFor(item) {
|
|
161706
|
+
const screen = item.wix && PURCHASE_SCREENS[item.wix.entityType];
|
|
161707
|
+
if (!screen || !item.wix) return [];
|
|
161708
|
+
const list = LIST_SCREENS[item.wix.entityType];
|
|
161709
|
+
return [{ screenId: `${screen}_${item.wix.entityId}` }, { screenId: screen, input: { id: item.wix.entityId } }, ...list ? [{ screenId: list }] : []];
|
|
161710
|
+
}
|
|
161711
|
+
function formatApplePrice(amount, currency, locale) {
|
|
161712
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(Number(amount));
|
|
161713
|
+
}
|
|
161714
|
+
function bindingHost(target, offers) {
|
|
161715
|
+
const appId2 = target.himiApp;
|
|
161716
|
+
const byEntity = new Map(offers.flatMap((offer) => offer.item.wix ? [[offer.item.wix.entityId, offer]] : []));
|
|
161717
|
+
const product = ({ item, displayPrice }) => ({ id: item.productId, type: item.type, displayName: item.localizations[0]?.name ?? item.referenceName, displayPrice });
|
|
161718
|
+
const answers = {
|
|
161719
|
+
"capability.app_info.get": () => ({ appId: appId2, bundleId: target.bundleId, platform: "ios" }),
|
|
161720
|
+
"capability.iap.appBinding": () => ({ status: "bound", binding: { purchasesAppId: RENDER_PURCHASES_APP_ID, himalayaAppId: appId2, bundleId: target.bundleId, siteId: target.wixSiteId } }),
|
|
161721
|
+
"capability.iap.getProducts": (params) => {
|
|
161722
|
+
const asked = new Set(String(params?.productIds ?? "").split(",").map((id) => id.trim()));
|
|
161723
|
+
return { products: offers.filter((offer) => asked.has(offer.item.productId)).map(product) };
|
|
161724
|
+
},
|
|
161725
|
+
"capability.iap.getUnfinishedTransactions": () => ({ status: "ok", transactions: [] })
|
|
161726
|
+
};
|
|
161727
|
+
const member = { generation: 1, kind: "member", memberId: RENDER_MEMBER_ID, siteId: target.wixSiteId, appId: appId2, ready: true };
|
|
161728
|
+
return {
|
|
161729
|
+
dispatch: (action, params) => answers[action]?.(params),
|
|
161730
|
+
wixCall: (method, path2, body) => {
|
|
161731
|
+
if (method === "GET") return MEMBER_OWN_READS.find((read) => read.path.test(path2))?.answer;
|
|
161732
|
+
if (method !== "POST" || !MAPPINGS_PATH.test(path2)) return void 0;
|
|
161733
|
+
const asked = body?.appProductIds;
|
|
161734
|
+
const ids = Array.isArray(asked) ? asked.filter((id) => typeof id === "string" && byEntity.has(id)) : [];
|
|
161735
|
+
return { mappings: ids.map((id) => {
|
|
161736
|
+
const { item } = byEntity.get(id);
|
|
161737
|
+
return { appProductId: id, storeProductId: item.productId, type: item.type === "consumable" ? "CONSUMABLE" : "NON_CONSUMABLE", active: true };
|
|
161738
|
+
}) };
|
|
161739
|
+
},
|
|
161740
|
+
wixApiSession: { identityBound: true, session: { current: () => member, subscribe: () => () => {
|
|
161741
|
+
} } }
|
|
161742
|
+
};
|
|
161743
|
+
}
|
|
161744
|
+
function offersPurchase(fields) {
|
|
161745
|
+
return PURCHASE_FLAGS.some((flag) => fields[`${flag}Disabled`] === false && fields[`${flag}Hidden`] !== true);
|
|
161746
|
+
}
|
|
161747
|
+
function isItemRow(fields, entityId, price) {
|
|
161748
|
+
const values = Object.values(fields).filter((v2) => typeof v2 === "string");
|
|
161749
|
+
return values.some((v2) => v2.toLowerCase() === entityId.toLowerCase()) && values.some((v2) => visibleText2(v2).includes(price));
|
|
161750
|
+
}
|
|
161751
|
+
function rowOffersPurchase(value, entityId, price) {
|
|
161752
|
+
if (Array.isArray(value)) return value.some((row) => rowOffersPurchase(row, entityId, price));
|
|
161753
|
+
if (!value || typeof value !== "object") return false;
|
|
161754
|
+
const fields = value;
|
|
161755
|
+
if (isItemRow(fields, entityId, price)) return offersPurchase(fields);
|
|
161756
|
+
return Object.values(fields).some((child) => rowOffersPurchase(child, entityId, price));
|
|
161757
|
+
}
|
|
161758
|
+
function purchaseEnabled(state, entityId, price) {
|
|
161759
|
+
return Object.values(state).some((service) => {
|
|
161760
|
+
if (!service || typeof service !== "object") return false;
|
|
161761
|
+
return offersPurchase(service) || Object.values(service).some((child) => rowOffersPurchase(child, entityId, price));
|
|
161762
|
+
});
|
|
161763
|
+
}
|
|
161764
|
+
function priceFor2(item, run2) {
|
|
161765
|
+
const amount = run2.applePrice(item) ?? (item.price.rule === "atLeast" ? void 0 : item.price.amount);
|
|
161766
|
+
if (amount === void 0) {
|
|
161767
|
+
return { skipped: run2.appleRead ? "App Store Connect has no price for it yet \u2014 run himi store iap apply first" : "Apple's price for an atLeast item is only known once App Store Connect is read \u2014 pass --profile" };
|
|
161768
|
+
}
|
|
161769
|
+
return formatApplePrice(amount, item.price.currency, item.localizations[0]?.locale ?? "en-US");
|
|
161770
|
+
}
|
|
161771
|
+
function unknownOnlyIds(run2) {
|
|
161772
|
+
const known = new Set(run2.manifest.items.map((item) => item.productId));
|
|
161773
|
+
return [...run2.only ?? []].filter((id) => !known.has(id)).map((productId) => ({ productId, skipped: "not in the manifest" }));
|
|
161774
|
+
}
|
|
161775
|
+
function select(run2) {
|
|
161776
|
+
return run2.manifest.items.flatMap((item, index) => {
|
|
161777
|
+
if (run2.only && !run2.only.has(item.productId)) return [];
|
|
161778
|
+
const screens = purchaseScreensFor(item);
|
|
161779
|
+
const report3 = { productId: item.productId, ...screens[0] ? { screenId: screens[0].screenId } : {} };
|
|
161780
|
+
const selected = (extra) => [{ index, item, screens, report: { ...report3, ...extra } }];
|
|
161781
|
+
if (!screens.length) return selected({ skipped: "no purchase screen: a price tier or an entity type the templates have no detail screen for" });
|
|
161782
|
+
const locked = run2.appleLocked?.(item);
|
|
161783
|
+
if (locked) return selected({ skipped: `is ${locked} \u2014 a live or in-review product's screenshot is never changed` });
|
|
161784
|
+
if (item.reviewScreenshot && !run2.force) return selected({ skipped: `already names ${item.reviewScreenshot} \u2014 pass --force to replace it` });
|
|
161785
|
+
const price = priceFor2(item, run2);
|
|
161786
|
+
return selected(typeof price === "string" ? { price } : price);
|
|
161787
|
+
});
|
|
161788
|
+
}
|
|
161789
|
+
function offersFor(selected, run2) {
|
|
161790
|
+
const others = run2.manifest.items.flatMap((item) => {
|
|
161791
|
+
if (item === selected.item || item.wix?.entityType !== selected.item.wix?.entityType) return [];
|
|
161792
|
+
const price = priceFor2(item, run2);
|
|
161793
|
+
return typeof price === "string" ? [{ item, displayPrice: price }] : [];
|
|
161794
|
+
});
|
|
161795
|
+
return [{ item: selected.item, displayPrice: selected.report.price }, ...others];
|
|
161796
|
+
}
|
|
161797
|
+
function notAPurchase(rendered, entityId, price) {
|
|
161798
|
+
if (rendered.problems.length) return `the screen reported problems while loading: ${rendered.problems.join("; ")}`;
|
|
161799
|
+
if (!visibleText2(rendered.html).includes(price)) return `did not show the Apple price ${price} \u2014 it is not a purchase screen this command knows, or it did not load`;
|
|
161800
|
+
if (!purchaseEnabled(rendered.state, entityId, price)) return "showed the price but no enabled buy or join action for this item";
|
|
161801
|
+
return void 0;
|
|
161802
|
+
}
|
|
161803
|
+
async function renderPurchaseScreen(selected, run2) {
|
|
161804
|
+
const host = bindingHost(run2.manifest.target, offersFor(selected, run2));
|
|
161805
|
+
const price = selected.report.price;
|
|
161806
|
+
const reasons = [];
|
|
161807
|
+
for (const screen of selected.screens) {
|
|
161808
|
+
let rendered;
|
|
161809
|
+
try {
|
|
161810
|
+
rendered = await run2.renderer.render({ contentDir: run2.contentDir, host, entityId: selected.item.wix.entityId, ...screen });
|
|
161811
|
+
} catch (e2) {
|
|
161812
|
+
if (e2 instanceof MissingScreenError) continue;
|
|
161813
|
+
return { skipped: `could not render ${screen.screenId}: ${e2.message}` };
|
|
161814
|
+
}
|
|
161815
|
+
const reason = notAPurchase(rendered, selected.item.wix.entityId, price);
|
|
161816
|
+
if (!reason) return { screenId: screen.screenId, html: rendered.html };
|
|
161817
|
+
reasons.push(`${screen.screenId} ${reason}`);
|
|
161818
|
+
}
|
|
161819
|
+
if (!reasons.length) return { skipped: `the app has none of these screens: ${selected.screens.map((s2) => s2.screenId).join(", ")}` };
|
|
161820
|
+
return { skipped: reasons.join("; ") };
|
|
161821
|
+
}
|
|
161822
|
+
async function shoot(selected, run2, outDir) {
|
|
161823
|
+
const found = await renderPurchaseScreen(selected, run2);
|
|
161824
|
+
if ("skipped" in found) return { ...selected.report, skipped: found.skipped };
|
|
161825
|
+
const report3 = { ...selected.report, screenId: found.screenId };
|
|
161826
|
+
const path2 = join76(outDir, `${selected.item.productId}.png`);
|
|
161827
|
+
try {
|
|
161828
|
+
run2.writeBytes(path2, await run2.renderer.capture(found.html, run2.contentDir));
|
|
161829
|
+
} catch (e2) {
|
|
161830
|
+
return { ...report3, skipped: `could not save the screenshot: ${e2.message}` };
|
|
161831
|
+
}
|
|
161832
|
+
return { ...report3, screenshot: relative15(dirname40(run2.manifestPath), path2) };
|
|
161833
|
+
}
|
|
161834
|
+
function visibleText2(html) {
|
|
161835
|
+
return html.replace(/ | | /gi, "\xA0").replace(/&/g, "&");
|
|
161836
|
+
}
|
|
161837
|
+
function manifestWithScreenshots(text9, shot) {
|
|
161838
|
+
const doc = JSON.parse(text9);
|
|
161839
|
+
for (const [index, path2] of shot) doc.items[index].reviewScreenshot = path2;
|
|
161840
|
+
return `${JSON.stringify(doc, null, 2)}
|
|
161841
|
+
`;
|
|
161842
|
+
}
|
|
161843
|
+
async function takeReviewScreenshots(run2) {
|
|
161844
|
+
const outDir = run2.outDir ?? join76(dirname40(run2.manifestPath), DEFAULT_OUT_DIR);
|
|
161845
|
+
const items = unknownOnlyIds(run2);
|
|
161846
|
+
const shot = /* @__PURE__ */ new Map();
|
|
161847
|
+
try {
|
|
161848
|
+
for (const selected of select(run2)) {
|
|
161849
|
+
const ready = !selected.report.skipped && !run2.dryRun;
|
|
161850
|
+
const report3 = ready ? await shoot(selected, run2, outDir) : selected.report;
|
|
161851
|
+
if (report3.screenshot) shot.set(selected.index, report3.screenshot);
|
|
161852
|
+
items.push(report3);
|
|
161853
|
+
}
|
|
161854
|
+
} finally {
|
|
161855
|
+
if (shot.size) run2.writeText(run2.manifestPath, manifestWithScreenshots(run2.manifestText, shot));
|
|
161856
|
+
}
|
|
161857
|
+
return { complete: items.every((i2) => !i2.skipped), items };
|
|
161858
|
+
}
|
|
161859
|
+
var MissingScreenError, REVIEW_SCREENSHOT_FRAME, DEFAULT_OUT_DIR, PURCHASE_SCREENS, LIST_SCREENS, RENDER_PURCHASES_APP_ID, RENDER_MEMBER_ID, MAPPINGS_PATH, MEMBER_OWN_READS, PURCHASE_FLAGS;
|
|
161860
|
+
var init_store_iap_screenshots = __esm({
|
|
161861
|
+
"src/store-iap-screenshots.ts"() {
|
|
161862
|
+
MissingScreenError = class extends Error {
|
|
161863
|
+
constructor(screenId) {
|
|
161864
|
+
super(`the app has no screen ${screenId}`);
|
|
161865
|
+
this.screenId = screenId;
|
|
161866
|
+
}
|
|
161867
|
+
};
|
|
161868
|
+
REVIEW_SCREENSHOT_FRAME = { width: 430, height: 932, scale: 3 };
|
|
161869
|
+
DEFAULT_OUT_DIR = "review-screenshots";
|
|
161870
|
+
PURCHASE_SCREENS = { storesProduct: "himi_product", onlineProgram: "himi_program", pricingPlan: "himi_plan" };
|
|
161871
|
+
LIST_SCREENS = { pricingPlan: "himi_plans" };
|
|
161872
|
+
RENDER_PURCHASES_APP_ID = "00000000-0000-4000-8000-00000000a99e";
|
|
161873
|
+
RENDER_MEMBER_ID = "00000000-0000-4000-8000-0000000be4e7";
|
|
161874
|
+
MAPPINGS_PATH = /\/v1\/iap\/mappings$/;
|
|
161875
|
+
MEMBER_OWN_READS = [{ path: /^\/pricing-plans\/v2\/member\/orders(\?|$)/, answer: { orders: [] } }];
|
|
161876
|
+
PURCHASE_FLAGS = ["buy", "join"];
|
|
161877
|
+
}
|
|
161878
|
+
});
|
|
161879
|
+
|
|
161880
|
+
// src/store-iap-screenshot-render.ts
|
|
161881
|
+
import { existsSync as existsSync75, mkdtempSync as mkdtempSync4, readFileSync as readFileSync91, rmSync as rmSync18 } from "node:fs";
|
|
161882
|
+
import { tmpdir as tmpdir5 } from "node:os";
|
|
161883
|
+
import { join as join77 } from "node:path";
|
|
161884
|
+
function renderProblems(render, entityId) {
|
|
161885
|
+
const problems = (render.liveErrors ?? []).map((e2) => `${e2.service}: ${e2.message}`);
|
|
161886
|
+
const ofItem = (call) => call.toLowerCase().includes(entityId.toLowerCase());
|
|
161887
|
+
const failed3 = (render.liveFailed ?? []).filter(ofItem);
|
|
161888
|
+
const attempted = (render.liveCalls ?? []).filter(ofItem).length;
|
|
161889
|
+
if (failed3.length > 0 && attempted <= failed3.length) problems.push(`reading the item failed (${failed3[0]}), so the screen could not show it`);
|
|
161890
|
+
return problems;
|
|
161891
|
+
}
|
|
161892
|
+
function workerBundleDir(result, dir) {
|
|
161893
|
+
if (result.compileErrors.length) {
|
|
161894
|
+
const detail = result.compileErrors.map((e2) => `${e2.bundle}: ${e2.errors.map((x2) => x2.text).join("; ")}`).join(" \xB7 ");
|
|
161895
|
+
throw new Error(`the app's screen code does not compile \u2014 fix it first (himi validate): ${detail}`);
|
|
161896
|
+
}
|
|
161897
|
+
return result.built.length > 0 ? dir : void 0;
|
|
161898
|
+
}
|
|
161899
|
+
function createReviewScreenRenderer() {
|
|
161900
|
+
const bundles = /* @__PURE__ */ new Map();
|
|
161901
|
+
let browser;
|
|
161902
|
+
function workerBundles(contentDir2) {
|
|
161903
|
+
let built = bundles.get(contentDir2);
|
|
161904
|
+
if (!built) {
|
|
161905
|
+
built = (async () => {
|
|
161906
|
+
const { buildContentBundles: buildContentBundles2, bundleOutDir: bundleOutDir2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
161907
|
+
return workerBundleDir(await buildContentBundles2(contentDir2, {}), bundleOutDir2(contentDir2));
|
|
161908
|
+
})();
|
|
161909
|
+
bundles.set(contentDir2, built);
|
|
161910
|
+
}
|
|
161911
|
+
return built;
|
|
161912
|
+
}
|
|
161913
|
+
async function launch() {
|
|
161914
|
+
let chromium;
|
|
161915
|
+
try {
|
|
161916
|
+
({ chromium } = await import("playwright"));
|
|
161917
|
+
} catch {
|
|
161918
|
+
throw new Error("taking a screenshot needs Playwright's Chromium: run `npx playwright install chromium`");
|
|
161919
|
+
}
|
|
161920
|
+
return chromium.launch();
|
|
161921
|
+
}
|
|
161922
|
+
return {
|
|
161923
|
+
async render({ contentDir: contentDir2, screenId, input, host, entityId }) {
|
|
161924
|
+
const { buildReleaseFromContent: buildReleaseFromContent2 } = await Promise.resolve().then(() => (init_build3(), build_exports2));
|
|
161925
|
+
const tier5Dir = await workerBundles(contentDir2);
|
|
161926
|
+
const out2 = mkdtempSync4(join77(tmpdir5(), "himi-iap-shot-"));
|
|
161927
|
+
try {
|
|
161928
|
+
const outcome = await buildReleaseFromContent2(contentDir2, out2, {
|
|
161929
|
+
...tier5Dir ? { tier5Dir } : {},
|
|
161930
|
+
collect: { render: { screenId, scheme: "light", png: false, hydrate: true, live: true, dumpState: true, width: REVIEW_SCREENSHOT_FRAME.width, host, ...input ? { input } : {} } }
|
|
161931
|
+
});
|
|
161932
|
+
const render = (outcome.renders ?? [])[0];
|
|
161933
|
+
if (!render) throw new MissingScreenError(screenId);
|
|
161934
|
+
if (!render.renderable || !render.html) throw new Error(render.reason ?? `${screenId} is not an SDUI screen`);
|
|
161935
|
+
return { html: render.html, problems: renderProblems(render, entityId), state: render.serviceState ?? {} };
|
|
161936
|
+
} finally {
|
|
161937
|
+
rmSync18(out2, { recursive: true, force: true });
|
|
161938
|
+
}
|
|
161939
|
+
},
|
|
161940
|
+
async capture(html, contentDir2) {
|
|
161941
|
+
const { pngPageHtml: pngPageHtml2, stabilizePngPage: stabilizePngPage2 } = await Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports));
|
|
161942
|
+
const tokensPath = join77(contentDir2, "tokens.json");
|
|
161943
|
+
const tokens2 = existsSync75(tokensPath) ? JSON.parse(readFileSync91(tokensPath, "utf8")) : null;
|
|
161944
|
+
const { width, height, scale } = REVIEW_SCREENSHOT_FRAME;
|
|
161945
|
+
const page = await (await (browser ??= launch())).newPage({ viewport: { width, height }, deviceScaleFactor: scale, colorScheme: "light" });
|
|
161946
|
+
try {
|
|
161947
|
+
await page.setContent(await pngPageHtml2({ html, tokens: tokens2, hasStickyFooter: true }), { waitUntil: "load" });
|
|
161948
|
+
await stabilizePngPage2(page, "light");
|
|
161949
|
+
await page.evaluate(FILL_PAGE_WITH_SCREEN_BACKGROUND);
|
|
161950
|
+
return new Uint8Array(await page.screenshot({ fullPage: false }));
|
|
161951
|
+
} finally {
|
|
161952
|
+
await page.close().catch(() => {
|
|
161953
|
+
});
|
|
161954
|
+
}
|
|
161955
|
+
},
|
|
161956
|
+
async close() {
|
|
161957
|
+
if (browser) await (await browser.catch(() => void 0))?.close().catch(() => {
|
|
161958
|
+
});
|
|
161959
|
+
}
|
|
161960
|
+
};
|
|
161961
|
+
}
|
|
161962
|
+
var FILL_PAGE_WITH_SCREEN_BACKGROUND;
|
|
161963
|
+
var init_store_iap_screenshot_render = __esm({
|
|
161964
|
+
"src/store-iap-screenshot-render.ts"() {
|
|
161965
|
+
init_store_iap_screenshots();
|
|
161966
|
+
FILL_PAGE_WITH_SCREEN_BACKGROUND = `(() => {
|
|
161967
|
+
const root = [...document.body.children].find((el) => el.tagName !== "STYLE");
|
|
161968
|
+
if (!root) return;
|
|
161969
|
+
const style = getComputedStyle(root);
|
|
161970
|
+
for (const el of [document.documentElement, document.body]) {
|
|
161971
|
+
el.style.backgroundColor = style.backgroundColor;
|
|
161972
|
+
el.style.backgroundImage = style.backgroundImage;
|
|
161973
|
+
}
|
|
161974
|
+
})()`;
|
|
161975
|
+
}
|
|
161976
|
+
});
|
|
161977
|
+
|
|
161300
161978
|
// src/serve-preview.ts
|
|
161301
161979
|
function parsePreviewTag(value) {
|
|
161302
161980
|
if (value === void 0 || value === "") return void 0;
|
|
@@ -161338,9 +162016,9 @@ __export(store_iap_exports, {
|
|
|
161338
162016
|
runStoreIap: () => runStoreIap
|
|
161339
162017
|
});
|
|
161340
162018
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
161341
|
-
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as
|
|
162019
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as readFileSync92, realpathSync as realpathSync13, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync30 } from "node:fs";
|
|
161342
162020
|
import { homedir as homedir11, hostname } from "node:os";
|
|
161343
|
-
import { join as
|
|
162021
|
+
import { dirname as dirname41, join as join78, resolve as resolve57 } from "node:path";
|
|
161344
162022
|
function scrubDeep(value, scrub) {
|
|
161345
162023
|
if (typeof value === "string") return scrub(value);
|
|
161346
162024
|
if (Array.isArray(value)) return value.map((v2) => scrubDeep(v2, scrub));
|
|
@@ -161348,7 +162026,7 @@ function scrubDeep(value, scrub) {
|
|
|
161348
162026
|
return value;
|
|
161349
162027
|
}
|
|
161350
162028
|
function failFrom(error, out2) {
|
|
161351
|
-
if (error instanceof IapManifestError) return out2.fail(`${error.label} is not a valid IAP manifest`, { problems: error.problems });
|
|
162029
|
+
if (error instanceof IapManifestError) return out2.fail(`${error.label} is not a valid IAP manifest`, { code: "manifest_invalid", problems: error.problems });
|
|
161352
162030
|
if (error instanceof IapProvisionError) return out2.fail(error.message, { code: error.reason, reason: error.reason }, error.reason === "drift" ? 1 : 2);
|
|
161353
162031
|
return out2.fail(error instanceof Error ? error.message : String(error));
|
|
161354
162032
|
}
|
|
@@ -161371,6 +162049,9 @@ function readInput(deps, path2, what) {
|
|
|
161371
162049
|
function readManifest2(deps, path2) {
|
|
161372
162050
|
return parseIapManifest(readInput(deps, path2, "manifest"), path2);
|
|
161373
162051
|
}
|
|
162052
|
+
function manifestDirOf(manifestPath) {
|
|
162053
|
+
return dirname41(resolve57(manifestPath));
|
|
162054
|
+
}
|
|
161374
162055
|
function readPlan(deps, path2) {
|
|
161375
162056
|
const text9 = readInput(deps, path2, "plan");
|
|
161376
162057
|
try {
|
|
@@ -161396,7 +162077,7 @@ function openSession(deps, out2, target, profile) {
|
|
|
161396
162077
|
const identity = { profile: creds.profile, team: creds.team, fingerprint: creds.fingerprint };
|
|
161397
162078
|
const api2 = deps.createApi(creds.key);
|
|
161398
162079
|
const journal2 = deps.openJournal(target.appleAppId);
|
|
161399
|
-
return { identity, api: api2, journal: journal2, planContext: { api: api2, identity, now: deps.now } };
|
|
162080
|
+
return { identity, api: api2, journal: journal2, planContext: { api: api2, identity, now: deps.now, readBytes: deps.readBytes } };
|
|
161400
162081
|
}
|
|
161401
162082
|
function printHeader(out2, identity, target) {
|
|
161402
162083
|
out2.line(` ${pad("account")}profile "${identity.profile}" \xB7 team ${identity.team} \xB7 key ${identity.fingerprint}`);
|
|
@@ -161465,6 +162146,7 @@ function printItemResult(out2, item) {
|
|
|
161465
162146
|
out2.line(` price drift: Wix ${wix} \xB7 Apple ${apple} \xB7 target ${wouldBe} ${currency} in ${baseTerritory}`);
|
|
161466
162147
|
}
|
|
161467
162148
|
for (const step of provisioning.steps.filter((s2) => s2.detail)) out2.line(` ${step.kind}${step.locale ? ` ${step.locale}` : ""} ${step.state}: ${step.detail}`);
|
|
162149
|
+
if (provisioning.reviewScreenshot?.observed) out2.line(` review screenshot: ${provisioning.reviewScreenshot.observed.fileName} ${provisioning.reviewScreenshot.observed.state}`);
|
|
161468
162150
|
for (const conflict of provisioning.conflicts) out2.line(` conflict: ${conflict}`);
|
|
161469
162151
|
for (const unmet of provisioning.unmet) out2.line(` unmet: ${unmet}`);
|
|
161470
162152
|
for (const remaining of provisioning.remainingRequirements) out2.line(` remaining: ${remaining}`);
|
|
@@ -161494,7 +162176,7 @@ async function planCommand(flags, deps, out2) {
|
|
|
161494
162176
|
const planPath = requireFlag(flags, "out", "plan");
|
|
161495
162177
|
const manifest = readManifest2(deps, manifestPath);
|
|
161496
162178
|
const session = openSession(deps, out2, manifest.target, profile);
|
|
161497
|
-
const plan = await planIap(manifest, session.planContext);
|
|
162179
|
+
const plan = await planIap(manifest, { ...session.planContext, manifestDir: manifestDirOf(manifestPath) });
|
|
161498
162180
|
writePlan(deps, out2, planPath, plan);
|
|
161499
162181
|
const summary2 = plan.items.map((i2) => ({ productId: i2.productId, decision: i2.decision, ops: i2.ops.length, conflicts: i2.conflicts }));
|
|
161500
162182
|
if (out2.json) out2.print({ ok: true, plan: planPath, items: summary2 });
|
|
@@ -161510,7 +162192,7 @@ function createLimit(flags) {
|
|
|
161510
162192
|
async function applyWithLock(deps, plan, session, limit) {
|
|
161511
162193
|
const release2 = deps.acquireLock(plan.target.appleAppId);
|
|
161512
162194
|
try {
|
|
161513
|
-
const context = {
|
|
162195
|
+
const context = { ...session.planContext, sleep: deps.sleep, journal: session.journal };
|
|
161514
162196
|
return await applyIap(plan, limit === void 0 ? context : { ...context, createLimit: limit });
|
|
161515
162197
|
} finally {
|
|
161516
162198
|
release2();
|
|
@@ -161556,7 +162238,7 @@ async function statusCommand(flags, deps, out2) {
|
|
|
161556
162238
|
return out2.fail("could not read the current Wix catalog \u2014 check owner authentication and site access; no manifest fallback was used", { ok: false, code: "wix_catalog_unavailable" });
|
|
161557
162239
|
}
|
|
161558
162240
|
}
|
|
161559
|
-
const result = await statusIap(manifest, session.planContext, catalog3?.items);
|
|
162241
|
+
const result = await statusIap(manifest, { ...session.planContext, manifestDir: manifestDirOf(manifestPath) }, catalog3?.items);
|
|
161560
162242
|
if (resultPath) writeJson(deps, out2, resultPath, result);
|
|
161561
162243
|
const code = result.complete ? void 0 : result.items.some((i2) => i2.provisioning.priceCheckIssue) ? "price_check_unavailable" : result.items.some((i2) => i2.provisioning.priceDrift) ? "price_drift" : "status_incomplete";
|
|
161562
162244
|
if (out2.json) out2.print({ ok: result.complete, ...code ? { code } : {}, result });
|
|
@@ -161796,6 +162478,71 @@ async function connectWith(flags, deps, out2) {
|
|
|
161796
162478
|
}
|
|
161797
162479
|
return code ? 1 : 0;
|
|
161798
162480
|
}
|
|
162481
|
+
async function appleFacts(flags, deps, out2, manifest) {
|
|
162482
|
+
const profile = textFlag(flags, "profile");
|
|
162483
|
+
if (!profile) return /* @__PURE__ */ new Map();
|
|
162484
|
+
const session = openSession(deps, out2, manifest.target, profile);
|
|
162485
|
+
const unscreenshotted = { ...manifest, items: manifest.items.map(({ reviewScreenshot: _shot, ...item }) => item) };
|
|
162486
|
+
const plans = await planItems(session.planContext, unscreenshotted);
|
|
162487
|
+
return new Map(plans.flatMap((plan, i2) => {
|
|
162488
|
+
const observed = plan.observed;
|
|
162489
|
+
if (!observed) return [];
|
|
162490
|
+
const base = observed.price?.baseTerritory === manifest.items[i2].price.baseTerritory && observed.price.customerPrices.length === 1;
|
|
162491
|
+
return [[plan.productId, { ...base ? { price: observed.price.customerPrices[0] } : {}, ...isLocked(observed) ? { locked: observed.state } : {} }]];
|
|
162492
|
+
}));
|
|
162493
|
+
}
|
|
162494
|
+
function printScreenshots(out2, report3, manifestPath, dryRun) {
|
|
162495
|
+
for (const item of report3.items) {
|
|
162496
|
+
if (item.skipped) out2.line(` \u2717 ${item.productId} ${item.skipped}`);
|
|
162497
|
+
else if (dryRun) out2.line(` \xB7 ${item.productId} would render ${item.screenId} at ${item.price}`);
|
|
162498
|
+
else out2.line(` \u2713 ${item.productId} ${item.screenshot} (${item.screenId}, ${item.price})`);
|
|
162499
|
+
}
|
|
162500
|
+
out2.line();
|
|
162501
|
+
if (dryRun) out2.line(" dry run \u2014 nothing was rendered or written.");
|
|
162502
|
+
else if (report3.items.some((i2) => i2.screenshot)) out2.line(` manifest updated: ${manifestPath} \u2014 next: himi store iap plan --manifest ${manifestPath} \u2026 uploads them.`);
|
|
162503
|
+
}
|
|
162504
|
+
async function screenshotsCommand(flags, deps, out2) {
|
|
162505
|
+
const manifestPath = requireFlag(flags, "manifest", "screenshots");
|
|
162506
|
+
const contentDir2 = requireFlag(flags, "content", "screenshots");
|
|
162507
|
+
const manifestText = readInput(deps, manifestPath, "manifest");
|
|
162508
|
+
const manifest = parseIapManifest(manifestText, manifestPath);
|
|
162509
|
+
const facts = await appleFacts(flags, deps, out2, manifest);
|
|
162510
|
+
const renderer = (deps.reviewScreenRenderer ?? createReviewScreenRenderer)();
|
|
162511
|
+
const only = textFlag(flags, "only");
|
|
162512
|
+
const outDir = textFlag(flags, "out-dir");
|
|
162513
|
+
const dryRun = flags["dry-run"] === true;
|
|
162514
|
+
let report3;
|
|
162515
|
+
try {
|
|
162516
|
+
report3 = await takeReviewScreenshots({
|
|
162517
|
+
manifest,
|
|
162518
|
+
manifestPath,
|
|
162519
|
+
manifestText,
|
|
162520
|
+
contentDir: contentDir2,
|
|
162521
|
+
renderer,
|
|
162522
|
+
applePrice: (item) => facts.get(item.productId)?.price,
|
|
162523
|
+
appleLocked: (item) => facts.get(item.productId)?.locked,
|
|
162524
|
+
appleRead: textFlag(flags, "profile") !== void 0,
|
|
162525
|
+
writeBytes: deps.writeBytes ?? writeBinaryFile,
|
|
162526
|
+
writeText: (path2, text9) => deps.writeFileAtomic(path2, text9),
|
|
162527
|
+
...only ? { only: new Set(only.split(",").map((id) => id.trim()).filter(Boolean)) } : {},
|
|
162528
|
+
...outDir ? { outDir: resolve57(outDir) } : {},
|
|
162529
|
+
force: flags.force === true,
|
|
162530
|
+
dryRun
|
|
162531
|
+
});
|
|
162532
|
+
} finally {
|
|
162533
|
+
await renderer.close?.();
|
|
162534
|
+
}
|
|
162535
|
+
const code = report3.complete ? void 0 : "screenshots_incomplete";
|
|
162536
|
+
if (out2.json) out2.print({ ok: report3.complete, ...code ? { code } : {}, manifest: manifestPath, items: report3.items });
|
|
162537
|
+
else printScreenshots(out2, report3, manifestPath, dryRun);
|
|
162538
|
+
return report3.complete ? 0 : 1;
|
|
162539
|
+
}
|
|
162540
|
+
function writeBinaryFile(path2, bytes2) {
|
|
162541
|
+
mkdirSync34(dirname41(path2), { recursive: true });
|
|
162542
|
+
const partial = `${path2}.${process.pid}.partial`;
|
|
162543
|
+
writeFileSync30(partial, bytes2);
|
|
162544
|
+
renameSync12(partial, path2);
|
|
162545
|
+
}
|
|
161799
162546
|
async function runStoreIap(pos, flags, io2, deps) {
|
|
161800
162547
|
const out2 = new CommandOutput(io2, flags.json === true);
|
|
161801
162548
|
const sub = pos[2];
|
|
@@ -161816,14 +162563,14 @@ function fileJournal(path2) {
|
|
|
161816
162563
|
}
|
|
161817
162564
|
function readLockSummary(path2) {
|
|
161818
162565
|
try {
|
|
161819
|
-
const { pid, host, at: at2 } = JSON.parse(
|
|
162566
|
+
const { pid, host, at: at2 } = JSON.parse(readFileSync92(path2, "utf8"));
|
|
161820
162567
|
return `pid ${pid} on ${host} since ${at2}`;
|
|
161821
162568
|
} catch {
|
|
161822
162569
|
return "unreadable lock";
|
|
161823
162570
|
}
|
|
161824
162571
|
}
|
|
161825
162572
|
function acquireApplyLock(dir, appleAppId) {
|
|
161826
|
-
const path2 =
|
|
162573
|
+
const path2 = join78(dir, "apply.lock");
|
|
161827
162574
|
const stamp = JSON.stringify({ pid: process.pid, host: hostname(), at: (/* @__PURE__ */ new Date()).toISOString(), token: randomUUID8() });
|
|
161828
162575
|
try {
|
|
161829
162576
|
writeFileSync30(path2, stamp, { flag: "wx", mode: 384 });
|
|
@@ -161836,15 +162583,15 @@ function acquireApplyLock(dir, appleAppId) {
|
|
|
161836
162583
|
return () => {
|
|
161837
162584
|
let current = "";
|
|
161838
162585
|
try {
|
|
161839
|
-
current =
|
|
162586
|
+
current = readFileSync92(path2, "utf8");
|
|
161840
162587
|
} catch {
|
|
161841
162588
|
return;
|
|
161842
162589
|
}
|
|
161843
|
-
if (current === stamp)
|
|
162590
|
+
if (current === stamp) rmSync19(path2, { force: true });
|
|
161844
162591
|
};
|
|
161845
162592
|
}
|
|
161846
162593
|
function stateDir(appleAppId) {
|
|
161847
|
-
const dir =
|
|
162594
|
+
const dir = join78(homedir11(), ".himalaya", "store-iap", appleAppId);
|
|
161848
162595
|
mkdirSync34(dir, { recursive: true, mode: 448 });
|
|
161849
162596
|
return dir;
|
|
161850
162597
|
}
|
|
@@ -161860,11 +162607,12 @@ async function confirmOnTerminal(question) {
|
|
|
161860
162607
|
}
|
|
161861
162608
|
function defaultStoreIapDeps() {
|
|
161862
162609
|
return {
|
|
161863
|
-
readFile: (path2) =>
|
|
162610
|
+
readFile: (path2) => readFileSync92(path2, "utf8"),
|
|
162611
|
+
readBytes: (path2) => readFileSync92(path2),
|
|
161864
162612
|
writeFileAtomic,
|
|
161865
162613
|
resolveCredentials: ({ profileFlag, target }) => resolveIapCredentials({ profileFlag, target }),
|
|
161866
162614
|
createApi: (key2) => createIapApi(createAscClient({ key: key2 })),
|
|
161867
|
-
openJournal: (appleAppId) => fileJournal(
|
|
162615
|
+
openJournal: (appleAppId) => fileJournal(join78(stateDir(appleAppId), "journal.jsonl")),
|
|
161868
162616
|
acquireLock: (appleAppId) => acquireApplyLock(stateDir(appleAppId), appleAppId),
|
|
161869
162617
|
canPrompt: () => process.stdin.isTTY === true,
|
|
161870
162618
|
wixTransport: (siteId) => ownerTransport(siteId),
|
|
@@ -161875,7 +162623,7 @@ function defaultStoreIapDeps() {
|
|
|
161875
162623
|
profileTeam: (profile) => resolveStoreCredentials({ app: profile, cfg: {}, profileFlag: profile, env: {} }).team,
|
|
161876
162624
|
confirm: confirmOnTerminal,
|
|
161877
162625
|
now: () => /* @__PURE__ */ new Date(),
|
|
161878
|
-
sleep: (ms2) => new Promise((
|
|
162626
|
+
sleep: (ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2))
|
|
161879
162627
|
};
|
|
161880
162628
|
}
|
|
161881
162629
|
var STORE_IAP_USAGE, SUMMARY_THRESHOLD, SUMMARY_DETAIL_LIMIT, UsageError, CommandOutput, pad, DECISION_ORDER, OUTCOME_ORDER, COMPLETE, DRAFT_MODES, TERRITORY_CODE, LOCALE_CODE, GRID_UNAVAILABLE_NOTE, KeyError, CredentialsError, writesPlanned, COMMANDS;
|
|
@@ -161897,10 +162645,12 @@ var init_store_iap = __esm({
|
|
|
161897
162645
|
init_iap_config_edit();
|
|
161898
162646
|
init_store_iap_catalog();
|
|
161899
162647
|
init_store_iap_connect();
|
|
162648
|
+
init_store_iap_screenshots();
|
|
162649
|
+
init_store_iap_screenshot_render();
|
|
161900
162650
|
init_store_iap_purchases();
|
|
161901
162651
|
init_serve_preview();
|
|
161902
162652
|
init_wix_owner();
|
|
161903
|
-
STORE_IAP_USAGE = "himi store iap draft|plan|apply|status|connect \u2014 draft --site <msid> --profile <name> --apple-app <id> --bundle <id> --base-territory <ISO3> --out <manifest.json> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <manifest.json>] [--report <file>] \xB7 plan --manifest <file> --profile <name> --out <plan.json> \xB7 apply --plan <plan.json> --profile <name> --out <result.json> [--yes] [--limit <n>] \xB7 status --manifest <file> --profile <name> [--out <file>] [--refresh-wix] \xB7 connect --manifest <file> --profile <name> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <report.json>]";
|
|
162653
|
+
STORE_IAP_USAGE = "himi store iap draft|plan|apply|status|connect|screenshots \u2014 draft --site <msid> --profile <name> --apple-app <id> --bundle <id> --base-territory <ISO3> --out <manifest.json> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <manifest.json>] [--report <file>] \xB7 plan --manifest <file> --profile <name> --out <plan.json> \xB7 apply --plan <plan.json> --profile <name> --out <result.json> [--yes] [--limit <n>] \xB7 status --manifest <file> --profile <name> [--out <file>] [--refresh-wix] \xB7 connect --manifest <file> --profile <name> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <report.json>] \xB7 screenshots --manifest <file> --content <app dir> [--profile <name>] [--out-dir <dir>] [--only <productId,\u2026>] [--force] [--dry-run]";
|
|
161904
162654
|
SUMMARY_THRESHOLD = 50;
|
|
161905
162655
|
SUMMARY_DETAIL_LIMIT = 20;
|
|
161906
162656
|
UsageError = class extends Error {
|
|
@@ -161961,7 +162711,8 @@ var init_store_iap = __esm({
|
|
|
161961
162711
|
plan: planCommand,
|
|
161962
162712
|
apply: applyCommand,
|
|
161963
162713
|
status: statusCommand,
|
|
161964
|
-
connect: connectCommand
|
|
162714
|
+
connect: connectCommand,
|
|
162715
|
+
screenshots: screenshotsCommand
|
|
161965
162716
|
};
|
|
161966
162717
|
}
|
|
161967
162718
|
});
|
|
@@ -162336,15 +163087,15 @@ __export(preflight_app_exports, {
|
|
|
162336
163087
|
analyzeSubmissionRecord: () => analyzeSubmissionRecord,
|
|
162337
163088
|
appIconState: () => appIconState,
|
|
162338
163089
|
isValidAppStoreSize: () => isValidAppStoreSize,
|
|
162339
|
-
jpegSize: () =>
|
|
163090
|
+
jpegSize: () => jpegSize2,
|
|
162340
163091
|
playListingAssets: () => playListingAssets,
|
|
162341
|
-
pngSize: () =>
|
|
163092
|
+
pngSize: () => pngSize2,
|
|
162342
163093
|
preflightApp: () => preflightApp,
|
|
162343
163094
|
profileAccount: () => profileAccount
|
|
162344
163095
|
});
|
|
162345
|
-
import { readFileSync as
|
|
162346
|
-
import { createHash as
|
|
162347
|
-
import { join as
|
|
163096
|
+
import { readFileSync as readFileSync93, existsSync as existsSync76, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
|
|
163097
|
+
import { createHash as createHash41 } from "node:crypto";
|
|
163098
|
+
import { join as join79 } from "node:path";
|
|
162348
163099
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
162349
163100
|
const f2 = [];
|
|
162350
163101
|
const has = (re2, s2) => re2.test(s2);
|
|
@@ -162408,13 +163159,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
162408
163159
|
}
|
|
162409
163160
|
}
|
|
162410
163161
|
async function preflightApp(app, opts = {}) {
|
|
162411
|
-
const projectYml =
|
|
162412
|
-
const storeConfig =
|
|
163162
|
+
const projectYml = existsSync76(iosProjectYml(app)) ? readFileSync93(iosProjectYml(app), "utf8") : "";
|
|
163163
|
+
const storeConfig = existsSync76(storeConfigPath(app)) ? readFileSync93(storeConfigPath(app), "utf8") : "";
|
|
162413
163164
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
162414
163165
|
const findings = analyze(
|
|
162415
163166
|
projectYml,
|
|
162416
163167
|
storeConfig,
|
|
162417
|
-
await appIconState(
|
|
163168
|
+
await appIconState(join79(appDir(app), "ios")),
|
|
162418
163169
|
profileAccount(app, storeConfig, opts)
|
|
162419
163170
|
);
|
|
162420
163171
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -162443,17 +163194,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
162443
163194
|
return f2;
|
|
162444
163195
|
}
|
|
162445
163196
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
162446
|
-
const root =
|
|
163197
|
+
const root = join79(storeDir(app), "metadata");
|
|
162447
163198
|
const out2 = /* @__PURE__ */ new Set();
|
|
162448
|
-
if (
|
|
163199
|
+
if (existsSync76(root)) {
|
|
162449
163200
|
for (const n2 of readdirSync34(root)) if (n2.endsWith(".txt")) out2.add(n2);
|
|
162450
163201
|
}
|
|
162451
|
-
if (
|
|
163202
|
+
if (existsSync76(join79(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
162452
163203
|
return out2;
|
|
162453
163204
|
}
|
|
162454
163205
|
function reviewInfoFiles(app) {
|
|
162455
|
-
const dir =
|
|
162456
|
-
if (!
|
|
163206
|
+
const dir = join79(storeDir(app), "review_information");
|
|
163207
|
+
if (!existsSync76(dir)) return /* @__PURE__ */ new Set();
|
|
162457
163208
|
return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
|
|
162458
163209
|
}
|
|
162459
163210
|
function isValidAppStoreSize(w2, h2) {
|
|
@@ -162462,7 +163213,7 @@ function isValidAppStoreSize(w2, h2) {
|
|
|
162462
163213
|
function isRequired69(w2, h2) {
|
|
162463
163214
|
return w2 === 1320 && h2 === 2868 || w2 === 1290 && h2 === 2796 || w2 === 2868 && h2 === 1320 || w2 === 2796 && h2 === 1290;
|
|
162464
163215
|
}
|
|
162465
|
-
function
|
|
163216
|
+
function pngSize2(buf) {
|
|
162466
163217
|
if (buf.length < 24 || buf.toString("ascii", 12, 16) !== "IHDR") return null;
|
|
162467
163218
|
return { w: buf.readUInt32BE(16), h: buf.readUInt32BE(20) };
|
|
162468
163219
|
}
|
|
@@ -162487,7 +163238,7 @@ function jpegStructure(bytes2) {
|
|
|
162487
163238
|
}
|
|
162488
163239
|
return null;
|
|
162489
163240
|
}
|
|
162490
|
-
function
|
|
163241
|
+
function jpegSize2(buf) {
|
|
162491
163242
|
if (buf.length < 4 || buf[0] !== 255 || buf[1] !== 216) return null;
|
|
162492
163243
|
let at2 = 2;
|
|
162493
163244
|
while (at2 + 9 < buf.length) {
|
|
@@ -162519,7 +163270,7 @@ function analyzePlayListing(assets) {
|
|
|
162519
163270
|
} else {
|
|
162520
163271
|
const { name, bytes: bytes2 } = assets.featureGraphic;
|
|
162521
163272
|
const isPng = bytes2.length > 8 && bytes2.toString("ascii", 1, 4) === "PNG";
|
|
162522
|
-
const size = isPng ?
|
|
163273
|
+
const size = isPng ? pngSize2(bytes2) : jpegSize2(bytes2);
|
|
162523
163274
|
if (!size) {
|
|
162524
163275
|
f2.push({
|
|
162525
163276
|
level: "error",
|
|
@@ -162563,12 +163314,12 @@ function analyzePlayListing(assets) {
|
|
|
162563
163314
|
return f2;
|
|
162564
163315
|
}
|
|
162565
163316
|
function playListingAssets(app, locale = "en-US") {
|
|
162566
|
-
const dir =
|
|
163317
|
+
const dir = join79(storeDir(app), "play", locale, "images");
|
|
162567
163318
|
const read = (names) => {
|
|
162568
163319
|
for (const name of names) {
|
|
162569
|
-
const p2 =
|
|
163320
|
+
const p2 = join79(dir, name);
|
|
162570
163321
|
try {
|
|
162571
|
-
if (statSync21(p2).isFile()) return { name, bytes:
|
|
163322
|
+
if (statSync21(p2).isFile()) return { name, bytes: readFileSync93(p2) };
|
|
162572
163323
|
} catch {
|
|
162573
163324
|
}
|
|
162574
163325
|
}
|
|
@@ -162599,26 +163350,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
162599
163350
|
return f2;
|
|
162600
163351
|
}
|
|
162601
163352
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
162602
|
-
const dir =
|
|
162603
|
-
if (!
|
|
163353
|
+
const dir = join79(storeDir(app), "metadata", locale);
|
|
163354
|
+
if (!existsSync76(dir)) return /* @__PURE__ */ new Set();
|
|
162604
163355
|
return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
|
|
162605
163356
|
}
|
|
162606
163357
|
function listScreenshots(app, locale = "en-US") {
|
|
162607
163358
|
const out2 = [];
|
|
162608
|
-
const flat =
|
|
162609
|
-
if (
|
|
163359
|
+
const flat = join79(storeDir(app), "screenshots", locale);
|
|
163360
|
+
if (existsSync76(flat)) {
|
|
162610
163361
|
for (const png of readdirSync34(flat).filter((n2) => n2.endsWith(".png"))) {
|
|
162611
|
-
const sz =
|
|
163362
|
+
const sz = pngSize2(readFileSync93(join79(flat, png)));
|
|
162612
163363
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
162613
163364
|
}
|
|
162614
163365
|
}
|
|
162615
|
-
const legacy =
|
|
162616
|
-
if (
|
|
163366
|
+
const legacy = join79(storeDir(app), "metadata", locale, "screenshots");
|
|
163367
|
+
if (existsSync76(legacy)) {
|
|
162617
163368
|
for (const deviceDir of readdirSync34(legacy)) {
|
|
162618
|
-
const d2 =
|
|
163369
|
+
const d2 = join79(legacy, deviceDir);
|
|
162619
163370
|
if (!statSync21(d2).isDirectory()) continue;
|
|
162620
163371
|
for (const png of readdirSync34(d2).filter((n2) => n2.endsWith(".png"))) {
|
|
162621
|
-
const sz =
|
|
163372
|
+
const sz = pngSize2(readFileSync93(join79(d2, png)));
|
|
162622
163373
|
if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
162623
163374
|
}
|
|
162624
163375
|
}
|
|
@@ -162626,13 +163377,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
162626
163377
|
return out2;
|
|
162627
163378
|
}
|
|
162628
163379
|
function placeholderHashes2() {
|
|
162629
|
-
const templateIos =
|
|
162630
|
-
if (!
|
|
163380
|
+
const templateIos = join79(appDir("_template"), "ios");
|
|
163381
|
+
if (!existsSync76(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
162631
163382
|
for (const target of readdirSync34(templateIos)) {
|
|
162632
|
-
const p2 =
|
|
163383
|
+
const p2 = join79(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
162633
163384
|
try {
|
|
162634
163385
|
if (!statSync21(p2).isFile()) continue;
|
|
162635
|
-
return [LEGACY_PLACEHOLDER_SHA2562,
|
|
163386
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash41("sha256").update(readFileSync93(p2)).digest("hex")];
|
|
162636
163387
|
} catch {
|
|
162637
163388
|
}
|
|
162638
163389
|
}
|
|
@@ -162663,13 +163414,13 @@ async function pixelIssues(bytes2) {
|
|
|
162663
163414
|
}
|
|
162664
163415
|
}
|
|
162665
163416
|
async function appIconState(iosDir) {
|
|
162666
|
-
if (!
|
|
163417
|
+
if (!existsSync76(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
162667
163418
|
for (const target of readdirSync34(iosDir)) {
|
|
162668
|
-
const p2 =
|
|
163419
|
+
const p2 = join79(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
162669
163420
|
try {
|
|
162670
163421
|
if (!statSync21(p2).isFile()) continue;
|
|
162671
|
-
const bytes2 =
|
|
162672
|
-
const hash2 =
|
|
163422
|
+
const bytes2 = readFileSync93(p2);
|
|
163423
|
+
const hash2 = createHash41("sha256").update(bytes2).digest("hex");
|
|
162673
163424
|
const pixels = await pixelIssues(bytes2);
|
|
162674
163425
|
return {
|
|
162675
163426
|
exists: true,
|
|
@@ -162735,7 +163486,7 @@ __export(asc_status_exports, {
|
|
|
162735
163486
|
ascStatus: () => ascStatus,
|
|
162736
163487
|
buildVerdict: () => buildVerdict
|
|
162737
163488
|
});
|
|
162738
|
-
import { readFileSync as
|
|
163489
|
+
import { readFileSync as readFileSync94 } from "node:fs";
|
|
162739
163490
|
function buildVerdict(builds) {
|
|
162740
163491
|
if (!builds.length) {
|
|
162741
163492
|
return "NO builds registered \u2014 if you uploaded recently and it's been >15 min, the binary was REJECTED IN PROCESSING (reason is email-only; run validate-binary.ts / scan-purpose-strings.ts to reproduce it).";
|
|
@@ -162749,7 +163500,7 @@ function buildVerdict(builds) {
|
|
|
162749
163500
|
function client(creds) {
|
|
162750
163501
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
162751
163502
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
162752
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
163503
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync94(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
162753
163504
|
return async (path2) => {
|
|
162754
163505
|
const r2 = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
162755
163506
|
return { status: r2.status, json: await r2.json().catch(() => ({})) };
|
|
@@ -162903,7 +163654,7 @@ var init_connector_token = __esm({
|
|
|
162903
163654
|
// ../../core/functions-secrets/src/vault.ts
|
|
162904
163655
|
import { createCipheriv, createDecipheriv as createDecipheriv2, randomBytes as randomBytes6 } from "node:crypto";
|
|
162905
163656
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
162906
|
-
import { dirname as
|
|
163657
|
+
import { dirname as dirname42 } from "node:path";
|
|
162907
163658
|
function createJsonSecretStore(filePath) {
|
|
162908
163659
|
const read = async () => {
|
|
162909
163660
|
try {
|
|
@@ -162916,7 +163667,7 @@ function createJsonSecretStore(filePath) {
|
|
|
162916
163667
|
}
|
|
162917
163668
|
};
|
|
162918
163669
|
const write2 = async (records) => {
|
|
162919
|
-
await mkdir(
|
|
163670
|
+
await mkdir(dirname42(filePath), { recursive: true });
|
|
162920
163671
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
162921
163672
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
162922
163673
|
`, { mode: 384 });
|
|
@@ -163014,7 +163765,7 @@ __export(secrets_exports, {
|
|
|
163014
163765
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
163015
163766
|
runSecretsCommand: () => runSecretsCommand
|
|
163016
163767
|
});
|
|
163017
|
-
import { readFileSync as
|
|
163768
|
+
import { readFileSync as readFileSync95 } from "node:fs";
|
|
163018
163769
|
function environment(value) {
|
|
163019
163770
|
if (value === "preview" || value === "production") return value;
|
|
163020
163771
|
throw new Error("--environment must be preview or production");
|
|
@@ -163045,7 +163796,7 @@ async function runSecretsCommand(operation, flags, io2, options = {}) {
|
|
|
163045
163796
|
io2.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
163046
163797
|
return 0;
|
|
163047
163798
|
}
|
|
163048
|
-
const value = options.readValue ? options.readValue() :
|
|
163799
|
+
const value = options.readValue ? options.readValue() : readFileSync95(0, "utf8").replace(/\r?\n$/, "");
|
|
163049
163800
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
163050
163801
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
163051
163802
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -163074,7 +163825,7 @@ async function runRemoteSecretsCommand(operation, flags, io2, options) {
|
|
|
163074
163825
|
}
|
|
163075
163826
|
let body;
|
|
163076
163827
|
if (operation !== "list") {
|
|
163077
|
-
const value = options.readValue ? options.readValue() :
|
|
163828
|
+
const value = options.readValue ? options.readValue() : readFileSync95(0, "utf8").replace(/\r?\n$/, "");
|
|
163078
163829
|
body = JSON.stringify({ value });
|
|
163079
163830
|
}
|
|
163080
163831
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -163268,7 +164019,7 @@ var init_site_member = __esm({
|
|
|
163268
164019
|
});
|
|
163269
164020
|
|
|
163270
164021
|
// src/notify-ping-all.ts
|
|
163271
|
-
import { createHash as
|
|
164022
|
+
import { createHash as createHash42 } from "node:crypto";
|
|
163272
164023
|
async function listApprovedMembers(input) {
|
|
163273
164024
|
const first = await scanMembers(input);
|
|
163274
164025
|
const second = await scanMembers(input);
|
|
@@ -163322,7 +164073,7 @@ async function scanMembers(input) {
|
|
|
163322
164073
|
}
|
|
163323
164074
|
}
|
|
163324
164075
|
function campaignRequestId(campaignId, memberId) {
|
|
163325
|
-
const bytes2 =
|
|
164076
|
+
const bytes2 = createHash42("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
|
|
163326
164077
|
bytes2[6] = bytes2[6] & 15 | 80;
|
|
163327
164078
|
bytes2[8] = bytes2[8] & 63 | 128;
|
|
163328
164079
|
const hex2 = bytes2.toString("hex");
|
|
@@ -163372,7 +164123,7 @@ __export(notify_ping_exports, {
|
|
|
163372
164123
|
runNotifyPing: () => runNotifyPing
|
|
163373
164124
|
});
|
|
163374
164125
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
163375
|
-
import { resolve as
|
|
164126
|
+
import { resolve as resolve58 } from "node:path";
|
|
163376
164127
|
function refuse6(io2, error, hint, exit = 2, extra = {}) {
|
|
163377
164128
|
io2.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
|
|
163378
164129
|
return exit;
|
|
@@ -163383,7 +164134,7 @@ async function runNotifyPing(flags, io2, deps = {}) {
|
|
|
163383
164134
|
const allMembers = flags["all-members"] === true;
|
|
163384
164135
|
if (allMembers && text8(flags["member-email"])) return refuse6(io2, "recipient_conflict", "Choose --all-members or --member-email.");
|
|
163385
164136
|
if (allMembers && flags["dry-run"] !== true && flags.yes !== true) return refuse6(io2, "confirmation_required", "Preview with --dry-run, then add --yes to send to every approved member.");
|
|
163386
|
-
const input = mergePushInputs(pushInputsFromContent(
|
|
164137
|
+
const input = mergePushInputs(pushInputsFromContent(resolve58(text8(flags.content) ?? process.cwd())), flags);
|
|
163387
164138
|
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f2) => !(allMembers && f2 === "member-email") && !text8(flags[f2]))];
|
|
163388
164139
|
if (missing.length) return refuse6(io2, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
|
|
163389
164140
|
const requestId2 = text8(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID9)();
|
|
@@ -163469,7 +164220,7 @@ async function runAllMembers(args) {
|
|
|
163469
164220
|
const result = await sendCampaign({
|
|
163470
164221
|
recipients,
|
|
163471
164222
|
campaignId: requestId2,
|
|
163472
|
-
wait: deps.wait ?? ((ms2) => new Promise((
|
|
164223
|
+
wait: deps.wait ?? ((ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2))),
|
|
163473
164224
|
onProgress: (completed) => {
|
|
163474
164225
|
if (completed % 10 === 0 || completed === recipients.length) {
|
|
163475
164226
|
io2.log(JSON.stringify({ ok: true, state: "progress", campaignId: requestId2, completed, recipients: recipients.length }));
|
|
@@ -163572,15 +164323,15 @@ __export(notify_exports, {
|
|
|
163572
164323
|
runNotify: () => runNotify,
|
|
163573
164324
|
saveAdminSession: () => saveAdminSession
|
|
163574
164325
|
});
|
|
163575
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as
|
|
164326
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as readFileSync96, writeFileSync as writeFileSync31 } from "node:fs";
|
|
163576
164327
|
import { homedir as homedir12 } from "node:os";
|
|
163577
|
-
import { dirname as
|
|
164328
|
+
import { dirname as dirname43, join as join80 } from "node:path";
|
|
163578
164329
|
function defaultSessionsPath() {
|
|
163579
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
164330
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join80(homedir12(), ".himalaya", "admin-sessions.json");
|
|
163580
164331
|
}
|
|
163581
164332
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
163582
164333
|
try {
|
|
163583
|
-
return JSON.parse(
|
|
164334
|
+
return JSON.parse(readFileSync96(path2, "utf8"));
|
|
163584
164335
|
} catch {
|
|
163585
164336
|
return {};
|
|
163586
164337
|
}
|
|
@@ -163588,10 +164339,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
163588
164339
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
163589
164340
|
const file2 = loadSessionsFile(path2);
|
|
163590
164341
|
file2.sessions = { ...file2.sessions, [adminUrl]: session };
|
|
163591
|
-
mkdirSync35(
|
|
164342
|
+
mkdirSync35(dirname43(path2), { recursive: true, mode: 448 });
|
|
163592
164343
|
writeFileSync31(path2, JSON.stringify(file2, null, 2) + "\n", { mode: 384 });
|
|
163593
164344
|
try {
|
|
163594
|
-
chmodSync3(
|
|
164345
|
+
chmodSync3(dirname43(path2), 448);
|
|
163595
164346
|
chmodSync3(path2, 384);
|
|
163596
164347
|
} catch {
|
|
163597
164348
|
}
|
|
@@ -163957,20 +164708,20 @@ __export(base44_auth_exports, {
|
|
|
163957
164708
|
usableBase44Auth: () => usableBase44Auth,
|
|
163958
164709
|
writeBase44Session: () => writeBase44Session
|
|
163959
164710
|
});
|
|
163960
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
164711
|
+
import { chmodSync as chmodSync4, existsSync as existsSync77, mkdirSync as mkdirSync36, readFileSync as readFileSync97, rmSync as rmSync20, writeFileSync as writeFileSync32 } from "node:fs";
|
|
163961
164712
|
import { homedir as homedir13 } from "node:os";
|
|
163962
|
-
import { dirname as
|
|
164713
|
+
import { dirname as dirname44, join as join81 } from "node:path";
|
|
163963
164714
|
function base44ApiBase(env = process.env) {
|
|
163964
164715
|
return (env.BASE44_API_URL?.trim() || "https://app.base44.com").replace(/\/+$/, "");
|
|
163965
164716
|
}
|
|
163966
164717
|
function base44SessionPath(home = homedir13()) {
|
|
163967
|
-
return
|
|
164718
|
+
return join81(home, ".himi", "base44", "session.json");
|
|
163968
164719
|
}
|
|
163969
164720
|
function readBase44Session(home) {
|
|
163970
164721
|
const p2 = base44SessionPath(home);
|
|
163971
|
-
if (!
|
|
164722
|
+
if (!existsSync77(p2)) return void 0;
|
|
163972
164723
|
try {
|
|
163973
|
-
const s2 = JSON.parse(
|
|
164724
|
+
const s2 = JSON.parse(readFileSync97(p2, "utf8"));
|
|
163974
164725
|
return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
|
|
163975
164726
|
} catch {
|
|
163976
164727
|
return void 0;
|
|
@@ -163978,7 +164729,7 @@ function readBase44Session(home) {
|
|
|
163978
164729
|
}
|
|
163979
164730
|
function writeBase44Session(session, home) {
|
|
163980
164731
|
const p2 = base44SessionPath(home);
|
|
163981
|
-
mkdirSync36(
|
|
164732
|
+
mkdirSync36(dirname44(p2), { recursive: true, mode: 448 });
|
|
163982
164733
|
writeFileSync32(p2, `${JSON.stringify(session, null, 2)}
|
|
163983
164734
|
`, { mode: 384 });
|
|
163984
164735
|
chmodSync4(p2, 384);
|
|
@@ -163986,8 +164737,8 @@ function writeBase44Session(session, home) {
|
|
|
163986
164737
|
}
|
|
163987
164738
|
function deleteBase44Session(home) {
|
|
163988
164739
|
const p2 = base44SessionPath(home);
|
|
163989
|
-
if (!
|
|
163990
|
-
|
|
164740
|
+
if (!existsSync77(p2)) return false;
|
|
164741
|
+
rmSync20(p2, { force: true });
|
|
163991
164742
|
return true;
|
|
163992
164743
|
}
|
|
163993
164744
|
function jwtClaims(token) {
|
|
@@ -164081,9 +164832,9 @@ async function base44DeviceLogin(opts) {
|
|
|
164081
164832
|
throw new Error("the Base44 sign-in code expired before it was approved \u2014 run `himi base44 login` again");
|
|
164082
164833
|
}
|
|
164083
164834
|
function importBase44CliSession(home = homedir13(), env = process.env) {
|
|
164084
|
-
const src =
|
|
164085
|
-
if (!
|
|
164086
|
-
const a2 = JSON.parse(
|
|
164835
|
+
const src = join81(home, ".base44", "auth", "auth.json");
|
|
164836
|
+
if (!existsSync77(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
|
|
164837
|
+
const a2 = JSON.parse(readFileSync97(src, "utf8"));
|
|
164087
164838
|
if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
|
|
164088
164839
|
const session = {
|
|
164089
164840
|
accessToken: a2.accessToken,
|
|
@@ -164254,10 +165005,10 @@ function assertPublicSiteUrl(raw) {
|
|
|
164254
165005
|
if (refusal) throw new Error(refusal);
|
|
164255
165006
|
}
|
|
164256
165007
|
function resolveAll(hostname3) {
|
|
164257
|
-
return new Promise((
|
|
165008
|
+
return new Promise((resolve65, reject) => {
|
|
164258
165009
|
dnsLookup(hostname3, { all: true, verbatim: true }, (err, addresses) => {
|
|
164259
165010
|
if (err) reject(err);
|
|
164260
|
-
else
|
|
165011
|
+
else resolve65(addresses);
|
|
164261
165012
|
});
|
|
164262
165013
|
});
|
|
164263
165014
|
}
|
|
@@ -164265,13 +165016,13 @@ function withAbort(start, signal, what) {
|
|
|
164265
165016
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
164266
165017
|
const work = start();
|
|
164267
165018
|
if (!signal) return work;
|
|
164268
|
-
return new Promise((
|
|
165019
|
+
return new Promise((resolve65, reject) => {
|
|
164269
165020
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
164270
165021
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
164271
|
-
work.then(
|
|
165022
|
+
work.then(resolve65, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
164272
165023
|
});
|
|
164273
165024
|
}
|
|
164274
|
-
async function pinAddress(url,
|
|
165025
|
+
async function pinAddress(url, resolve65 = resolveAll, signal) {
|
|
164275
165026
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
164276
165027
|
if (ipv4Octets(host)) {
|
|
164277
165028
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -164281,7 +165032,7 @@ async function pinAddress(url, resolve63 = resolveAll, signal) {
|
|
|
164281
165032
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
164282
165033
|
return { address: host, family: 6 };
|
|
164283
165034
|
}
|
|
164284
|
-
const addresses = await withAbort(() =>
|
|
165035
|
+
const addresses = await withAbort(() => resolve65(host), signal, `${host} lookup`);
|
|
164285
165036
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
164286
165037
|
const blocked = addresses.filter((a2) => isBlockedAddress(a2.address)).map((a2) => a2.address);
|
|
164287
165038
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -164321,7 +165072,7 @@ function copyIncomingHeaders(headers2) {
|
|
|
164321
165072
|
return out2;
|
|
164322
165073
|
}
|
|
164323
165074
|
function requestOnce(url, pinned, init) {
|
|
164324
|
-
return new Promise((
|
|
165075
|
+
return new Promise((resolve65, reject) => {
|
|
164325
165076
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
164326
165077
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
164327
165078
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -164351,7 +165102,7 @@ function requestOnce(url, pinned, init) {
|
|
|
164351
165102
|
reject(err);
|
|
164352
165103
|
return;
|
|
164353
165104
|
}
|
|
164354
|
-
|
|
165105
|
+
resolve65(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
|
|
164355
165106
|
}
|
|
164356
165107
|
);
|
|
164357
165108
|
req.on("error", reject);
|
|
@@ -166323,7 +167074,7 @@ var init_brand_font = __esm({
|
|
|
166323
167074
|
|
|
166324
167075
|
// src/site-analyze/write-artifacts.ts
|
|
166325
167076
|
import { mkdirSync as mkdirSync37, writeFileSync as writeFileSync33 } from "node:fs";
|
|
166326
|
-
import { join as
|
|
167077
|
+
import { join as join82 } from "node:path";
|
|
166327
167078
|
function attachVeloSources(book, sources, put) {
|
|
166328
167079
|
const byPath = new Map((sources ?? []).map((s2) => [s2.path, s2.text]));
|
|
166329
167080
|
for (const f2 of book.velo.files) {
|
|
@@ -166478,12 +167229,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
166478
167229
|
}
|
|
166479
167230
|
async function writeBusinessBook(result, opts) {
|
|
166480
167231
|
const out2 = opts.outDir;
|
|
166481
|
-
mkdirSync37(
|
|
166482
|
-
mkdirSync37(
|
|
167232
|
+
mkdirSync37(join82(out2, "evidence/pages"), { recursive: true });
|
|
167233
|
+
mkdirSync37(join82(out2, "media/catalog"), { recursive: true });
|
|
166483
167234
|
const files = [];
|
|
166484
167235
|
const put = (rel, body) => {
|
|
166485
|
-
const p2 =
|
|
166486
|
-
mkdirSync37(
|
|
167236
|
+
const p2 = join82(out2, rel);
|
|
167237
|
+
mkdirSync37(join82(p2, ".."), { recursive: true });
|
|
166487
167238
|
writeFileSync33(p2, body);
|
|
166488
167239
|
files.push(rel);
|
|
166489
167240
|
};
|
|
@@ -167387,11 +168138,11 @@ var init_analyze = __esm({
|
|
|
167387
168138
|
});
|
|
167388
168139
|
|
|
167389
168140
|
// src/base44-analyze/write-artifacts.ts
|
|
167390
|
-
import { existsSync as
|
|
167391
|
-
import { dirname as
|
|
168141
|
+
import { existsSync as existsSync78, mkdirSync as mkdirSync38, readFileSync as readFileSync98, rmSync as rmSync21, writeFileSync as writeFileSync34 } from "node:fs";
|
|
168142
|
+
import { dirname as dirname45, join as join83, resolve as resolve59, sep as sep19 } from "node:path";
|
|
167392
168143
|
function isBookFolder(dir) {
|
|
167393
168144
|
try {
|
|
167394
|
-
return JSON.parse(
|
|
168145
|
+
return JSON.parse(readFileSync98(join83(dir, "book.json"), "utf8")).kind === "base44-app-book";
|
|
167395
168146
|
} catch {
|
|
167396
168147
|
return false;
|
|
167397
168148
|
}
|
|
@@ -167465,7 +168216,7 @@ function renderBookMd(book) {
|
|
|
167465
168216
|
return L2.join("\n");
|
|
167466
168217
|
}
|
|
167467
168218
|
function writeBase44Book(result, outDir, opts = {}) {
|
|
167468
|
-
const out2 =
|
|
168219
|
+
const out2 = resolve59(outDir);
|
|
167469
168220
|
const book = result.book;
|
|
167470
168221
|
const files = [];
|
|
167471
168222
|
const shots = (opts.screenshots ?? []).filter((s2) => safeRel(s2.filename) && !s2.filename.includes("/"));
|
|
@@ -167478,26 +168229,26 @@ function writeBase44Book(result, outDir, opts = {}) {
|
|
|
167478
168229
|
const md = renderBookMd(book);
|
|
167479
168230
|
assertNoSecrets(json6);
|
|
167480
168231
|
assertNoSecrets(md);
|
|
167481
|
-
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) =>
|
|
168232
|
+
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync78(join83(out2, n2)));
|
|
167482
168233
|
if (owned.length) {
|
|
167483
168234
|
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`);
|
|
167484
|
-
for (const d2 of ["source", "screenshots"])
|
|
168235
|
+
for (const d2 of ["source", "screenshots"]) rmSync21(join83(out2, d2), { recursive: true, force: true });
|
|
167485
168236
|
}
|
|
167486
168237
|
mkdirSync38(out2, { recursive: true });
|
|
167487
|
-
writeFileSync34(
|
|
167488
|
-
writeFileSync34(
|
|
168238
|
+
writeFileSync34(join83(out2, "book.json"), json6);
|
|
168239
|
+
writeFileSync34(join83(out2, "BOOK.md"), md);
|
|
167489
168240
|
files.push("book.json", "BOOK.md");
|
|
167490
168241
|
for (const s2 of shots) {
|
|
167491
|
-
mkdirSync38(
|
|
167492
|
-
writeFileSync34(
|
|
168242
|
+
mkdirSync38(join83(out2, "screenshots"), { recursive: true });
|
|
168243
|
+
writeFileSync34(join83(out2, "screenshots", s2.filename), s2.bytes);
|
|
167493
168244
|
files.push(`screenshots/${s2.filename}`);
|
|
167494
168245
|
}
|
|
167495
|
-
const sourceRoot =
|
|
168246
|
+
const sourceRoot = join83(out2, "source");
|
|
167496
168247
|
for (const f2 of result.sourceFiles) {
|
|
167497
168248
|
if (!safeRel(f2.path)) continue;
|
|
167498
|
-
const dest =
|
|
168249
|
+
const dest = join83(sourceRoot, ...f2.path.split("/"));
|
|
167499
168250
|
if (!dest.startsWith(sourceRoot + sep19)) continue;
|
|
167500
|
-
mkdirSync38(
|
|
168251
|
+
mkdirSync38(dirname45(dest), { recursive: true });
|
|
167501
168252
|
writeFileSync34(dest, f2.bytes);
|
|
167502
168253
|
}
|
|
167503
168254
|
if (result.sourceFiles.length) files.push(`source/ (${result.sourceFiles.length} files)`);
|
|
@@ -168368,10 +169119,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
168368
169119
|
}
|
|
168369
169120
|
function createPromiseCallback(cb) {
|
|
168370
169121
|
let callback;
|
|
168371
|
-
let
|
|
169122
|
+
let resolve65;
|
|
168372
169123
|
let reject;
|
|
168373
169124
|
const promise = new Promise((_resolve, _reject) => {
|
|
168374
|
-
|
|
169125
|
+
resolve65 = _resolve;
|
|
168375
169126
|
reject = _reject;
|
|
168376
169127
|
});
|
|
168377
169128
|
if (typeof cb === "function") {
|
|
@@ -168387,7 +169138,7 @@ function createPromiseCallback(cb) {
|
|
|
168387
169138
|
callback = (err, result) => {
|
|
168388
169139
|
try {
|
|
168389
169140
|
if (err) reject(err);
|
|
168390
|
-
else
|
|
169141
|
+
else resolve65(result);
|
|
168391
169142
|
} catch (e2) {
|
|
168392
169143
|
reject(e2 instanceof Error ? e2 : new Error());
|
|
168393
169144
|
}
|
|
@@ -171039,9 +171790,9 @@ __export(cli_exports, {
|
|
|
171039
171790
|
systemTar: () => systemTar
|
|
171040
171791
|
});
|
|
171041
171792
|
import { execFile } from "node:child_process";
|
|
171042
|
-
import { mkdirSync as mkdirSync39, mkdtempSync as
|
|
171043
|
-
import { tmpdir as
|
|
171044
|
-
import { join as
|
|
171793
|
+
import { mkdirSync as mkdirSync39, mkdtempSync as mkdtempSync5, rmSync as rmSync22, writeFileSync as writeFileSync35 } from "node:fs";
|
|
171794
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
171795
|
+
import { join as join84, resolve as resolve60 } from "node:path";
|
|
171045
171796
|
import { promisify } from "node:util";
|
|
171046
171797
|
function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
171047
171798
|
return async (appId2) => {
|
|
@@ -171054,11 +171805,11 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
|
171054
171805
|
}
|
|
171055
171806
|
const bytes2 = await readCapped(res, MAX_TARBALL_BYTES);
|
|
171056
171807
|
if (!bytes2) throw new Error(`project download is over the ${MAX_TARBALL_BYTES}-byte cap`);
|
|
171057
|
-
const root =
|
|
171058
|
-
const cleanup = () =>
|
|
171808
|
+
const root = mkdtempSync5(join84(tmpdir6(), "himi-base44-"));
|
|
171809
|
+
const cleanup = () => rmSync22(root, { recursive: true, force: true });
|
|
171059
171810
|
try {
|
|
171060
|
-
const archive =
|
|
171061
|
-
const dir =
|
|
171811
|
+
const archive = join84(root, "project.tar");
|
|
171812
|
+
const dir = join84(root, "project");
|
|
171062
171813
|
writeFileSync35(archive, bytes2);
|
|
171063
171814
|
mkdirSync39(dir);
|
|
171064
171815
|
await extract(archive, dir);
|
|
@@ -171096,7 +171847,7 @@ async function runBase44Analyze(opts) {
|
|
|
171096
171847
|
now: opts.now ?? (() => /* @__PURE__ */ new Date())
|
|
171097
171848
|
};
|
|
171098
171849
|
const result = await analyzeBase44({ url: opts.url, appId: opts.appId, sample: opts.sample }, ports);
|
|
171099
|
-
const written = writeBase44Book(result,
|
|
171850
|
+
const written = writeBase44Book(result, resolve60(opts.cwd ?? process.cwd(), opts.outDir ?? ".himi/base44-book"), { screenshots });
|
|
171100
171851
|
return { ok: true, out: written.outDir, files: written.files, mode: result.book.mode, gaps: result.book.gaps, book: result.book };
|
|
171101
171852
|
}
|
|
171102
171853
|
var MAX_TARBALL_BYTES, systemTar;
|
|
@@ -171130,7 +171881,7 @@ var init_errors2 = __esm({
|
|
|
171130
171881
|
});
|
|
171131
171882
|
|
|
171132
171883
|
// src/one-app/collect.ts
|
|
171133
|
-
import { createHash as
|
|
171884
|
+
import { createHash as createHash43 } from "node:crypto";
|
|
171134
171885
|
function isObject2(value) {
|
|
171135
171886
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
171136
171887
|
}
|
|
@@ -171202,7 +171953,7 @@ function semanticFingerprint(structure) {
|
|
|
171202
171953
|
}
|
|
171203
171954
|
return JSON.stringify(value);
|
|
171204
171955
|
};
|
|
171205
|
-
return
|
|
171956
|
+
return createHash43("sha256").update(canonical4(structure, true)).digest("hex");
|
|
171206
171957
|
}
|
|
171207
171958
|
async function collectOneApp(input, deps = {}) {
|
|
171208
171959
|
if (typeof input.metaSiteId !== "string" || !UUID.test(input.metaSiteId)) {
|
|
@@ -171615,9 +172366,9 @@ __export(cli_exports2, {
|
|
|
171615
172366
|
ONE_APP_WORKFLOW: () => ONE_APP_WORKFLOW,
|
|
171616
172367
|
runOneAppCommand: () => runOneAppCommand
|
|
171617
172368
|
});
|
|
171618
|
-
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync40, openSync as openSync6, readFileSync as
|
|
171619
|
-
import { createHash as
|
|
171620
|
-
import { dirname as
|
|
172369
|
+
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync40, openSync as openSync6, readFileSync as readFileSync99, realpathSync as realpathSync14, writeFileSync as writeFileSync36 } from "node:fs";
|
|
172370
|
+
import { createHash as createHash44 } from "node:crypto";
|
|
172371
|
+
import { dirname as dirname46, join as join85, parse as parse3, resolve as resolve61 } from "node:path";
|
|
171621
172372
|
function readOptions(argv, cwd, commandIncluded) {
|
|
171622
172373
|
let cursor = 0;
|
|
171623
172374
|
const skipGlobalSwitches = () => {
|
|
@@ -171658,10 +172409,10 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
171658
172409
|
let prompt = flags.prompt ?? "";
|
|
171659
172410
|
if (flags["prompt-file"] !== void 0) {
|
|
171660
172411
|
try {
|
|
171661
|
-
const file2 =
|
|
172412
|
+
const file2 = resolve61(cwd, flags["prompt-file"]);
|
|
171662
172413
|
const stat2 = lstatSync21(file2);
|
|
171663
172414
|
if (!stat2.isFile() || stat2.size > MAX_PROMPT_BYTES) throw new Error("invalid prompt file");
|
|
171664
|
-
prompt =
|
|
172415
|
+
prompt = readFileSync99(file2, "utf8");
|
|
171665
172416
|
} catch {
|
|
171666
172417
|
throw new OneAppError("invalid_prompt", "Use a readable text file of at most 64 KiB for --prompt-file.");
|
|
171667
172418
|
}
|
|
@@ -171676,8 +172427,8 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
171676
172427
|
if (flags.dir !== void 0 && !flags.dir.trim()) {
|
|
171677
172428
|
throw new OneAppError("invalid_output_path", "Pass a parent directory with --dir.");
|
|
171678
172429
|
}
|
|
171679
|
-
const parentDir =
|
|
171680
|
-
const workspace =
|
|
172430
|
+
const parentDir = resolve61(cwd, flags.dir ?? ".");
|
|
172431
|
+
const workspace = join85(parentDir, name);
|
|
171681
172432
|
assertSafeParents(parentDir);
|
|
171682
172433
|
if (pathExists(workspace)) throw new OneAppError("output_exists", "The destination already exists. Choose a new --name or --dir.");
|
|
171683
172434
|
return { metaSiteId, appInstance, prompt, name, parentDir, workspace, target };
|
|
@@ -171706,7 +172457,7 @@ function assertSafeParents(path2) {
|
|
|
171706
172457
|
throw new OneAppError("invalid_output_path", "The output parent cannot be inspected.");
|
|
171707
172458
|
}
|
|
171708
172459
|
}
|
|
171709
|
-
current =
|
|
172460
|
+
current = dirname46(current);
|
|
171710
172461
|
}
|
|
171711
172462
|
}
|
|
171712
172463
|
function writePrivate(path2, contents, append) {
|
|
@@ -171734,7 +172485,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171734
172485
|
const hashes = {};
|
|
171735
172486
|
const diskWrite = deps.writeFile ?? writePrivate;
|
|
171736
172487
|
const put = (name, content) => {
|
|
171737
|
-
const path2 =
|
|
172488
|
+
const path2 = join85(evidenceDir, name);
|
|
171738
172489
|
try {
|
|
171739
172490
|
assertSafeParents(evidenceDir);
|
|
171740
172491
|
diskWrite(path2, content, false);
|
|
@@ -171742,7 +172493,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171742
172493
|
throw new OneAppError("artifact_write_failed", "Could not save the migration evidence. Existing files were kept.", { stage });
|
|
171743
172494
|
}
|
|
171744
172495
|
artifacts[name] = path2;
|
|
171745
|
-
hashes[name] =
|
|
172496
|
+
hashes[name] = createHash44("sha256").update(content).digest("hex");
|
|
171746
172497
|
return path2;
|
|
171747
172498
|
};
|
|
171748
172499
|
const progress = (nextStage) => {
|
|
@@ -171750,7 +172501,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171750
172501
|
if (!evidenceDir) return;
|
|
171751
172502
|
try {
|
|
171752
172503
|
assertSafeParents(evidenceDir);
|
|
171753
|
-
diskWrite(
|
|
172504
|
+
diskWrite(join85(evidenceDir, "progress.jsonl"), JSON.stringify({ stage, at: now() }) + "\n", true);
|
|
171754
172505
|
} catch {
|
|
171755
172506
|
throw new OneAppError("artifact_write_failed", "Could not record migration progress. Existing files were kept.", { stage });
|
|
171756
172507
|
}
|
|
@@ -171766,7 +172517,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171766
172517
|
assertSafeParents(options.parentDir);
|
|
171767
172518
|
mkdirSync40(options.workspace, { mode: 448 });
|
|
171768
172519
|
if (realpathSync14(options.workspace) !== options.workspace) throw new Error("destination changed");
|
|
171769
|
-
evidenceDir =
|
|
172520
|
+
evidenceDir = join85(options.workspace, ".himi", "one-app");
|
|
171770
172521
|
mkdirSync40(evidenceDir, { recursive: true, mode: 448 });
|
|
171771
172522
|
} catch (error) {
|
|
171772
172523
|
if (error.code === "EEXIST") {
|
|
@@ -173582,15 +174333,15 @@ var init_customer_build = __esm({
|
|
|
173582
174333
|
});
|
|
173583
174334
|
|
|
173584
174335
|
// src/site-analyze/apply.ts
|
|
173585
|
-
import { existsSync as
|
|
173586
|
-
import { dirname as
|
|
174336
|
+
import { existsSync as existsSync79, readFileSync as readFileSync100, writeFileSync as writeFileSync37, copyFileSync as copyFileSync2, mkdirSync as mkdirSync41, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
|
|
174337
|
+
import { dirname as dirname47, isAbsolute as isAbsolute8, join as join86, resolve as resolve62, sep as sep20 } from "node:path";
|
|
173587
174338
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
173588
174339
|
function unpairedRedirectNote(overlay) {
|
|
173589
174340
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
173590
174341
|
return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
|
|
173591
174342
|
}
|
|
173592
174343
|
function posix4(p2) {
|
|
173593
|
-
return
|
|
174344
|
+
return resolve62(p2).replace(/\\/g, "/");
|
|
173594
174345
|
}
|
|
173595
174346
|
function committedShellProvisioning(path2) {
|
|
173596
174347
|
return committedShellFor(posix4(path2));
|
|
@@ -173598,8 +174349,8 @@ function committedShellProvisioning(path2) {
|
|
|
173598
174349
|
function findRepoRoot(cwd) {
|
|
173599
174350
|
let dir = cwd;
|
|
173600
174351
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
173601
|
-
if (SHELL_NAMES2.some((name) =>
|
|
173602
|
-
const next =
|
|
174352
|
+
if (SHELL_NAMES2.some((name) => existsSync79(join86(dir, shellAppDir(name), "package.json")))) return dir;
|
|
174353
|
+
const next = dirname47(dir);
|
|
173603
174354
|
if (next === dir) break;
|
|
173604
174355
|
dir = next;
|
|
173605
174356
|
}
|
|
@@ -173624,7 +174375,7 @@ function assertNotCommitted(path2, forbidden2) {
|
|
|
173624
174375
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
173625
174376
|
);
|
|
173626
174377
|
}
|
|
173627
|
-
if (forbidden2 &&
|
|
174378
|
+
if (forbidden2 && resolve62(path2) === resolve62(forbidden2)) {
|
|
173628
174379
|
const named = committedShellProvisioning(forbidden2);
|
|
173629
174380
|
throw new Error(
|
|
173630
174381
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden2} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -173701,24 +174452,24 @@ function sameKnownSite(previous, next) {
|
|
|
173701
174452
|
}
|
|
173702
174453
|
function buildMergedContract(options) {
|
|
173703
174454
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
173704
|
-
const committedPath =
|
|
173705
|
-
if (!
|
|
174455
|
+
const committedPath = join86(appDir3, "provisioning.json");
|
|
174456
|
+
if (!existsSync79(committedPath)) {
|
|
173706
174457
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
173707
174458
|
}
|
|
173708
|
-
const committed = JSON.parse(
|
|
174459
|
+
const committed = JSON.parse(readFileSync100(committedPath, "utf8"));
|
|
173709
174460
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
173710
174461
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
173711
174462
|
const branding = merged.branding ?? {};
|
|
173712
174463
|
const staged = [];
|
|
173713
174464
|
const contained = (root, rel) => {
|
|
173714
174465
|
if (isAbsolute8(rel)) return void 0;
|
|
173715
|
-
const full =
|
|
173716
|
-
return full.startsWith(
|
|
174466
|
+
const full = resolve62(root, rel);
|
|
174467
|
+
return full.startsWith(resolve62(root) + sep20) ? full : void 0;
|
|
173717
174468
|
};
|
|
173718
174469
|
const stage = (fromRel, toRel) => {
|
|
173719
174470
|
const from = contained(packageDir, fromRel);
|
|
173720
|
-
const to2 = contained(
|
|
173721
|
-
if (!from || !to2 || !
|
|
174471
|
+
const to2 = contained(join86(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
174472
|
+
if (!from || !to2 || !existsSync79(from)) return void 0;
|
|
173722
174473
|
let real;
|
|
173723
174474
|
let realRoot;
|
|
173724
174475
|
try {
|
|
@@ -173730,7 +174481,7 @@ function buildMergedContract(options) {
|
|
|
173730
174481
|
if (!real.startsWith(realRoot + sep20)) return void 0;
|
|
173731
174482
|
try {
|
|
173732
174483
|
if (!statSync22(real).isFile()) return void 0;
|
|
173733
|
-
mkdirSync41(
|
|
174484
|
+
mkdirSync41(dirname47(to2), { recursive: true });
|
|
173734
174485
|
copyFileSync2(real, to2);
|
|
173735
174486
|
} catch {
|
|
173736
174487
|
return void 0;
|
|
@@ -173740,11 +174491,11 @@ function buildMergedContract(options) {
|
|
|
173740
174491
|
};
|
|
173741
174492
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
173742
174493
|
if (icon) branding.appIconPath = icon;
|
|
173743
|
-
const facesPath =
|
|
173744
|
-
if (
|
|
174494
|
+
const facesPath = join86(packageDir, "media/fonts/faces.json");
|
|
174495
|
+
if (existsSync79(facesPath)) {
|
|
173745
174496
|
let faces = [];
|
|
173746
174497
|
try {
|
|
173747
|
-
const parsed = JSON.parse(
|
|
174498
|
+
const parsed = JSON.parse(readFileSync100(facesPath, "utf8"));
|
|
173748
174499
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
173749
174500
|
} catch {
|
|
173750
174501
|
faces = [];
|
|
@@ -173765,10 +174516,10 @@ function buildMergedContract(options) {
|
|
|
173765
174516
|
merged.branding = branding;
|
|
173766
174517
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
173767
174518
|
`;
|
|
173768
|
-
const path2 =
|
|
174519
|
+
const path2 = join86(packageDir, "provisioning.contract.json");
|
|
173769
174520
|
writeFileSync37(path2, body);
|
|
173770
|
-
const localPath2 =
|
|
173771
|
-
mkdirSync41(
|
|
174521
|
+
const localPath2 = join86(appDir3, LOCAL_CONTRACT_REL);
|
|
174522
|
+
mkdirSync41(dirname47(localPath2), { recursive: true });
|
|
173772
174523
|
writeFileSync37(localPath2, body);
|
|
173773
174524
|
staged.push(localPath2);
|
|
173774
174525
|
return { path: path2, staged };
|
|
@@ -173802,10 +174553,10 @@ function catalogTypography(overlay, template) {
|
|
|
173802
174553
|
function staticFaqFor(overlay, overlayPath) {
|
|
173803
174554
|
const own5 = overlay.faq;
|
|
173804
174555
|
if (own5 !== void 0) return deriveStaticFaq(own5);
|
|
173805
|
-
const bookPath =
|
|
173806
|
-
if (!
|
|
174556
|
+
const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
|
|
174557
|
+
if (!existsSync79(bookPath)) return void 0;
|
|
173807
174558
|
try {
|
|
173808
|
-
const book = JSON.parse(
|
|
174559
|
+
const book = JSON.parse(readFileSync100(bookPath, "utf8"));
|
|
173809
174560
|
const copy = book?.copy;
|
|
173810
174561
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
173811
174562
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -173819,10 +174570,10 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
173819
174570
|
if (overlay.galleries !== void 0) return deriveStaticGalleries(
|
|
173820
174571
|
overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
|
|
173821
174572
|
);
|
|
173822
|
-
const bookPath =
|
|
173823
|
-
if (!
|
|
174573
|
+
const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
|
|
174574
|
+
if (!existsSync79(bookPath)) return void 0;
|
|
173824
174575
|
try {
|
|
173825
|
-
const book = JSON.parse(
|
|
174576
|
+
const book = JSON.parse(readFileSync100(bookPath, "utf8"));
|
|
173826
174577
|
if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
|
|
173827
174578
|
const galleries = deriveStaticGalleries(book.look.pages);
|
|
173828
174579
|
return galleries.length || book.look.complete === true ? galleries : void 0;
|
|
@@ -173831,11 +174582,11 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
173831
174582
|
}
|
|
173832
174583
|
}
|
|
173833
174584
|
async function applyOverlays(input) {
|
|
173834
|
-
const cwd =
|
|
174585
|
+
const cwd = resolve62(input.cwd);
|
|
173835
174586
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
173836
174587
|
assertKnownShell(shell);
|
|
173837
|
-
const overlay = JSON.parse(
|
|
173838
|
-
const tokens2 = JSON.parse(
|
|
174588
|
+
const overlay = JSON.parse(readFileSync100(input.overlayPath, "utf8"));
|
|
174589
|
+
const tokens2 = JSON.parse(readFileSync100(input.tokensPath, "utf8"));
|
|
173839
174590
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
173840
174591
|
if (faq !== void 0) overlay.faq = faq;
|
|
173841
174592
|
const galleries = staticGalleriesFor(overlay, input.overlayPath);
|
|
@@ -173852,15 +174603,15 @@ async function applyOverlays(input) {
|
|
|
173852
174603
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
173853
174604
|
);
|
|
173854
174605
|
}
|
|
173855
|
-
const appDir3 =
|
|
173856
|
-
const committedPath =
|
|
173857
|
-
const committedSite =
|
|
174606
|
+
const appDir3 = join86(repoRoot2, shellAppDir(shell));
|
|
174607
|
+
const committedPath = join86(appDir3, "provisioning.json");
|
|
174608
|
+
const committedSite = existsSync79(committedPath) ? JSON.parse(readFileSync100(committedPath, "utf8")).site : void 0;
|
|
173858
174609
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
173859
174610
|
throw new Error(
|
|
173860
174611
|
`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.`
|
|
173861
174612
|
);
|
|
173862
174613
|
}
|
|
173863
|
-
const packageDir =
|
|
174614
|
+
const packageDir = dirname47(resolve62(input.overlayPath));
|
|
173864
174615
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
173865
174616
|
wrote.push(...staged);
|
|
173866
174617
|
const r2 = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -173881,9 +174632,9 @@ async function applyOverlays(input) {
|
|
|
173881
174632
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
173882
174633
|
};
|
|
173883
174634
|
}
|
|
173884
|
-
const pkgProv =
|
|
174635
|
+
const pkgProv = join86(cwd, "provisioning.json");
|
|
173885
174636
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
173886
|
-
const contentPath =
|
|
174637
|
+
const contentPath = join86(cwd, "himalaya.content.json");
|
|
173887
174638
|
const syncViewNames = (before, after) => {
|
|
173888
174639
|
const content = readContentManifest(cwd);
|
|
173889
174640
|
if (!content) return;
|
|
@@ -173895,8 +174646,8 @@ async function applyOverlays(input) {
|
|
|
173895
174646
|
};
|
|
173896
174647
|
let packageFaq = faq;
|
|
173897
174648
|
let packageGalleries = galleries;
|
|
173898
|
-
if (
|
|
173899
|
-
const cur = JSON.parse(
|
|
174649
|
+
if (existsSync79(pkgProv)) {
|
|
174650
|
+
const cur = JSON.parse(readFileSync100(pkgProv, "utf8"));
|
|
173900
174651
|
if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
|
|
173901
174652
|
const merged = deepMerge4(cur, overlay);
|
|
173902
174653
|
packageFaq = merged.faq;
|
|
@@ -173912,9 +174663,9 @@ async function applyOverlays(input) {
|
|
|
173912
174663
|
if (Array.isArray(packageGalleries) && packageGalleries.length && !overlay.installedVerticals.includes("galleries")) {
|
|
173913
174664
|
overlay.installedVerticals.push("galleries");
|
|
173914
174665
|
}
|
|
173915
|
-
const pkgTokens =
|
|
173916
|
-
if (
|
|
173917
|
-
const cur = JSON.parse(
|
|
174666
|
+
const pkgTokens = join86(cwd, "tokens.json");
|
|
174667
|
+
if (existsSync79(pkgTokens) && (tokens2.colors || tokens2.typography)) {
|
|
174668
|
+
const cur = JSON.parse(readFileSync100(pkgTokens, "utf8"));
|
|
173918
174669
|
let tokensIn = tokens2;
|
|
173919
174670
|
if (tokens2.typography) {
|
|
173920
174671
|
const fonts = catalogTypography(tokens2.typography, cur.typography);
|
|
@@ -173939,9 +174690,9 @@ async function applyOverlays(input) {
|
|
|
173939
174690
|
wrote.push(pkgTokens);
|
|
173940
174691
|
}
|
|
173941
174692
|
const homeAction = homeRefreshActionId(shell);
|
|
173942
|
-
const homeSrc =
|
|
173943
|
-
if (homeAction &&
|
|
173944
|
-
const prev =
|
|
174693
|
+
const homeSrc = join86(cwd, "dev/index.ts");
|
|
174694
|
+
if (homeAction && existsSync79(homeSrc)) {
|
|
174695
|
+
const prev = readFileSync100(homeSrc, "utf8");
|
|
173945
174696
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
173946
174697
|
let next = patched.src;
|
|
173947
174698
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -173976,13 +174727,13 @@ async function applyOverlays(input) {
|
|
|
173976
174727
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
173977
174728
|
}
|
|
173978
174729
|
}
|
|
173979
|
-
if (!input.iconPath || !
|
|
173980
|
-
const book = input.iconPath ?
|
|
174730
|
+
if (!input.iconPath || !existsSync79(input.iconPath)) {
|
|
174731
|
+
const book = input.iconPath ? dirname47(dirname47(resolve62(input.iconPath))) : void 0;
|
|
173981
174732
|
notes.push(
|
|
173982
174733
|
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"
|
|
173983
174734
|
);
|
|
173984
174735
|
}
|
|
173985
|
-
if (input.iconPath &&
|
|
174736
|
+
if (input.iconPath && existsSync79(input.iconPath)) {
|
|
173986
174737
|
try {
|
|
173987
174738
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
173988
174739
|
wrote.push(...installed.wrote);
|
|
@@ -174940,8 +175691,8 @@ __export(cli_exports3, {
|
|
|
174940
175691
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
174941
175692
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
174942
175693
|
});
|
|
174943
|
-
import { existsSync as
|
|
174944
|
-
import { resolve as
|
|
175694
|
+
import { existsSync as existsSync80, readFileSync as readFileSync101 } from "node:fs";
|
|
175695
|
+
import { resolve as resolve63 } from "node:path";
|
|
174945
175696
|
function applyNeedsClient(shell) {
|
|
174946
175697
|
if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
|
|
174947
175698
|
return !isSiteShell(shell);
|
|
@@ -174965,7 +175716,7 @@ async function runSiteAnalyze(opts) {
|
|
|
174965
175716
|
const assetFetch = assetFetchFor(opts);
|
|
174966
175717
|
const siteFetch = guardedSiteFetch;
|
|
174967
175718
|
const cwd = opts.cwd ?? process.cwd();
|
|
174968
|
-
const outDir =
|
|
175719
|
+
const outDir = resolve63(cwd, opts.outDir ?? ".himi/business-book");
|
|
174969
175720
|
let ownerAuth;
|
|
174970
175721
|
let msid;
|
|
174971
175722
|
const ownerSite = ownerSiteFor(opts);
|
|
@@ -174992,14 +175743,14 @@ async function runSiteAnalyze(opts) {
|
|
|
174992
175743
|
if (opts.shell !== void 0 && isSiteShell(opts.shell)) {
|
|
174993
175744
|
try {
|
|
174994
175745
|
const kind = siteKindForOrigin(result.book.input.siteUrl);
|
|
174995
|
-
const book = kind === "base44" ? base44BookRoutes(
|
|
175746
|
+
const book = kind === "base44" ? base44BookRoutes(resolve63(cwd, ".himi/base44-book/book.json"), result.book.input.siteUrl) : void 0;
|
|
174996
175747
|
const routes = book?.routes;
|
|
174997
175748
|
if (book?.skipped) result.warnings = [...result.warnings ?? [], book.skipped];
|
|
174998
175749
|
const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look, kind, routes });
|
|
174999
|
-
const prevOverlayPath =
|
|
175000
|
-
const prevSite =
|
|
175750
|
+
const prevOverlayPath = resolve63(outDir, "provisioning.overlay.json");
|
|
175751
|
+
const prevSite = existsSync80(prevOverlayPath) ? (() => {
|
|
175001
175752
|
try {
|
|
175002
|
-
return JSON.parse(
|
|
175753
|
+
return JSON.parse(readFileSync101(prevOverlayPath, "utf8")).site;
|
|
175003
175754
|
} catch {
|
|
175004
175755
|
return void 0;
|
|
175005
175756
|
}
|
|
@@ -175016,9 +175767,9 @@ async function runSiteAnalyze(opts) {
|
|
|
175016
175767
|
];
|
|
175017
175768
|
}
|
|
175018
175769
|
}
|
|
175019
|
-
const previousOverlay =
|
|
175770
|
+
const previousOverlay = resolve63(outDir, "provisioning.overlay.json");
|
|
175020
175771
|
carryOverGoals(
|
|
175021
|
-
|
|
175772
|
+
existsSync80(previousOverlay) ? readFileSync101(previousOverlay, "utf8") : void 0,
|
|
175022
175773
|
result.provisioningOverlay
|
|
175023
175774
|
);
|
|
175024
175775
|
const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
|
|
@@ -175037,9 +175788,9 @@ async function runSiteAnalyze(opts) {
|
|
|
175037
175788
|
if (opts.apply) {
|
|
175038
175789
|
applied = await applyOverlays({
|
|
175039
175790
|
cwd,
|
|
175040
|
-
overlayPath:
|
|
175041
|
-
tokensPath:
|
|
175042
|
-
iconPath:
|
|
175791
|
+
overlayPath: resolve63(outDir, "provisioning.overlay.json"),
|
|
175792
|
+
tokensPath: resolve63(outDir, "tokens.overlay.json"),
|
|
175793
|
+
iconPath: resolve63(outDir, "media/icon.png"),
|
|
175043
175794
|
shell: opts.shell
|
|
175044
175795
|
});
|
|
175045
175796
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -175075,8 +175826,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
175075
175826
|
const token = opts.token ?? await siteToken(msid);
|
|
175076
175827
|
let source;
|
|
175077
175828
|
if (opts.sourcePath) {
|
|
175078
|
-
const p2 =
|
|
175079
|
-
source =
|
|
175829
|
+
const p2 = resolve63(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
175830
|
+
source = readFileSync101(p2, "utf8");
|
|
175080
175831
|
}
|
|
175081
175832
|
let body;
|
|
175082
175833
|
if (opts.bodyRaw != null) {
|
|
@@ -175104,9 +175855,9 @@ async function runSiteFunctionCli(opts) {
|
|
|
175104
175855
|
});
|
|
175105
175856
|
}
|
|
175106
175857
|
function base44BookRoutes(bookPath, siteUrl) {
|
|
175107
|
-
if (!
|
|
175858
|
+
if (!existsSync80(bookPath)) return void 0;
|
|
175108
175859
|
try {
|
|
175109
|
-
const book = JSON.parse(
|
|
175860
|
+
const book = JSON.parse(readFileSync101(bookPath, "utf8"));
|
|
175110
175861
|
if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
|
|
175111
175862
|
const host = (u2) => {
|
|
175112
175863
|
try {
|
|
@@ -175155,7 +175906,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
175155
175906
|
cached2 = fromEnv;
|
|
175156
175907
|
return fromEnv;
|
|
175157
175908
|
}
|
|
175158
|
-
const token = await new Promise((
|
|
175909
|
+
const token = await new Promise((resolve65, reject) => {
|
|
175159
175910
|
let child;
|
|
175160
175911
|
try {
|
|
175161
175912
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -175184,7 +175935,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
175184
175935
|
const scan = (d2) => {
|
|
175185
175936
|
out2 += String(d2);
|
|
175186
175937
|
const m2 = out2.match(TOKEN_RE2);
|
|
175187
|
-
if (m2) done(() =>
|
|
175938
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
175188
175939
|
};
|
|
175189
175940
|
child.stdout?.on("data", scan);
|
|
175190
175941
|
child.stderr?.on("data", scan);
|
|
@@ -175361,7 +176112,7 @@ __export(site_create_exports, {
|
|
|
175361
176112
|
runSiteList: () => runSiteList,
|
|
175362
176113
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
175363
176114
|
});
|
|
175364
|
-
import { existsSync as
|
|
176115
|
+
import { existsSync as existsSync81, readFileSync as readFileSync102, writeFileSync as writeFileSync38 } from "node:fs";
|
|
175365
176116
|
import { resolve as resolvePath2 } from "node:path";
|
|
175366
176117
|
function oauthClientName(projectName) {
|
|
175367
176118
|
return `${projectName} client`;
|
|
@@ -175510,7 +176261,7 @@ async function runSiteCreate(opts) {
|
|
|
175510
176261
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
175511
176262
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
175512
176263
|
}
|
|
175513
|
-
function writeProvisioningBinding(target, binding2, fs2 = { existsSync:
|
|
176264
|
+
function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync81, readFileSync: readFileSync102, writeFileSync: writeFileSync38 }) {
|
|
175514
176265
|
const msid = binding2.siteId;
|
|
175515
176266
|
const path2 = resolvePath2(target);
|
|
175516
176267
|
const committed = committedShellProvisioning(path2);
|
|
@@ -176207,12 +176958,12 @@ var init_context = __esm({
|
|
|
176207
176958
|
});
|
|
176208
176959
|
|
|
176209
176960
|
// src/cli.ts
|
|
176210
|
-
import { mkdtempSync as
|
|
176961
|
+
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync103, mkdirSync as mkdirSync42, writeFileSync as writeFileSync39, existsSync as existsSync82, rmSync as rmSync23, readdirSync as readdirSync35, statSync as statSync23, lstatSync as lstatSync22, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
|
|
176211
176962
|
import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
176212
176963
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
176213
|
-
import { createHash as
|
|
176214
|
-
import { tmpdir as
|
|
176215
|
-
import { join as
|
|
176964
|
+
import { createHash as createHash45, randomUUID as randomUUID11 } from "node:crypto";
|
|
176965
|
+
import { tmpdir as tmpdir7, homedir as homedir14, hostname as hostname2 } from "node:os";
|
|
176966
|
+
import { join as join87, resolve as resolve64, relative as relative16, basename as basename21, dirname as dirname48 } from "node:path";
|
|
176216
176967
|
import { fileURLToPath as fileURLToPath29 } from "node:url";
|
|
176217
176968
|
|
|
176218
176969
|
// ../serve-cli/src/client.ts
|
|
@@ -178294,8 +179045,8 @@ var str9 = (v2) => typeof v2 === "string" ? v2 : void 0;
|
|
|
178294
179045
|
var num3 = (v2) => typeof v2 === "string" && v2 !== "" && Number.isFinite(Number(v2)) ? Number(v2) : void 0;
|
|
178295
179046
|
function embeddedTemplateCatalog() {
|
|
178296
179047
|
return availableTemplates().map((name) => {
|
|
178297
|
-
const path2 =
|
|
178298
|
-
const meta = JSON.parse(
|
|
179048
|
+
const path2 = join87(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
179049
|
+
const meta = JSON.parse(readFileSync103(path2, "utf8"));
|
|
178299
179050
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
178300
179051
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
178301
179052
|
}
|
|
@@ -178855,6 +179606,13 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
178855
179606
|
conflict, never overwritten. --content records the
|
|
178856
179607
|
purchases app as wixIap in the app's config.ts.
|
|
178857
179608
|
No build, signing or repo checkout. Guide: himi docs iap-products
|
|
179609
|
+
himi store iap screenshots --manifest <file> --content <app dir> [--profile <name>] [--out-dir <dir>]
|
|
179610
|
+
[--only <productId,\u2026>] [--force] [--dry-run] [--json]
|
|
179611
|
+
render each product's purchase screen from the app, as a
|
|
179612
|
+
signed-in member sees it on a bound iPhone (Apple price, buy
|
|
179613
|
+
button), save it at 1290\xD72796 and name it as the item's
|
|
179614
|
+
reviewScreenshot. --profile reads Apple's price (read-only)
|
|
179615
|
+
and skips live products. Guide: himi docs iap-products
|
|
178858
179616
|
himi logout [--target <t>] clear the stored control token for a target
|
|
178859
179617
|
himi notify setup --content <dir> [--target wix] [--yes] [--no-push-setup]
|
|
178860
179618
|
Optional Branded/Ping setup. Prompts for site, native IDs and APNs key file.
|
|
@@ -179165,7 +179923,7 @@ var COMMANDS2 = [
|
|
|
179165
179923
|
{ name: "visibility", summary: "read (no value) or set whether the public registry (/v1/apps + the Himi Player picker) LISTS the app. `public` lists it for everyone; `unlisted` hides it from listings while direct reads by app id \u2014 deep links, previews \u2014 keep working. App from --app or the content dir. Setting it needs no republish.", required: "[public|unlisted] [--app <a>] [--content <dir>] (--control-token)" },
|
|
179166
179924
|
{ name: "dist", summary: "build an INSTALLABLE QA binary (signed IPA / APK) on the Wix Job Service Mac pool and return an install link \u2014 the serve plane brokers the job, the pool builds it. WAITS for the build by default (~4 min) and prints the install link; `--no-wait` returns a jobId immediately instead. Omitting `--release` builds whatever is LIVE for the app. A named draft is refused unless `--allow-draft` makes that exceptional build explicit. `status <jobId>` / `watch <jobId>` / `list --app <a>` / `cancel <jobId>` inspect and stop builds (`watch` reports up front whether the job mints its own signing identity or borrows one, so a doomed iOS build is cancellable in seconds rather than after the archive). Off-repo, name a target \u2014 `--target wix` for a self-serve Wix login or `--target bo` for the internal employee path (the in-repo default is a local dev plane that isn't reachable off-repo); self-serve callers may build their OWN apps under a tighter budget (2 in flight / 5 per 24h), while a manage-only owner-role credential is refused. `--shell` picks the native host to sign into (branded-lite | owner-lite | brandy | base44 | player | demo-app) and defaults to the content package's himalaya.content.json `shell` (templates carry the one they were written for), else branded-lite. The per-app shells ADD the release's declared capabilities to the binary, while Himi Player and demo-app refuse a release declaring one they lack; `--plan` previews it without building; `brandy` is the site shell \u2014 the customer's own website as native-framed tabs. `--signing` defaults to `wix-managed` \u2014 the Wix Apple account mints a per-app signing identity for the build, so the caller provisions no Apple credentials of their own; `--signing byo --site <id>` reuses an existing customer ad-hoc profile and certificate for iOS; requires an owned site and a completed personal signing binding. `--android-signing` is the Android counterpart and a SEPARATE axis (a keystore, not an Apple account): `qa-keystore` (default \u2014 the repo's committed QA key, identical on every pool machine, so a build installs over the previous one), `wix-keystore` (the Wix key the pool machine carries; the build FAILS naming the paths searched if it carries none, rather than quietly signing with something else), or `debug` (the old per-machine key \u2014 QA must uninstall any previous build first). NOT the normal way to ship: screens, Tier-5 bundles, tokens and app-config all go over the air with `himi push` in seconds \u2014 a binary trip is only needed for a NATIVE delta (a new SDUI component, a new declared capability/entitlement, a new bundle id, or a minBinaryVersion floor bump). Refuses to build an app whose launcher icon is missing, a placeholder, or one a store would reject \u2014 the one thing a binary carries that no later OTA push can fix; `--force` builds anyway", required: "[--app <a>] [--platform ios,android] [--release <id>] [--allow-draft] [--target <t>] [--shell branded-lite|owner-lite|brandy|base44|player|demo-app] [--signing wix-managed|byo] [--site <id>] [--android-signing qa-keystore|wix-keystore|debug] [--borrow-ios-id <bundleId>] [--no-wait] [--force] [--plan] | status <jobId> [--target <t>] | watch <jobId> [--target <t>] [--interval <ms>] | list --app <a> [--target <t>] | cancel <jobId> [--target <t>]" },
|
|
179167
179925
|
{ name: "testflight", summary: 'build, sign and upload an app to TestFlight (internal testers \u2014 no Beta App Review), then WAIT until App Store Connect finishes processing it. Sugar for `store upload --track testflight`. Prompts first: a build number is consumed permanently on a real Apple account and cannot be reused \u2014 `--yes` for CI, `--dry-run` to see the plan without touching anything. The wait is the real check, not a nicety: fastlane prints "Successfully uploaded" for a binary App Store Connect then rejects in processing, and a rejected binary leaves NO build record at all (the reason is emailed). Public App Store review is deliberately NOT automatable here \u2014 `--track appstore` is refused; use /submit-ios-app when you mean to go public', required: "<app> [--track testflight|internal] [--profile <name>] [--yes] [--dry-run] [--skip-build] [--no-wait] [--json]" },
|
|
179168
|
-
{ name: "store", summary: "the App Store Connect group behind `testflight`. `preflight <app>` checks readiness offline (icon, entitlements, encryption flag, version, store.config ids, listing + review record); `upload <app>` is what `testflight` runs; `status <app>` reads live build + processing state. `--profile` selects WHICH App Store Connect account: an app built for a Wix customer ships under the CUSTOMER's Apple team (Apple guideline 4.2.6 forbids an app-generation service submitting on a client's behalf), declared per-app as ios.credentialProfile in store.config.yaml and resolved from ~/.himalaya/store-credentials/<name>.json \u2014 the .p8 itself never enters the repo. `iap draft|plan|apply|status|connect` registers an app owner's digital products as in-app purchases (non-consumables, or consumable price tiers): draft reads the Wix catalog and writes the manifest, plan and status only read, apply is the one App Store mutation boundary, connect readies the Wix site to sell them (purchases app, In-App Purchase key, appleIAP provider, product mappings; --preview-tag routes only its Serve calls to a deploy preview), and none of them builds, signs or needs a checkout (`himi docs iap-products`)", required: "preflight <app> [--profile <n>] | upload <app> [--track <t>] [--profile <n>] [--yes] [--dry-run] | status <app> [--profile <n>] | iap draft --site <msid> --profile <n> --apple-app <id> --bundle <id> --base-territory <t> --out <f> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <f>] [--report <f>] [--json] | iap plan --manifest <f> --profile <n> --out <f> [--json] | iap apply --plan <f> --profile <n> --out <f> [--yes] [--limit <n>] [--json] | iap status --manifest <f> --profile <n> [--out <f>] [--json] | iap connect --manifest <f> --profile <n> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <f>] [--json]" },
|
|
179926
|
+
{ name: "store", summary: "the App Store Connect group behind `testflight`. `preflight <app>` checks readiness offline (icon, entitlements, encryption flag, version, store.config ids, listing + review record); `upload <app>` is what `testflight` runs; `status <app>` reads live build + processing state. `--profile` selects WHICH App Store Connect account: an app built for a Wix customer ships under the CUSTOMER's Apple team (Apple guideline 4.2.6 forbids an app-generation service submitting on a client's behalf), declared per-app as ios.credentialProfile in store.config.yaml and resolved from ~/.himalaya/store-credentials/<name>.json \u2014 the .p8 itself never enters the repo. `iap draft|plan|apply|status|connect|screenshots` registers an app owner's digital products as in-app purchases (non-consumables, or consumable price tiers): draft reads the Wix catalog and writes the manifest, plan and status only read, apply is the one App Store mutation boundary, connect readies the Wix site to sell them (purchases app, In-App Purchase key, appleIAP provider, product mappings; --preview-tag routes only its Serve calls to a deploy preview), screenshots renders each product's purchase screen from the app (--content) as a bound iPhone shows it to a signed-in member and names the 1290\xD72796 PNG as the item's App Review screenshot, and none of them builds, signs or needs a checkout (`himi docs iap-products`)", required: "preflight <app> [--profile <n>] | upload <app> [--track <t>] [--profile <n>] [--yes] [--dry-run] | status <app> [--profile <n>] | iap draft --site <msid> --profile <n> --apple-app <id> --bundle <id> --base-territory <t> --out <f> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <f>] [--report <f>] [--json] | iap plan --manifest <f> --profile <n> --out <f> [--json] | iap apply --plan <f> --profile <n> --out <f> [--yes] [--limit <n>] [--json] | iap status --manifest <f> --profile <n> [--out <f>] [--json] | iap connect --manifest <f> --profile <n> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <f>] [--json] | iap screenshots --manifest <f> --content <dir> [--profile <n>] [--out-dir <d>] [--only <id,\u2026>] [--force] [--dry-run] [--json]" },
|
|
179169
179927
|
{ name: "guide", summary: "print the Himalaya overview + headless dev loop + available topics (offline)", required: "[--json]" },
|
|
179170
179928
|
{ name: "docs", summary: "print bundled/verified cached guides offline; status reports kit identity; refresh downloads compatible reference content independently of CLI without changing app source", required: "[<topic>|catalog [kind]|status|refresh] [--pin <version|digest>] [--unpin] [--no-network] [--json]" },
|
|
179171
179929
|
{ name: "components", summary: "print the SDUI component vocabulary + props; a name = that component (offline)", required: "[<Name>] [--json]" },
|
|
@@ -179182,7 +179940,7 @@ var COMMANDS2 = [
|
|
|
179182
179940
|
];
|
|
179183
179941
|
function cliVersion() {
|
|
179184
179942
|
try {
|
|
179185
|
-
return JSON.parse(
|
|
179943
|
+
return JSON.parse(readFileSync103(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
179186
179944
|
} catch {
|
|
179187
179945
|
return "unknown";
|
|
179188
179946
|
}
|
|
@@ -179233,18 +179991,18 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
|
179233
179991
|
}
|
|
179234
179992
|
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
179235
179993
|
function execNpmConfig(file2, args, options) {
|
|
179236
|
-
return new Promise((
|
|
179237
|
-
execFile2(file2, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) :
|
|
179994
|
+
return new Promise((resolve65, reject) => {
|
|
179995
|
+
execFile2(file2, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve65(String(stdout)));
|
|
179238
179996
|
});
|
|
179239
179997
|
}
|
|
179240
179998
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
179241
179999
|
async function scopedRegistryBefore(lookup3, deadline, onTimeout) {
|
|
179242
180000
|
let cancel = () => {
|
|
179243
180001
|
};
|
|
179244
|
-
const expired = new Promise((
|
|
180002
|
+
const expired = new Promise((resolve65) => {
|
|
179245
180003
|
const timer = setTimeout(() => {
|
|
179246
180004
|
onTimeout?.();
|
|
179247
|
-
|
|
180005
|
+
resolve65(void 0);
|
|
179248
180006
|
}, Math.max(0, deadline - Date.now()));
|
|
179249
180007
|
cancel = () => clearTimeout(timer);
|
|
179250
180008
|
});
|
|
@@ -179307,18 +180065,18 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
179307
180065
|
}
|
|
179308
180066
|
function packageVersion(path2) {
|
|
179309
180067
|
try {
|
|
179310
|
-
const version4 = JSON.parse(
|
|
180068
|
+
const version4 = JSON.parse(readFileSync103(path2, "utf8")).version;
|
|
179311
180069
|
return typeof version4 === "string" && version4 ? version4 : void 0;
|
|
179312
180070
|
} catch {
|
|
179313
180071
|
return void 0;
|
|
179314
180072
|
}
|
|
179315
180073
|
}
|
|
179316
180074
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
179317
|
-
let dir =
|
|
180075
|
+
let dir = resolve64(fromDir);
|
|
179318
180076
|
for (; ; ) {
|
|
179319
|
-
const version4 = packageVersion(
|
|
180077
|
+
const version4 = packageVersion(join87(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
179320
180078
|
if (version4) return { version: version4, source: "local" };
|
|
179321
|
-
const parent =
|
|
180079
|
+
const parent = dirname48(dir);
|
|
179322
180080
|
if (parent === dir) break;
|
|
179323
180081
|
dir = parent;
|
|
179324
180082
|
}
|
|
@@ -179326,7 +180084,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
179326
180084
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
179327
180085
|
try {
|
|
179328
180086
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
179329
|
-
const version4 = root ? packageVersion(
|
|
180087
|
+
const version4 = root ? packageVersion(join87(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
179330
180088
|
return version4 ? { version: version4, source: "global" } : {};
|
|
179331
180089
|
} catch {
|
|
179332
180090
|
return {};
|
|
@@ -179373,11 +180131,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
179373
180131
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
179374
180132
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
179375
180133
|
function updateCachePath(env = process.env) {
|
|
179376
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
180134
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join87(homedir14(), ".himalaya", "update-check.json");
|
|
179377
180135
|
}
|
|
179378
180136
|
function readUpdateCache(path2) {
|
|
179379
180137
|
try {
|
|
179380
|
-
const parsed = JSON.parse(
|
|
180138
|
+
const parsed = JSON.parse(readFileSync103(path2, "utf8"));
|
|
179381
180139
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
179382
180140
|
} catch {
|
|
179383
180141
|
return {};
|
|
@@ -179385,7 +180143,7 @@ function readUpdateCache(path2) {
|
|
|
179385
180143
|
}
|
|
179386
180144
|
function writeUpdateCache(path2, cache) {
|
|
179387
180145
|
try {
|
|
179388
|
-
mkdirSync42(
|
|
180146
|
+
mkdirSync42(dirname48(path2), { recursive: true, mode: 448 });
|
|
179389
180147
|
writeFileSync39(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
179390
180148
|
} catch {
|
|
179391
180149
|
}
|
|
@@ -179446,12 +180204,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
179446
180204
|
},
|
|
179447
180205
|
installedVersion: () => {
|
|
179448
180206
|
const root = globalNodeModulesRoot();
|
|
179449
|
-
return root ? packageVersion(
|
|
180207
|
+
return root ? packageVersion(join87(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
179450
180208
|
},
|
|
179451
180209
|
reexec: (argv) => {
|
|
179452
180210
|
const root = globalNodeModulesRoot();
|
|
179453
|
-
const entry = root ?
|
|
179454
|
-
if (!entry || !
|
|
180211
|
+
const entry = root ? join87(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
180212
|
+
if (!entry || !existsSync82(entry)) return void 0;
|
|
179455
180213
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
179456
180214
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
179457
180215
|
stdio: "inherit",
|
|
@@ -179498,7 +180256,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
179498
180256
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
179499
180257
|
let content;
|
|
179500
180258
|
try {
|
|
179501
|
-
content =
|
|
180259
|
+
content = readFileSync103(path2, "utf8");
|
|
179502
180260
|
} catch {
|
|
179503
180261
|
continue;
|
|
179504
180262
|
}
|
|
@@ -179521,7 +180279,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179521
180279
|
const mine = lockStamp(now);
|
|
179522
180280
|
const readLock = (path2) => {
|
|
179523
180281
|
try {
|
|
179524
|
-
return
|
|
180282
|
+
return readFileSync103(path2, "utf8");
|
|
179525
180283
|
} catch {
|
|
179526
180284
|
return void 0;
|
|
179527
180285
|
}
|
|
@@ -179536,13 +180294,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179536
180294
|
};
|
|
179537
180295
|
const removeIfMine = (path2) => {
|
|
179538
180296
|
try {
|
|
179539
|
-
if (readLock(path2) === mine)
|
|
180297
|
+
if (readLock(path2) === mine) rmSync23(path2, { force: true });
|
|
179540
180298
|
} catch {
|
|
179541
180299
|
}
|
|
179542
180300
|
};
|
|
179543
180301
|
const release2 = () => removeIfMine(lockPath);
|
|
179544
180302
|
try {
|
|
179545
|
-
mkdirSync42(
|
|
180303
|
+
mkdirSync42(dirname48(lockPath), { recursive: true, mode: 448 });
|
|
179546
180304
|
} catch {
|
|
179547
180305
|
return () => {
|
|
179548
180306
|
};
|
|
@@ -179559,7 +180317,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179559
180317
|
hooks.underBreakLock?.();
|
|
179560
180318
|
if (current === void 0) return tryCreate(lockPath) ? release2 : void 0;
|
|
179561
180319
|
if (!isAbandoned(current)) return void 0;
|
|
179562
|
-
|
|
180320
|
+
rmSync23(lockPath, { force: true });
|
|
179563
180321
|
return tryCreate(lockPath) ? release2 : void 0;
|
|
179564
180322
|
} finally {
|
|
179565
180323
|
removeIfMine(breakPath);
|
|
@@ -179655,7 +180413,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
|
|
|
179655
180413
|
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
179656
180414
|
};
|
|
179657
180415
|
return async (dir, opts = {}) => {
|
|
179658
|
-
const argv = ["validate", "--content",
|
|
180416
|
+
const argv = ["validate", "--content", resolve64(dir), "--strict", "--skip-version-check"];
|
|
179659
180417
|
if (!opts.fresh) {
|
|
179660
180418
|
const out2 = [];
|
|
179661
180419
|
const err = [];
|
|
@@ -180113,7 +180871,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
180113
180871
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
180114
180872
|
for (const dir of entries) {
|
|
180115
180873
|
for (const suffix of suffixes) {
|
|
180116
|
-
const candidate =
|
|
180874
|
+
const candidate = join87(dir, `${name}${suffix}`);
|
|
180117
180875
|
try {
|
|
180118
180876
|
if (!statSync23(candidate).isFile()) continue;
|
|
180119
180877
|
if (process.platform !== "win32") accessSync(candidate, constants5.X_OK);
|
|
@@ -180222,7 +180980,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
180222
180980
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
180223
180981
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
180224
180982
|
const iosYmlPath = iosProjectYml2(app);
|
|
180225
|
-
const iosYml =
|
|
180983
|
+
const iosYml = existsSync82(iosYmlPath) ? readFileSync103(iosYmlPath, "utf8") : "";
|
|
180226
180984
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
180227
180985
|
if (!optedIn) {
|
|
180228
180986
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -180236,13 +180994,13 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
180236
180994
|
}
|
|
180237
180995
|
function readConfigSource(dir) {
|
|
180238
180996
|
try {
|
|
180239
|
-
return
|
|
180997
|
+
return readFileSync103(join87(dir, "config.ts"), "utf8");
|
|
180240
180998
|
} catch {
|
|
180241
180999
|
return null;
|
|
180242
181000
|
}
|
|
180243
181001
|
}
|
|
180244
181002
|
function writePngFile(path2, base64) {
|
|
180245
|
-
mkdirSync42(
|
|
181003
|
+
mkdirSync42(dirname48(path2), { recursive: true });
|
|
180246
181004
|
writeFileSync39(path2, Buffer.from(base64, "base64"));
|
|
180247
181005
|
return path2;
|
|
180248
181006
|
}
|
|
@@ -180289,8 +181047,8 @@ function keptPlan(kept) {
|
|
|
180289
181047
|
var NoBase44SlotError = class extends Error {
|
|
180290
181048
|
};
|
|
180291
181049
|
async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
|
|
180292
|
-
const dir =
|
|
180293
|
-
if (
|
|
181050
|
+
const dir = resolve64(parentDir, name);
|
|
181051
|
+
if (existsSync82(join87(dir, "himalaya.content.json"))) {
|
|
180294
181052
|
throw new Error(`content package already exists at ${dir}`);
|
|
180295
181053
|
}
|
|
180296
181054
|
const r2 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -180305,7 +181063,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {})
|
|
|
180305
181063
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
180306
181064
|
}
|
|
180307
181065
|
function contentDir(flags) {
|
|
180308
|
-
return
|
|
181066
|
+
return resolve64(str9(flags.content) ?? process.cwd());
|
|
180309
181067
|
}
|
|
180310
181068
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
180311
181069
|
const text9 = {};
|
|
@@ -180336,7 +181094,7 @@ function symlinkDestinationIssue(dest) {
|
|
|
180336
181094
|
function restoreDestinationIssue(dest, force) {
|
|
180337
181095
|
const link = symlinkDestinationIssue(dest);
|
|
180338
181096
|
if (link) return link;
|
|
180339
|
-
if (!
|
|
181097
|
+
if (!existsSync82(dest)) return null;
|
|
180340
181098
|
if (!statSync23(dest).isDirectory()) {
|
|
180341
181099
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
180342
181100
|
}
|
|
@@ -180349,10 +181107,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
180349
181107
|
return null;
|
|
180350
181108
|
}
|
|
180351
181109
|
function isHimalayaMonorepoCheckout(start) {
|
|
180352
|
-
let dir =
|
|
181110
|
+
let dir = resolve64(start);
|
|
180353
181111
|
for (; ; ) {
|
|
180354
|
-
if (
|
|
180355
|
-
const parent =
|
|
181112
|
+
if (existsSync82(join87(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync82(join87(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
181113
|
+
const parent = dirname48(dir);
|
|
180356
181114
|
if (parent === dir) return false;
|
|
180357
181115
|
dir = parent;
|
|
180358
181116
|
}
|
|
@@ -180389,7 +181147,7 @@ function shellShaDivergenceWarnings(jobs) {
|
|
|
180389
181147
|
}
|
|
180390
181148
|
async function templatePublishName(sourceDir) {
|
|
180391
181149
|
const id = await appId(sourceDir);
|
|
180392
|
-
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ?
|
|
181150
|
+
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ? basename21(sourceDir) : id;
|
|
180393
181151
|
}
|
|
180394
181152
|
function templateNameError(name, from) {
|
|
180395
181153
|
if (name.startsWith(TEMPLATE_APP_PREFIX)) {
|
|
@@ -180411,8 +181169,8 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
180411
181169
|
const forBuild = Object.fromEntries(
|
|
180412
181170
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
180413
181171
|
);
|
|
180414
|
-
const repoRoot2 =
|
|
180415
|
-
const root =
|
|
181172
|
+
const repoRoot2 = resolve64(fileURLToPath29(new URL("../../..", import.meta.url)));
|
|
181173
|
+
const root = join87(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
180416
181174
|
const stillRunning = (pid) => {
|
|
180417
181175
|
try {
|
|
180418
181176
|
process.kill(pid, 0);
|
|
@@ -180426,35 +181184,35 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
180426
181184
|
if (!entry.isDirectory()) continue;
|
|
180427
181185
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
180428
181186
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
180429
|
-
|
|
181187
|
+
rmSync23(join87(root, entry.name), { recursive: true, force: true });
|
|
180430
181188
|
}
|
|
180431
181189
|
}
|
|
180432
181190
|
} catch {
|
|
180433
181191
|
}
|
|
180434
|
-
const dest =
|
|
180435
|
-
|
|
181192
|
+
const dest = join87(root, `${slug}-${process.pid}`);
|
|
181193
|
+
rmSync23(dest, { recursive: true, force: true });
|
|
180436
181194
|
mkdirSync42(dest, { recursive: true });
|
|
180437
181195
|
try {
|
|
180438
181196
|
materializeSource(forBuild, displayName2, dest, slug);
|
|
180439
181197
|
} catch (e2) {
|
|
180440
|
-
|
|
181198
|
+
rmSync23(dest, { recursive: true, force: true });
|
|
180441
181199
|
throw e2;
|
|
180442
181200
|
}
|
|
180443
181201
|
return dest;
|
|
180444
181202
|
}
|
|
180445
181203
|
async function appId(dir) {
|
|
180446
181204
|
try {
|
|
180447
|
-
const { readFileSync:
|
|
180448
|
-
const m2 = JSON.parse(
|
|
181205
|
+
const { readFileSync: readFileSync104 } = await import("node:fs");
|
|
181206
|
+
const m2 = JSON.parse(readFileSync104(join87(dir, "himalaya.content.json"), "utf8"));
|
|
180449
181207
|
if (m2.name) return m2.name;
|
|
180450
181208
|
} catch {
|
|
180451
181209
|
}
|
|
180452
|
-
return
|
|
181210
|
+
return basename21(dir);
|
|
180453
181211
|
}
|
|
180454
181212
|
async function contentVisibility(dir) {
|
|
180455
181213
|
try {
|
|
180456
|
-
const { readFileSync:
|
|
180457
|
-
const m2 = JSON.parse(
|
|
181214
|
+
const { readFileSync: readFileSync104 } = await import("node:fs");
|
|
181215
|
+
const m2 = JSON.parse(readFileSync104(join87(dir, "himalaya.content.json"), "utf8"));
|
|
180458
181216
|
if (m2.visibility === "public" || m2.visibility === "unlisted") return m2.visibility;
|
|
180459
181217
|
} catch {
|
|
180460
181218
|
}
|
|
@@ -180724,7 +181482,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
180724
181482
|
return 0;
|
|
180725
181483
|
}
|
|
180726
181484
|
case "agent-init": {
|
|
180727
|
-
const dir =
|
|
181485
|
+
const dir = resolve64(str9(flags.dir) ?? process.cwd());
|
|
180728
181486
|
const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
|
|
180729
181487
|
let res;
|
|
180730
181488
|
try {
|
|
@@ -180746,7 +181504,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
180746
181504
|
...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/" } : {},
|
|
180747
181505
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
180748
181506
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
180749
|
-
...
|
|
181507
|
+
...existsSync82(join87(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" } : {},
|
|
180750
181508
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
180751
181509
|
portalUrl: idx.portalUrl
|
|
180752
181510
|
});
|
|
@@ -180769,7 +181527,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
180769
181527
|
try {
|
|
180770
181528
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
180771
181529
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
180772
|
-
out2 =
|
|
181530
|
+
out2 = mkdtempSync6(join87(tmpdir7(), "himi-ux-record-"));
|
|
180773
181531
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
180774
181532
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
180775
181533
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -180782,7 +181540,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
180782
181540
|
return null;
|
|
180783
181541
|
} finally {
|
|
180784
181542
|
if (out2 !== void 0) try {
|
|
180785
|
-
|
|
181543
|
+
rmSync23(out2, { recursive: true, force: true });
|
|
180786
181544
|
} catch {
|
|
180787
181545
|
}
|
|
180788
181546
|
}
|
|
@@ -180948,7 +181706,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
180948
181706
|
let js2;
|
|
180949
181707
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
180950
181708
|
try {
|
|
180951
|
-
js2 =
|
|
181709
|
+
js2 = readFileSync103(join87(outDir, candidate), "utf8");
|
|
180952
181710
|
break;
|
|
180953
181711
|
} catch {
|
|
180954
181712
|
}
|
|
@@ -180979,7 +181737,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
180979
181737
|
}
|
|
180980
181738
|
return { families, source: "dist/bundles" };
|
|
180981
181739
|
}
|
|
180982
|
-
var boardOpen = (dir) =>
|
|
181740
|
+
var boardOpen = (dir) => existsSync82(join87(dir, ".himi", "studio", "index.html"));
|
|
180983
181741
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
180984
181742
|
async function leaveForBoard(dir, record2, value) {
|
|
180985
181743
|
if (!boardOpen(dir)) return;
|
|
@@ -181003,7 +181761,7 @@ async function liveMapFor(dir) {
|
|
|
181003
181761
|
}
|
|
181004
181762
|
var commandScratch = new AsyncLocalStorage2();
|
|
181005
181763
|
function commandScratchDir(prefix) {
|
|
181006
|
-
const dir =
|
|
181764
|
+
const dir = mkdtempSync6(join87(tmpdir7(), prefix));
|
|
181007
181765
|
commandScratch.getStore()?.push(dir);
|
|
181008
181766
|
return dir;
|
|
181009
181767
|
}
|
|
@@ -181014,7 +181772,7 @@ async function run(argv, io2 = defaultIO, deps = {}) {
|
|
|
181014
181772
|
code = await commandScratch.run(scratch, () => runCommand(argv, io2, deps));
|
|
181015
181773
|
} finally {
|
|
181016
181774
|
for (const dir of scratch) try {
|
|
181017
|
-
|
|
181775
|
+
rmSync23(dir, { recursive: true, force: true });
|
|
181018
181776
|
} catch {
|
|
181019
181777
|
}
|
|
181020
181778
|
}
|
|
@@ -181314,7 +182072,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
181314
182072
|
return 2;
|
|
181315
182073
|
}
|
|
181316
182074
|
const template = str9(flags.template);
|
|
181317
|
-
const parentDir =
|
|
182075
|
+
const parentDir = resolve64(str9(flags.dir) ?? process.cwd());
|
|
181318
182076
|
const base44AppId = flags["base44-app-id"] === void 0 ? void 0 : String(flags["base44-app-id"]);
|
|
181319
182077
|
const base44AppUrl = flags["base44-app-url"] === void 0 ? void 0 : String(flags["base44-app-url"]);
|
|
181320
182078
|
if (base44AppUrl !== void 0) {
|
|
@@ -181357,7 +182115,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
181357
182115
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
181358
182116
|
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`);
|
|
181359
182117
|
}
|
|
181360
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) =>
|
|
182118
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync82(join87(parentDir, f2)));
|
|
181361
182119
|
if (planInParent.length) {
|
|
181362
182120
|
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}`);
|
|
181363
182121
|
}
|
|
@@ -181518,13 +182276,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181518
182276
|
if (adding) {
|
|
181519
182277
|
const from = str9(flags.from);
|
|
181520
182278
|
if (!from) throw new TrimRefusal2('--add <id> needs --from <file> holding the whole new SCREENS entry (` "<id>": { "screenId": "<id>", \u2026 },`)');
|
|
181521
|
-
print(adopt.addScreen(dir, adding,
|
|
182279
|
+
print(adopt.addScreen(dir, adding, readFileSync103(from, "utf8"), { parent: str9(flags.parent), tab: str9(flags.tab), displayName: str9(flags["display-name"]) }));
|
|
181522
182280
|
return 0;
|
|
181523
182281
|
}
|
|
181524
182282
|
if (target) {
|
|
181525
182283
|
const from = str9(flags.from);
|
|
181526
182284
|
if (!from) throw new TrimRefusal2("--write <id> needs --from <file> holding the whole entry, as --show prints it");
|
|
181527
|
-
print(adopt.replaceScreen(dir, target,
|
|
182285
|
+
print(adopt.replaceScreen(dir, target, readFileSync103(from, "utf8")));
|
|
181528
182286
|
return 0;
|
|
181529
182287
|
}
|
|
181530
182288
|
if (show) {
|
|
@@ -181606,7 +182364,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181606
182364
|
const { keepFromSpec: keepFromSpec2 } = await Promise.resolve().then(() => (init_template_adopt(), template_adopt_exports));
|
|
181607
182365
|
const dir = contentDir(flags);
|
|
181608
182366
|
try {
|
|
181609
|
-
const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ??
|
|
182367
|
+
const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ?? join87(dir, "SPEC.md"));
|
|
181610
182368
|
const own5 = typeof keep === "string" ? keep.split(",").map((k2) => k2.trim()).filter(Boolean) : [];
|
|
181611
182369
|
keep = [.../* @__PURE__ */ new Set([...spec.keep, ...own5])].join(",");
|
|
181612
182370
|
fromSpec = { fromSpec: {
|
|
@@ -181647,7 +182405,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181647
182405
|
const result = { ...outcome.result, ...fromSpec };
|
|
181648
182406
|
const adoptDir = contentDir(flags);
|
|
181649
182407
|
const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
|
|
181650
|
-
if (kept &&
|
|
182408
|
+
if (kept && existsSync82(join87(adoptDir, adoptBits.ADOPT_FILE))) {
|
|
181651
182409
|
try {
|
|
181652
182410
|
const inv = adoptBits.inspectApp(adoptDir);
|
|
181653
182411
|
adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
|
|
@@ -181672,11 +182430,11 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181672
182430
|
return 2;
|
|
181673
182431
|
}
|
|
181674
182432
|
}
|
|
181675
|
-
const appDir3 =
|
|
181676
|
-
const sourceDir =
|
|
182433
|
+
const appDir3 = resolve64(str9(flags.dir) ?? process.cwd());
|
|
182434
|
+
const sourceDir = resolve64(str9(flags["source-dir"]) ?? appDir3);
|
|
181677
182435
|
let meta;
|
|
181678
182436
|
try {
|
|
181679
|
-
meta = JSON.parse(
|
|
182437
|
+
meta = JSON.parse(readFileSync103(join87(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
181680
182438
|
} catch {
|
|
181681
182439
|
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>)` }));
|
|
181682
182440
|
return 2;
|
|
@@ -181686,7 +182444,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181686
182444
|
return 2;
|
|
181687
182445
|
}
|
|
181688
182446
|
try {
|
|
181689
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
182447
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync103(join87(sourceDir, "tokens.json"), "utf8")));
|
|
181690
182448
|
meta = { ...appearance, ...meta };
|
|
181691
182449
|
} catch {
|
|
181692
182450
|
}
|
|
@@ -181708,14 +182466,14 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181708
182466
|
const force = flags.force === true;
|
|
181709
182467
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
181710
182468
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
181711
|
-
const out2 =
|
|
182469
|
+
const out2 = mkdtempSync6(join87(tmpdir7(), "himi-template-"));
|
|
181712
182470
|
publishScratch.push(out2);
|
|
181713
182471
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
181714
182472
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
181715
182473
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
181716
182474
|
collect: { lint: true, strict }
|
|
181717
182475
|
});
|
|
181718
|
-
const scaffoldSourceFindings =
|
|
182476
|
+
const scaffoldSourceFindings = resolve64(sourceDir) === resolve64(appDir3) ? [] : [
|
|
181719
182477
|
...(await Promise.resolve().then(() => (init_capabilities(), capabilities_exports))).capabilityConfigFindings(sourceDir, buildDir),
|
|
181720
182478
|
...tokenColorIssues(sourceDir),
|
|
181721
182479
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
@@ -181761,13 +182519,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181761
182519
|
}));
|
|
181762
182520
|
return 1;
|
|
181763
182521
|
}
|
|
181764
|
-
const iconPath = str9(flags.icon) ?
|
|
182522
|
+
const iconPath = str9(flags.icon) ? resolve64(str9(flags.icon)) : templateIconPath(name);
|
|
181765
182523
|
let iconHash;
|
|
181766
182524
|
if (iconPath) {
|
|
181767
182525
|
try {
|
|
181768
|
-
const bytes2 =
|
|
182526
|
+
const bytes2 = readFileSync103(iconPath);
|
|
181769
182527
|
payload.icon = bytes2.toString("base64");
|
|
181770
|
-
iconHash =
|
|
182528
|
+
iconHash = createHash45("sha256").update(bytes2).digest("hex");
|
|
181771
182529
|
} catch {
|
|
181772
182530
|
}
|
|
181773
182531
|
}
|
|
@@ -181943,7 +182701,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181943
182701
|
} finally {
|
|
181944
182702
|
for (const dir of publishScratch) {
|
|
181945
182703
|
try {
|
|
181946
|
-
|
|
182704
|
+
rmSync23(dir, { recursive: true, force: true });
|
|
181947
182705
|
} catch (e2) {
|
|
181948
182706
|
io2.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e2.message}` }));
|
|
181949
182707
|
}
|
|
@@ -182069,7 +182827,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182069
182827
|
const path2 = dpxSessionTokenPath();
|
|
182070
182828
|
let raw;
|
|
182071
182829
|
try {
|
|
182072
|
-
raw =
|
|
182830
|
+
raw = readFileSync103(path2, "utf8");
|
|
182073
182831
|
} catch {
|
|
182074
182832
|
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`);
|
|
182075
182833
|
}
|
|
@@ -182200,11 +182958,11 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182200
182958
|
return 1;
|
|
182201
182959
|
}
|
|
182202
182960
|
const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
|
|
182203
|
-
const dir =
|
|
182961
|
+
const dir = resolve64(out2);
|
|
182204
182962
|
const files = himiPluginFiles2(skills.skillMd);
|
|
182205
182963
|
for (const f2 of files) {
|
|
182206
|
-
mkdirSync42(
|
|
182207
|
-
writeFileSync39(
|
|
182964
|
+
mkdirSync42(dirname48(join87(dir, f2.path)), { recursive: true });
|
|
182965
|
+
writeFileSync39(join87(dir, f2.path), f2.text);
|
|
182208
182966
|
}
|
|
182209
182967
|
print({ ok: true, dir, files: files.map((f2) => f2.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
182210
182968
|
return 0;
|
|
@@ -182214,22 +182972,22 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182214
182972
|
run,
|
|
182215
182973
|
version: cliVersion(),
|
|
182216
182974
|
withFiles: flags["with-files"] === true,
|
|
182217
|
-
...process.env.HIMI_WORKSPACE ? { workspace:
|
|
182975
|
+
...process.env.HIMI_WORKSPACE ? { workspace: resolve64(process.env.HIMI_WORKSPACE) } : {}
|
|
182218
182976
|
});
|
|
182219
182977
|
return 0;
|
|
182220
182978
|
}
|
|
182221
182979
|
case "studio": {
|
|
182222
182980
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
182223
182981
|
const dir = contentDir(flags);
|
|
182224
|
-
if (!
|
|
182982
|
+
if (!existsSync82(join87(dir, "himalaya.content.json"))) {
|
|
182225
182983
|
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/" }));
|
|
182226
182984
|
return 2;
|
|
182227
182985
|
}
|
|
182228
182986
|
if (pos[1] === "reel") {
|
|
182229
182987
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
182230
|
-
const out2 =
|
|
182988
|
+
const out2 = resolve64(str9(flags.out) ?? join87(dir, ".himi", "making-of.html"));
|
|
182231
182989
|
const { html, plan } = buildReel2(dir);
|
|
182232
|
-
mkdirSync42(
|
|
182990
|
+
mkdirSync42(dirname48(out2), { recursive: true });
|
|
182233
182991
|
writeFileSync39(out2, html);
|
|
182234
182992
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
182235
182993
|
const url2 = pathToFileURL9(out2).href;
|
|
@@ -182238,7 +182996,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182238
182996
|
const { openUrl: openUrl2 } = await Promise.resolve().then(() => (init_open_url(), open_url_exports));
|
|
182239
182997
|
openUrl2(url2);
|
|
182240
182998
|
}
|
|
182241
|
-
const handover = { file: out2, hint: `hand ${
|
|
182999
|
+
const handover = { file: out2, hint: `hand ${basename21(out2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
|
|
182242
183000
|
const report3 = {
|
|
182243
183001
|
ok: true,
|
|
182244
183002
|
file: out2,
|
|
@@ -182299,7 +183057,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182299
183057
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
182300
183058
|
const dir = contentDir(flags);
|
|
182301
183059
|
const journal2 = journalPath2(dir);
|
|
182302
|
-
const isContentPackage =
|
|
183060
|
+
const isContentPackage = existsSync82(join87(dir, "himalaya.content.json"));
|
|
182303
183061
|
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" };
|
|
182304
183062
|
const message = pos.slice(1).join(" ").trim();
|
|
182305
183063
|
const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
|
|
@@ -182451,7 +183209,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182451
183209
|
case "test": {
|
|
182452
183210
|
const dir = contentDir(flags);
|
|
182453
183211
|
const structuredOutput = flags.json === true || io2.isTTY !== true;
|
|
182454
|
-
if (
|
|
183212
|
+
if (existsSync82(join87(dir, "functions"))) {
|
|
182455
183213
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
182456
183214
|
const loaded = await loadFunctionsApp2(dir);
|
|
182457
183215
|
const results = [];
|
|
@@ -182583,7 +183341,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182583
183341
|
io2.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
182584
183342
|
return 2;
|
|
182585
183343
|
}
|
|
182586
|
-
const sources = collectWorkerSources2(
|
|
183344
|
+
const sources = collectWorkerSources2(join87(dir, "tier5-src"), screen.bundleName);
|
|
182587
183345
|
if (!sources) {
|
|
182588
183346
|
io2.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
182589
183347
|
return 2;
|
|
@@ -182761,7 +183519,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182761
183519
|
const sp = await runShotsPass2({
|
|
182762
183520
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
182763
183521
|
tokens: outcome.tokens,
|
|
182764
|
-
outDir:
|
|
183522
|
+
outDir: join87(dir, ".himi", "shots"),
|
|
182765
183523
|
width: 390,
|
|
182766
183524
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
182767
183525
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -182772,7 +183530,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182772
183530
|
renderPngBatch: renderPngBatch2,
|
|
182773
183531
|
isUnserved: isUnservedRequest2,
|
|
182774
183532
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
182775
|
-
clearDir: (d2) =>
|
|
183533
|
+
clearDir: (d2) => rmSync23(d2, { recursive: true, force: true })
|
|
182776
183534
|
}
|
|
182777
183535
|
});
|
|
182778
183536
|
writtenShots = sp.written;
|
|
@@ -182801,7 +183559,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182801
183559
|
releaseId: result.releaseId,
|
|
182802
183560
|
releasePayload: release2,
|
|
182803
183561
|
descriptors: attestedDescriptors,
|
|
182804
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
183562
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join87(dir, ".himi", "shots", name)])),
|
|
182805
183563
|
coverage: {
|
|
182806
183564
|
screens: crawledScreens.size,
|
|
182807
183565
|
actionsDispatched: result.actions.exercised,
|
|
@@ -182926,7 +183684,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
182926
183684
|
return 2;
|
|
182927
183685
|
}
|
|
182928
183686
|
try {
|
|
182929
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
183687
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync103(stateArg.replace(/^@/, ""), "utf8");
|
|
182930
183688
|
injectedState = JSON.parse(raw);
|
|
182931
183689
|
} catch (e2) {
|
|
182932
183690
|
io2.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e2.message}` }));
|
|
@@ -182941,7 +183699,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
182941
183699
|
return 2;
|
|
182942
183700
|
}
|
|
182943
183701
|
try {
|
|
182944
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
183702
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync103(inputArg.replace(/^@/, ""), "utf8");
|
|
182945
183703
|
const parsed = JSON.parse(raw);
|
|
182946
183704
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
182947
183705
|
injectedInput = parsed;
|
|
@@ -183023,11 +183781,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
183023
183781
|
const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
|
|
183024
183782
|
let pngFile;
|
|
183025
183783
|
let attestationPngFile;
|
|
183026
|
-
const shotPath =
|
|
183784
|
+
const shotPath = join87(dir, ".himi", "shots", `${screenId}.png`);
|
|
183027
183785
|
const pngTarget = typeof flags.png === "string" ? str9(flags.png) : flags.png === true ? shotPath : void 0;
|
|
183028
183786
|
if (pngTarget && r2.pngBase64) {
|
|
183029
183787
|
pngFile = writePngFile(pngTarget, r2.pngBase64);
|
|
183030
|
-
attestationPngFile =
|
|
183788
|
+
attestationPngFile = resolve64(pngTarget) === resolve64(shotPath) ? pngFile : writePngFile(shotPath, r2.pngBase64);
|
|
183031
183789
|
}
|
|
183032
183790
|
if (renderWidth !== void 0 && r2.renderable) {
|
|
183033
183791
|
recordRenderWidth(dir, {
|
|
@@ -183374,7 +184132,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183374
184132
|
return 2;
|
|
183375
184133
|
}
|
|
183376
184134
|
const renamed = str9(flags.name);
|
|
183377
|
-
const dest =
|
|
184135
|
+
const dest = resolve64(str9(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
183378
184136
|
const replace = flags.replace === true;
|
|
183379
184137
|
const force = replace || flags.force === true;
|
|
183380
184138
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -183382,7 +184140,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183382
184140
|
io2.error(JSON.stringify(linked));
|
|
183383
184141
|
return 1;
|
|
183384
184142
|
}
|
|
183385
|
-
if (
|
|
184143
|
+
if (existsSync82(dest)) {
|
|
183386
184144
|
if (!statSync23(dest).isDirectory()) {
|
|
183387
184145
|
io2.error(JSON.stringify({
|
|
183388
184146
|
error: `${dest} exists and is not a directory`,
|
|
@@ -183395,7 +184153,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183395
184153
|
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" }));
|
|
183396
184154
|
return 1;
|
|
183397
184155
|
}
|
|
183398
|
-
if (replace && occupied && !
|
|
184156
|
+
if (replace && occupied && !existsSync82(join87(dest, "himalaya.content.json"))) {
|
|
183399
184157
|
io2.error(JSON.stringify({
|
|
183400
184158
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
183401
184159
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -183564,7 +184322,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183564
184322
|
const manifest = outcome.manifest;
|
|
183565
184323
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
183566
184324
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
183567
|
-
const contentRel =
|
|
184325
|
+
const contentRel = relative16(process.cwd(), dir) || ".";
|
|
183568
184326
|
const contentArg2 = shellQuote3(contentRel);
|
|
183569
184327
|
if (onlyRaw !== void 0) {
|
|
183570
184328
|
const onlyDraft = flags.draft === true;
|
|
@@ -183626,7 +184384,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183626
184384
|
let localSourceHash;
|
|
183627
184385
|
try {
|
|
183628
184386
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
183629
|
-
localSourceHash =
|
|
184387
|
+
localSourceHash = createHash45("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
183630
184388
|
} catch {
|
|
183631
184389
|
}
|
|
183632
184390
|
return runReleasePatch({
|
|
@@ -184054,7 +184812,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184054
184812
|
return 2;
|
|
184055
184813
|
}
|
|
184056
184814
|
try {
|
|
184057
|
-
const res = writePack(
|
|
184815
|
+
const res = writePack(resolve64(releaseDir), only, resolve64(str9(flags.out) ?? process.cwd()));
|
|
184058
184816
|
print({
|
|
184059
184817
|
ok: true,
|
|
184060
184818
|
app: res.app,
|
|
@@ -184103,7 +184861,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184103
184861
|
}
|
|
184104
184862
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184105
184863
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
184106
|
-
const built =
|
|
184864
|
+
const built = mkdtempSync6(join87(tmpdir7(), "himi-pack-"));
|
|
184107
184865
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
184108
184866
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
184109
184867
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -184122,12 +184880,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184122
184880
|
...await navIssues2(dir, strict)
|
|
184123
184881
|
]);
|
|
184124
184882
|
if (hasErrors && !force) {
|
|
184125
|
-
|
|
184883
|
+
rmSync23(built, { recursive: true, force: true });
|
|
184126
184884
|
print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
184127
184885
|
return 1;
|
|
184128
184886
|
}
|
|
184129
184887
|
try {
|
|
184130
|
-
const res = writePack(built, app,
|
|
184888
|
+
const res = writePack(built, app, resolve64(str9(flags.out) ?? dir), sourceArchive);
|
|
184131
184889
|
print({
|
|
184132
184890
|
ok: true,
|
|
184133
184891
|
app: res.app,
|
|
@@ -184158,7 +184916,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184158
184916
|
io2.error(JSON.stringify({ error: e2.message }));
|
|
184159
184917
|
return 1;
|
|
184160
184918
|
} finally {
|
|
184161
|
-
|
|
184919
|
+
rmSync23(built, { recursive: true, force: true });
|
|
184162
184920
|
}
|
|
184163
184921
|
}
|
|
184164
184922
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -184172,7 +184930,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184172
184930
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
184173
184931
|
let opened;
|
|
184174
184932
|
try {
|
|
184175
|
-
opened = openPackageFile2(
|
|
184933
|
+
opened = openPackageFile2(resolve64(file2));
|
|
184176
184934
|
} catch (e2) {
|
|
184177
184935
|
io2.error(JSON.stringify({ error: e2.message }));
|
|
184178
184936
|
return 1;
|
|
@@ -184185,7 +184943,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184185
184943
|
io2.error(JSON.stringify({
|
|
184186
184944
|
ok: false,
|
|
184187
184945
|
error: "app_source_not_in_package",
|
|
184188
|
-
detail: `${
|
|
184946
|
+
detail: `${resolve64(file2)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
184189
184947
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
184190
184948
|
}));
|
|
184191
184949
|
return 1;
|
|
@@ -184208,7 +184966,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184208
184966
|
return 1;
|
|
184209
184967
|
}
|
|
184210
184968
|
}
|
|
184211
|
-
const dest =
|
|
184969
|
+
const dest = resolve64(str9(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
184212
184970
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
184213
184971
|
if (issue2) {
|
|
184214
184972
|
io2.error(JSON.stringify(issue2));
|
|
@@ -184295,7 +185053,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184295
185053
|
}
|
|
184296
185054
|
try {
|
|
184297
185055
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
184298
|
-
const opened = openPackageFile2(
|
|
185056
|
+
const opened = openPackageFile2(resolve64(file2));
|
|
184299
185057
|
if (!opened.validation.ok || !opened.header) {
|
|
184300
185058
|
io2.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
184301
185059
|
return 1;
|
|
@@ -184305,12 +185063,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184305
185063
|
io2.error(JSON.stringify({
|
|
184306
185064
|
ok: false,
|
|
184307
185065
|
error: "refusing to share a package that carries the app's source",
|
|
184308
|
-
detail: `${
|
|
185066
|
+
detail: `${resolve64(file2)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
|
|
184309
185067
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
184310
185068
|
}));
|
|
184311
185069
|
return 1;
|
|
184312
185070
|
}
|
|
184313
|
-
const archive =
|
|
185071
|
+
const archive = readFileSync103(resolve64(file2));
|
|
184314
185072
|
const result = await client2().createPackageShare({
|
|
184315
185073
|
app: opened.header.app,
|
|
184316
185074
|
releaseId: opened.header.releaseId,
|
|
@@ -184407,11 +185165,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184407
185165
|
const app = await appId(dir2);
|
|
184408
185166
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184409
185167
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
184410
|
-
temp =
|
|
185168
|
+
temp = mkdtempSync6(join87(tmpdir7(), "himi-run-build-"));
|
|
184411
185169
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
184412
185170
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
184413
185171
|
servedMissing = initial.missingBundles;
|
|
184414
|
-
source =
|
|
185172
|
+
source = join87(temp, app);
|
|
184415
185173
|
}
|
|
184416
185174
|
const chromeArg = str9(flags.chrome) ?? "preview";
|
|
184417
185175
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -184450,7 +185208,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184450
185208
|
if (!recordKit) return;
|
|
184451
185209
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
184452
185210
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
184453
|
-
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
185211
|
+
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join87(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
184454
185212
|
await refreshBoard();
|
|
184455
185213
|
};
|
|
184456
185214
|
const retract = async () => {
|
|
@@ -184473,9 +185231,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184473
185231
|
});
|
|
184474
185232
|
await announce(run2);
|
|
184475
185233
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
184476
|
-
await new Promise((
|
|
185234
|
+
await new Promise((resolve65) => {
|
|
184477
185235
|
const stop = () => {
|
|
184478
|
-
void retract().catch((e2) => io2.error(JSON.stringify({ run: "stop_cleanup_failed", message: e2.message }))).finally(() => run2.close().finally(() =>
|
|
185236
|
+
void retract().catch((e2) => io2.error(JSON.stringify({ run: "stop_cleanup_failed", message: e2.message }))).finally(() => run2.close().finally(() => resolve65()));
|
|
184479
185237
|
};
|
|
184480
185238
|
dropEarlySignals?.();
|
|
184481
185239
|
process.once("SIGINT", stop);
|
|
@@ -184486,7 +185244,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184486
185244
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
184487
185245
|
const hhpPreviewRoute = watch2 ? (await Promise.resolve().then(() => (init_hhp_preview(), hhp_preview_exports))).hhpPreviewResponse : null;
|
|
184488
185246
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
184489
|
-
if (watch2) served =
|
|
185247
|
+
if (watch2) served = mkdtempSync6(join87(tmpdir7(), "himi-run-served-"));
|
|
184490
185248
|
const running = await runPackage2(source, {
|
|
184491
185249
|
port,
|
|
184492
185250
|
chrome: chromeArg,
|
|
@@ -184515,8 +185273,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184515
185273
|
await announce(running);
|
|
184516
185274
|
if (watchKit && bus) {
|
|
184517
185275
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184518
|
-
const live3 =
|
|
184519
|
-
const manifestOf = (tree) => JSON.parse(
|
|
185276
|
+
const live3 = join87(running.releaseRoot, running.app);
|
|
185277
|
+
const manifestOf = (tree) => JSON.parse(readFileSync103(join87(tree, "release-manifest.json"), "utf8"));
|
|
184520
185278
|
let current = manifestOf(live3);
|
|
184521
185279
|
const failed3 = async (message) => {
|
|
184522
185280
|
if (stopping) return;
|
|
@@ -184527,7 +185285,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184527
185285
|
};
|
|
184528
185286
|
rebuild = watchKit.serialize(async () => {
|
|
184529
185287
|
const t0 = Date.now();
|
|
184530
|
-
const next =
|
|
185288
|
+
const next = mkdtempSync6(join87(tmpdir7(), "himi-run-build-"));
|
|
184531
185289
|
try {
|
|
184532
185290
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
184533
185291
|
if (bres.compileErrors.length) {
|
|
@@ -184544,18 +185302,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184544
185302
|
return;
|
|
184545
185303
|
}
|
|
184546
185304
|
if (stopping) return;
|
|
184547
|
-
const fresh = manifestOf(
|
|
185305
|
+
const fresh = manifestOf(join87(next, running.app));
|
|
184548
185306
|
const diff = watchKit.diffReleases(current, fresh);
|
|
184549
185307
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
184550
|
-
const changes = describeChanges2(live3,
|
|
185308
|
+
const changes = describeChanges2(live3, join87(next, running.app), diff);
|
|
184551
185309
|
const retired = `${live3}.retired-${Date.now()}`;
|
|
184552
|
-
|
|
185310
|
+
renameSync13(live3, retired);
|
|
184553
185311
|
try {
|
|
184554
|
-
|
|
185312
|
+
renameSync13(join87(next, running.app), live3);
|
|
184555
185313
|
} catch {
|
|
184556
|
-
cpSync3(
|
|
185314
|
+
cpSync3(join87(next, running.app), live3, { recursive: true });
|
|
184557
185315
|
}
|
|
184558
|
-
|
|
185316
|
+
rmSync23(retired, { recursive: true, force: true });
|
|
184559
185317
|
current = fresh;
|
|
184560
185318
|
servedMissing = outcome.missingBundles;
|
|
184561
185319
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
@@ -184565,7 +185323,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184565
185323
|
} catch (e2) {
|
|
184566
185324
|
await failed3(e2.message.split("\n")[0]);
|
|
184567
185325
|
} finally {
|
|
184568
|
-
|
|
185326
|
+
rmSync23(next, { recursive: true, force: true });
|
|
184569
185327
|
}
|
|
184570
185328
|
});
|
|
184571
185329
|
watcher2 = watchKit.watchContent(dir, () => {
|
|
@@ -184636,9 +185394,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184636
185394
|
} finally {
|
|
184637
185395
|
dropEarlySignals?.();
|
|
184638
185396
|
dropInitRecord?.();
|
|
184639
|
-
if (temp)
|
|
184640
|
-
if (served)
|
|
184641
|
-
if (browserCopy)
|
|
185397
|
+
if (temp) rmSync23(temp, { recursive: true, force: true });
|
|
185398
|
+
if (served) rmSync23(served, { recursive: true, force: true });
|
|
185399
|
+
if (browserCopy) rmSync23(browserCopy, { recursive: true, force: true });
|
|
184642
185400
|
}
|
|
184643
185401
|
}
|
|
184644
185402
|
case "preview": {
|
|
@@ -185180,7 +185938,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185180
185938
|
io2.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
185181
185939
|
return 2;
|
|
185182
185940
|
}
|
|
185183
|
-
if (!
|
|
185941
|
+
if (!existsSync82(file2)) {
|
|
185184
185942
|
io2.error(JSON.stringify({ error: `no such file: ${file2}` }));
|
|
185185
185943
|
return 2;
|
|
185186
185944
|
}
|
|
@@ -185236,7 +185994,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185236
185994
|
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."
|
|
185237
185995
|
};
|
|
185238
185996
|
if (kind === "tokens" || kind === "app-config") {
|
|
185239
|
-
const body =
|
|
185997
|
+
const body = readFileSync103(file2, "utf8");
|
|
185240
185998
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
185241
185999
|
return runReleasePatch({
|
|
185242
186000
|
...common,
|
|
@@ -185251,7 +186009,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185251
186009
|
io2.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
185252
186010
|
return 2;
|
|
185253
186011
|
}
|
|
185254
|
-
const descriptor =
|
|
186012
|
+
const descriptor = readFileSync103(file2, "utf8");
|
|
185255
186013
|
try {
|
|
185256
186014
|
JSON.parse(descriptor);
|
|
185257
186015
|
} catch (e2) {
|
|
@@ -185291,8 +186049,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185291
186049
|
extra: { kind, screen: id, file: { path: file2, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
185292
186050
|
});
|
|
185293
186051
|
}
|
|
185294
|
-
const bytes2 =
|
|
185295
|
-
const sha2 =
|
|
186052
|
+
const bytes2 = readFileSync103(file2);
|
|
186053
|
+
const sha2 = createHash45("sha256").update(bytes2).digest("hex");
|
|
185296
186054
|
const forScreens = (str9(flags["for-screen"]) ?? "").split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
185297
186055
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
185298
186056
|
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 }));
|
|
@@ -185435,7 +186193,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185435
186193
|
}
|
|
185436
186194
|
let def;
|
|
185437
186195
|
try {
|
|
185438
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
186196
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync103(arg.slice(1), "utf8") : arg);
|
|
185439
186197
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
185440
186198
|
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}`] }));
|
|
185441
186199
|
return 2;
|
|
@@ -185717,7 +186475,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185717
186475
|
const rememberLastDist = async (jobs2) => {
|
|
185718
186476
|
try {
|
|
185719
186477
|
const dir = contentDir(flags);
|
|
185720
|
-
if (!
|
|
186478
|
+
if (!existsSync82(join87(dir, "himalaya.content.json"))) return;
|
|
185721
186479
|
const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
|
|
185722
186480
|
const own5 = await appId(dir);
|
|
185723
186481
|
for (const job of jobs2) {
|
|
@@ -185957,7 +186715,7 @@ ${label2}`);
|
|
|
185957
186715
|
const platform = str9(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
185958
186716
|
{
|
|
185959
186717
|
const distDir = contentDir(flags);
|
|
185960
|
-
if (
|
|
186718
|
+
if (existsSync82(join87(distDir, "himalaya.content.json"))) {
|
|
185961
186719
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
185962
186720
|
const errors = issues.filter((i2) => i2.severity === "error");
|
|
185963
186721
|
for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
|
|
@@ -186297,7 +187055,7 @@ ${label2}`);
|
|
|
186297
187055
|
const dpxPath = dpxSessionTokenPath();
|
|
186298
187056
|
let dpx;
|
|
186299
187057
|
try {
|
|
186300
|
-
dpx =
|
|
187058
|
+
dpx = readFileSync103(dpxPath, "utf8").trim();
|
|
186301
187059
|
} catch {
|
|
186302
187060
|
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` }));
|
|
186303
187061
|
return 1;
|
|
@@ -186760,7 +187518,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
186760
187518
|
const path2 = dpxSessionTokenPath();
|
|
186761
187519
|
let raw;
|
|
186762
187520
|
try {
|
|
186763
|
-
raw =
|
|
187521
|
+
raw = readFileSync103(path2, "utf8");
|
|
186764
187522
|
} catch {
|
|
186765
187523
|
io2.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
186766
187524
|
return 1;
|