@popcraft/cli 0.32.1 → 0.34.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/popcraft.mjs +123 -19
- package/package.json +2 -2
package/dist/popcraft.mjs
CHANGED
|
@@ -594,7 +594,7 @@ var init_openapi = __esm({
|
|
|
594
594
|
init_api_limits();
|
|
595
595
|
init_listing();
|
|
596
596
|
init_groups();
|
|
597
|
-
API_VERSION = "1.
|
|
597
|
+
API_VERSION = "1.4.0";
|
|
598
598
|
ref = (name2) => ({ $ref: `#/components/schemas/${name2}` });
|
|
599
599
|
str = { type: "string" };
|
|
600
600
|
nstr = { type: ["string", "null"] };
|
|
@@ -897,7 +897,7 @@ Lists are paged: follow \`nextCursor\` (passing it as \`?cursor=\`) until it is
|
|
|
897
897
|
"/files/{key}": {
|
|
898
898
|
get: op("Files", "File metadata, your role and document JSON", "files:read", ok(ref("FileDetail")), { parameters: [key, query("depth", { type: "string", enum: ["metadata"] }, "Omit the document")] }),
|
|
899
899
|
put: op("Files", "Replace the document", "files:write", ok(ref("WriteResult")), {
|
|
900
|
-
description: "Body: a `Document`, `{ document }` or a .popcraft export. A live file takes the difference as one edit in its collaborative log, so people editing it see the change merge in; private (PopCorn) layers are never written. Send `If-Match: <revision>` to write only if the file has not changed since you read it. Needs edit access.",
|
|
900
|
+
description: "Body: a `Document`, `{ document }` or a .popcraft export, and may be gzipped (`Content-Encoding: gzip`). Requests are capped at about 4.5 MB on the wire, so upload pictures, video and fonts first (`POST /files/{key}/media`) and send a document that names them as `media://<hash>`. A live file takes the difference as one edit in its collaborative log, so people editing it see the change merge in; private (PopCorn) layers are never written. Send `If-Match: <revision>` to write only if the file has not changed since you read it. Needs edit access.",
|
|
901
901
|
parameters: [key, { name: "If-Match", in: "header", required: false, schema: str, description: "The `revision` you read" }],
|
|
902
902
|
requestBody: { required: true, content: { "application/json": { schema: ref("Document") } } },
|
|
903
903
|
responses: {
|
|
@@ -922,6 +922,14 @@ Lists are paged: follow \`nextCursor\` (passing it as \`?cursor=\`) until it is
|
|
|
922
922
|
"/files/{key}/nodes": { get: op("Files", "Nodes with their subtrees", "files:read", ok(ref("NodeResult")), { parameters: [key, query("ids", str, "Comma-separated node ids (\u2264 200)", true), query("depth", { type: "string", enum: ["1"] }, "Only the nodes themselves, no descendants")], responses: { "400": { description: "`ids` missing", content: errBody } } }) },
|
|
923
923
|
"/files/{key}/images": { get: op("Files", "Thumbnail and media assets the file references", "files:read", ok(ref("Images")), { parameters: [key] }) },
|
|
924
924
|
"/files/{key}/thumbnail": { get: op("Files", "Preview image bytes", "files:read", ok({ type: "string", format: "binary" }, "PNG or WebP bytes", "image/*"), { parameters: [key] }) },
|
|
925
|
+
"/files/{key}/media": {
|
|
926
|
+
post: op("Files", "Upload media the file uses", "files:write", null, {
|
|
927
|
+
description: 'The raw bytes of a picture, video, audio or font file, with `x-media-hash` set to their hash (SHA-256, the first 32 hex characters). The document, or a command such as `font.add` (`src: "media://<hash>"`), can then name them. A workspace stores the same bytes once. Needs edit access.',
|
|
928
|
+
parameters: [key, { name: "x-media-hash", in: "header", required: true, schema: str, description: "The bytes' hash: the first 32 hex characters of their SHA-256" }],
|
|
929
|
+
requestBody: { required: true, content: { "*/*": { schema: { type: "string", format: "binary" } } } },
|
|
930
|
+
responses: { "200": ok(obj({ hash: str, uploaded: bool }, ["hash", "uploaded"]), "Already stored"), "201": ok(obj({ hash: str, uploaded: bool }, ["hash", "uploaded"]), "Stored"), "400": { description: "Missing hash, or the hash does not match the bytes", content: errBody }, "413": { description: "Over the plan's upload size", content: errBody } }
|
|
931
|
+
})
|
|
932
|
+
},
|
|
925
933
|
"/files/{key}/media/{hash}": { get: op("Files", "Media asset bytes", "files:read", ok({ type: "string", format: "binary" }, "The asset, with its own content type", "*/*"), { parameters: [key, id("hash", "From `/files/{key}/images`")] }) },
|
|
926
934
|
"/files/{key}/comments": {
|
|
927
935
|
get: op("Comments", "Comments (threads and replies), oldest first", "comments:read", ok(ref("CommentList")), { parameters: [key, query("limit", { ...int, minimum: 1, maximum: 500, default: 500 }, "Page size"), cursor] }),
|
|
@@ -1188,7 +1196,7 @@ function operations(spec = openapi) {
|
|
|
1188
1196
|
}
|
|
1189
1197
|
async function call(target2, method, path, opts = {}) {
|
|
1190
1198
|
const qs = new URLSearchParams(opts.query ?? {}).toString();
|
|
1191
|
-
const headers = { "user-agent": `popcraft-cli/${"0.
|
|
1199
|
+
const headers = { "user-agent": `popcraft-cli/${"0.34.0"}`, ...opts.headers };
|
|
1192
1200
|
if (target2.token) headers.authorization = `Bearer ${target2.token}`;
|
|
1193
1201
|
if (opts.contentType) headers["content-type"] = opts.contentType;
|
|
1194
1202
|
try {
|
|
@@ -32175,6 +32183,23 @@ var init_en2 = __esm({
|
|
|
32175
32183
|
"apiTokensDialog.used": "used {date}",
|
|
32176
32184
|
"appHeader.doubleClickToRename": "Double-click to rename",
|
|
32177
32185
|
"appHeader.fileName": "File name",
|
|
32186
|
+
"appStoreOffers.buyCredits": "Buy AI credits",
|
|
32187
|
+
"appStoreOffers.creditsAdded": "{credits} AI credits added to {teamName}.",
|
|
32188
|
+
"appStoreOffers.creditsGoTo": "Credits are added to {teamName} and pay for AI. They don't expire.",
|
|
32189
|
+
"appStoreOffers.failed": "The purchase did not go through.",
|
|
32190
|
+
"appStoreOffers.loading": "Loading App Store prices\u2026",
|
|
32191
|
+
"appStoreOffers.manage": "Manage in the App Store",
|
|
32192
|
+
"appStoreOffers.pack": "{credits} credits \xB7 {price}",
|
|
32193
|
+
"appStoreOffers.pending": "Your purchase is waiting for approval. It's added as soon as it goes through.",
|
|
32194
|
+
"appStoreOffers.perMonth": " / month",
|
|
32195
|
+
"appStoreOffers.perYear": " / year",
|
|
32196
|
+
"appStoreOffers.privacy": "Privacy Policy",
|
|
32197
|
+
"appStoreOffers.renewalTerms": "Payment is charged to your Apple Account. The subscription renews automatically at the price shown for each period unless you cancel it at least 24 hours before the period ends. Manage or cancel it in your App Store account settings.",
|
|
32198
|
+
"appStoreOffers.restore": "Restore purchases",
|
|
32199
|
+
"appStoreOffers.restored": "{count, plural, =0 {No purchases to restore.} one {Restored # purchase.} other {Restored # purchases.}}",
|
|
32200
|
+
"appStoreOffers.subscribe": "Subscribe",
|
|
32201
|
+
"appStoreOffers.subscribed": "Subscribed to {plan} \xB7 {teamName}.",
|
|
32202
|
+
"appStoreOffers.terms": "Terms of Use",
|
|
32178
32203
|
"assetsPanel.components": "Components",
|
|
32179
32204
|
"assetsPanel.documentColors": "Document colors",
|
|
32180
32205
|
"assetsPanel.editComponent": "Edit component",
|
|
@@ -34938,6 +34963,7 @@ var init_en2 = __esm({
|
|
|
34938
34963
|
"planDialog.isOnThePlan": "{teamName} is on the {value} plan.",
|
|
34939
34964
|
"planDialog.largestUpload": "Largest upload",
|
|
34940
34965
|
"planDialog.loadingPlans": "Loading plans\u2026",
|
|
34966
|
+
"planDialog.managedInAppStore": "Bought in the App Store. Manage or cancel it in the App Store on your iPad or Mac.",
|
|
34941
34967
|
"planDialog.mediaStorage": "Storage (media and websites)",
|
|
34942
34968
|
"planDialog.mo": "mo",
|
|
34943
34969
|
"planDialog.namedVersionsPerFile": "Named versions per file",
|
|
@@ -95224,6 +95250,11 @@ var init_idb = __esm({
|
|
|
95224
95250
|
});
|
|
95225
95251
|
|
|
95226
95252
|
// lib/storage/media-hash.ts
|
|
95253
|
+
var media_hash_exports = {};
|
|
95254
|
+
__export(media_hash_exports, {
|
|
95255
|
+
hashBytesSync: () => hashBytesSync,
|
|
95256
|
+
sha256Prefix: () => sha256Prefix
|
|
95257
|
+
});
|
|
95227
95258
|
function hashBytesSync(bytes2) {
|
|
95228
95259
|
const run4 = (seed2) => {
|
|
95229
95260
|
let h1 = 3735928559 ^ seed2, h22 = 1103547991 ^ seed2;
|
|
@@ -95238,6 +95269,10 @@ function hashBytesSync(bytes2) {
|
|
|
95238
95269
|
};
|
|
95239
95270
|
return run4(2654435769) + run4(2246822507 ^ bytes2.length);
|
|
95240
95271
|
}
|
|
95272
|
+
async function sha256Prefix(bytes2) {
|
|
95273
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes2);
|
|
95274
|
+
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("").slice(0, 32);
|
|
95275
|
+
}
|
|
95241
95276
|
var init_media_hash = __esm({
|
|
95242
95277
|
"lib/storage/media-hash.ts"() {
|
|
95243
95278
|
"use strict";
|
|
@@ -261307,8 +261342,13 @@ var init_plans = __esm({
|
|
|
261307
261342
|
});
|
|
261308
261343
|
|
|
261309
261344
|
// lib/billing/purchases.ts
|
|
261345
|
+
function purchaseChannel() {
|
|
261346
|
+
const store6 = storePlatform();
|
|
261347
|
+
if (store6 === null) return "web";
|
|
261348
|
+
return store6 === "ios" || store6 === "macos" ? "app_store" : null;
|
|
261349
|
+
}
|
|
261310
261350
|
function purchasesAllowed() {
|
|
261311
|
-
return
|
|
261351
|
+
return purchaseChannel() === "web";
|
|
261312
261352
|
}
|
|
261313
261353
|
function limitMessageHere(d) {
|
|
261314
261354
|
return limitMessage(purchasesAllowed() ? d : { ...d, upgradeTo: null });
|
|
@@ -310142,6 +310182,7 @@ async function dispatchShaped(key5, options) {
|
|
|
310142
310182
|
var onViolation;
|
|
310143
310183
|
var init_dispatch = __esm({
|
|
310144
310184
|
"lib/commands/dispatch.ts"() {
|
|
310185
|
+
"use strict";
|
|
310145
310186
|
init_errors();
|
|
310146
310187
|
init_registry();
|
|
310147
310188
|
init_confirm();
|
|
@@ -310532,6 +310573,7 @@ function creditLine(c2) {
|
|
|
310532
310573
|
var MAX_PHOTO_PAGE, MAX_PHOTO_QUERY, UUID, isPhotoId, photoImagePath;
|
|
310533
310574
|
var init_stock = __esm({
|
|
310534
310575
|
"lib/photos/stock.ts"() {
|
|
310576
|
+
"use strict";
|
|
310535
310577
|
MAX_PHOTO_PAGE = 12;
|
|
310536
310578
|
MAX_PHOTO_QUERY = 200;
|
|
310537
310579
|
UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -315656,6 +315698,7 @@ async function exportSettingFile(renderer, node2, setting, doc2, styles) {
|
|
|
315656
315698
|
var MIME, DEFAULT_EXPORT, exportSettingsOf;
|
|
315657
315699
|
var init_export = __esm({
|
|
315658
315700
|
"lib/io/export.ts"() {
|
|
315701
|
+
"use strict";
|
|
315659
315702
|
init_download();
|
|
315660
315703
|
init_scene_graph();
|
|
315661
315704
|
init_codecs();
|
|
@@ -316090,7 +316133,6 @@ function videoPixelSize(resolution, aspect) {
|
|
|
316090
316133
|
var VIDEO_ASPECTS, VIDEO_RESOLUTIONS, SEEDANCE_ASPECTS, range, VIDEO_MODELS, DEFAULT_VIDEO_MODEL, videoModel, VIDEO_LIMITS;
|
|
316091
316134
|
var init_video_models = __esm({
|
|
316092
316135
|
"lib/ai/video-models.ts"() {
|
|
316093
|
-
"use strict";
|
|
316094
316136
|
VIDEO_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
|
|
316095
316137
|
VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
316096
316138
|
SEEDANCE_ASPECTS = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"];
|
|
@@ -326442,7 +326484,7 @@ var init_package = __esm({
|
|
|
326442
326484
|
"packages/runtime/package.json"() {
|
|
326443
326485
|
package_default = {
|
|
326444
326486
|
name: "@popcraft/runtime",
|
|
326445
|
-
version: "0.
|
|
326487
|
+
version: "0.34.0",
|
|
326446
326488
|
description: "What code exported from PopCraft shares: the meaning of expressions (operators and functions) and, as it grows, the parts of a design's behaviour that are common code rather than generated React.",
|
|
326447
326489
|
license: "MIT",
|
|
326448
326490
|
homepage: "https://popcraft.app/docs/exporting/nextjs",
|
|
@@ -351108,6 +351150,7 @@ function exportsOf(source3) {
|
|
|
351108
351150
|
var CODE_LIMITS, packageOf;
|
|
351109
351151
|
var init_source2 = __esm({
|
|
351110
351152
|
"lib/code/source.ts"() {
|
|
351153
|
+
"use strict";
|
|
351111
351154
|
CODE_LIMITS = { modules: 100, sourceLength: 2e5, packages: 12 };
|
|
351112
351155
|
packageOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).join("/");
|
|
351113
351156
|
}
|
|
@@ -351150,6 +351193,7 @@ function compileModule(module2) {
|
|
|
351150
351193
|
var import_sucrase, BUILT_IN, memo4;
|
|
351151
351194
|
var init_compile2 = __esm({
|
|
351152
351195
|
"lib/code/compile.ts"() {
|
|
351196
|
+
"use strict";
|
|
351153
351197
|
import_sucrase = __toESM(require_dist2());
|
|
351154
351198
|
init_source2();
|
|
351155
351199
|
init_source2();
|
|
@@ -360124,6 +360168,7 @@ var init_publish = __esm({
|
|
|
360124
360168
|
var storeOpsSeam;
|
|
360125
360169
|
var init_seams = __esm({
|
|
360126
360170
|
"lib/commands/seams.ts"() {
|
|
360171
|
+
"use strict";
|
|
360127
360172
|
storeOpsSeam = (st) => ({
|
|
360128
360173
|
booleanOperation: (op4) => st().booleanOperation(op4),
|
|
360129
360174
|
flatten: () => st().flattenSelection(),
|
|
@@ -396078,7 +396123,11 @@ async function fontBytes(args2, ctx2) {
|
|
|
396078
396123
|
}
|
|
396079
396124
|
} else if (args2.src) {
|
|
396080
396125
|
const { isMediaUrl: isMediaUrl2, loadMediaBlob: loadMediaBlob2 } = await Promise.resolve().then(() => (init_media_store(), media_store_exports));
|
|
396081
|
-
if (isMediaUrl2(args2.src)) {
|
|
396126
|
+
if (isMediaUrl2(args2.src) && ctx2.can("media")) {
|
|
396127
|
+
const bytes2 = await ctx2.use("media").read(args2.src);
|
|
396128
|
+
if (!bytes2) throw new CommandError(`${args2.src} is not in this file's media: upload it first (POST /files/{key}/media).`, "not_found");
|
|
396129
|
+
got = { bytes: bytes2 };
|
|
396130
|
+
} else if (isMediaUrl2(args2.src)) {
|
|
396082
396131
|
const blob = await loadMediaBlob2(args2.src);
|
|
396083
396132
|
if (!blob) throw new CommandError(`${args2.src} is not on this device.`, "not_found");
|
|
396084
396133
|
got = { bytes: new Uint8Array(await blob.arrayBuffer()) };
|
|
@@ -396155,7 +396204,7 @@ var init_font = __esm({
|
|
|
396155
396204
|
params: external_exports.object({
|
|
396156
396205
|
family: external_exports.string().trim().min(1).max(200).optional().describe("The family name texts will use (default: the name in the file). Texts set in it draw in this file."),
|
|
396157
396206
|
file: external_exports.string().min(1).max(4096).optional().describe("A font file on this machine, read by the CLI: .ttf, .otf, .ttc, .woff or .woff2."),
|
|
396158
|
-
src: external_exports.string().max(MAX_SRC).optional().describe("The font file as a base64 data URL, or a media:// ref already on this device."),
|
|
396207
|
+
src: external_exports.string().max(MAX_SRC).optional().describe("The font file as a base64 data URL, or a media:// ref already on this device (through the API: already uploaded to the file's media)."),
|
|
396159
396208
|
weight: external_exports.number().int().min(1).max(1e3).optional().describe("The weight this face stands for (default: the file's)."),
|
|
396160
396209
|
style: external_exports.enum(["normal", "italic"]).optional().describe("normal or italic (default: the file's)."),
|
|
396161
396210
|
face: faceParam.optional()
|
|
@@ -396170,10 +396219,9 @@ var init_font = __esm({
|
|
|
396170
396219
|
run: async (args2, ctx2) => {
|
|
396171
396220
|
const { bytes: bytes2, fileName: fileName2 } = await fontBytes(args2, ctx2);
|
|
396172
396221
|
const { face, family, weight, style, info: info2 } = await resolveFace(bytes2, args2);
|
|
396173
|
-
const { internBytes: internBytes2 } = await Promise.resolve().then(() => (init_media_store(), media_store_exports));
|
|
396174
396222
|
const { fontMime: fontMime2 } = await Promise.resolve().then(() => (init_sfnt(), sfnt_exports));
|
|
396175
396223
|
const { addDocumentFont: addDocumentFont2 } = await Promise.resolve().then(() => (init_document_fonts(), document_fonts_exports));
|
|
396176
|
-
const src =
|
|
396224
|
+
const src = ctx2.can("media") ? await ctx2.use("media").store(bytes2, fontMime2(bytes2)) : (await Promise.resolve().then(() => (init_media_store(), media_store_exports))).internBytes(bytes2, fontMime2(bytes2));
|
|
396177
396225
|
const font = {
|
|
396178
396226
|
id: `font-${src.slice(8, 20)}-${face.index}-${weight}-${style === "italic" ? "i" : "n"}`,
|
|
396179
396227
|
family,
|
|
@@ -397472,6 +397520,7 @@ function designRecorder() {
|
|
|
397472
397520
|
var installed;
|
|
397473
397521
|
var init_recorders = __esm({
|
|
397474
397522
|
"lib/agent/design-script/recorders.ts"() {
|
|
397523
|
+
"use strict";
|
|
397475
397524
|
installed = null;
|
|
397476
397525
|
}
|
|
397477
397526
|
});
|
|
@@ -407837,6 +407886,7 @@ var init_headless2 = __esm({
|
|
|
407837
407886
|
|
|
407838
407887
|
// packages/cli/src/cloud.ts
|
|
407839
407888
|
import { existsSync as existsSync4 } from "node:fs";
|
|
407889
|
+
import { gzipSync } from "node:zlib";
|
|
407840
407890
|
function signedIn2(target2) {
|
|
407841
407891
|
if (!target2.token) throw new CliError(`Not signed in to ${target2.url}: run \`popcraft login\` (with a files:write token).`);
|
|
407842
407892
|
return target2;
|
|
@@ -407851,25 +407901,79 @@ async function runPush(args2, flags, target2, out) {
|
|
|
407851
407901
|
const name2 = flagString(flags, "name");
|
|
407852
407902
|
if (key5) {
|
|
407853
407903
|
const ifMatch = flagString(flags, "ifMatch");
|
|
407854
|
-
const
|
|
407904
|
+
const { doc: doc3, media: media3 } = await separateMedia(document2);
|
|
407905
|
+
await uploadMedia2(t3, key5, media3);
|
|
407906
|
+
const body = gzipJson({ document: name2 ? { ...doc3, name: name2 } : doc3 });
|
|
407855
407907
|
const res2 = await callJson(t3, "PUT", `/files/${encodeURIComponent(key5)}`, {
|
|
407856
|
-
body
|
|
407857
|
-
|
|
407858
|
-
headers: ifMatch ? { "if-match": ifMatch } : void 0
|
|
407908
|
+
...body,
|
|
407909
|
+
headers: { ...body.headers, ...ifMatch ? { "if-match": ifMatch } : {} }
|
|
407859
407910
|
});
|
|
407860
407911
|
out.result(res2.changed ? `Updated ${key5} (revision ${res2.revision})${res2.live ? "; open sessions merged it" : ""}.` : `${key5} already matched ${file2}.`, out.json ? { key: key5, ...res2 } : void 0);
|
|
407861
407912
|
return;
|
|
407862
407913
|
}
|
|
407863
|
-
const
|
|
407864
|
-
|
|
407914
|
+
const { doc: doc2, media: media2 } = await separateMedia(document2);
|
|
407915
|
+
const res = await callJson(t3, "POST", "/files", gzipJson({
|
|
407916
|
+
document: doc2,
|
|
407865
407917
|
...name2 ? { name: name2 } : {},
|
|
407866
407918
|
...flagString(flags, "workspace") ? { workspaceId: flagString(flags, "workspace") } : {},
|
|
407867
407919
|
...flagString(flags, "project") ? { projectId: flagString(flags, "project") } : {},
|
|
407868
407920
|
...flagString(flags, "folder") ? { folderId: flagString(flags, "folder") } : {}
|
|
407869
|
-
});
|
|
407870
|
-
|
|
407921
|
+
}));
|
|
407922
|
+
await uploadMedia2(t3, res.key, media2);
|
|
407871
407923
|
out.result(`Created ${res.key}: ${t3.url}/pop/${res.key}`, out.json ? { ...res, url: `${t3.url}/pop/${res.key}` } : void 0);
|
|
407872
407924
|
}
|
|
407925
|
+
async function separateMedia(document2) {
|
|
407926
|
+
const { MEDIA_SCHEME: MEDIA_SCHEME2, isMediaUrl: isMediaUrl2, loadMediaBlob: loadMediaBlob2 } = await Promise.resolve().then(() => (init_media_store(), media_store_exports));
|
|
407927
|
+
const { hashBytesSync: hashBytesSync2 } = await Promise.resolve().then(() => (init_media_hash(), media_hash_exports));
|
|
407928
|
+
const media2 = /* @__PURE__ */ new Map();
|
|
407929
|
+
const pending8 = [];
|
|
407930
|
+
const walk4 = (v) => {
|
|
407931
|
+
if (typeof v === "string") {
|
|
407932
|
+
if (isMediaUrl2(v)) {
|
|
407933
|
+
const hash3 = v.slice(MEDIA_SCHEME2.length);
|
|
407934
|
+
if (!media2.has(hash3)) {
|
|
407935
|
+
media2.set(hash3, { bytes: new Uint8Array(0), type: "" });
|
|
407936
|
+
pending8.push(loadMediaBlob2(v).then(async (blob) => {
|
|
407937
|
+
if (blob) media2.set(hash3, { bytes: new Uint8Array(await blob.arrayBuffer()), type: blob.type });
|
|
407938
|
+
else media2.delete(hash3);
|
|
407939
|
+
}));
|
|
407940
|
+
}
|
|
407941
|
+
return v;
|
|
407942
|
+
}
|
|
407943
|
+
const m = /^data:([^;,]*)(?:;[^,]*)?;base64,/.exec(v);
|
|
407944
|
+
if (m && v.length > 1024) {
|
|
407945
|
+
const bytes2 = Uint8Array.from(Buffer.from(v.slice(m[0].length), "base64"));
|
|
407946
|
+
const hash3 = hashBytesSync2(bytes2);
|
|
407947
|
+
media2.set(hash3, { bytes: bytes2, type: m[1] || "application/octet-stream" });
|
|
407948
|
+
return MEDIA_SCHEME2 + hash3;
|
|
407949
|
+
}
|
|
407950
|
+
return v;
|
|
407951
|
+
}
|
|
407952
|
+
if (Array.isArray(v)) return v.map(walk4);
|
|
407953
|
+
if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k2, x2]) => [k2, walk4(x2)]));
|
|
407954
|
+
return v;
|
|
407955
|
+
};
|
|
407956
|
+
const doc2 = walk4(document2);
|
|
407957
|
+
await Promise.all(pending8);
|
|
407958
|
+
return { doc: doc2, media: media2 };
|
|
407959
|
+
}
|
|
407960
|
+
async function uploadMedia2(t3, key5, media2) {
|
|
407961
|
+
const queue2 = [...media2];
|
|
407962
|
+
const worker2 = async () => {
|
|
407963
|
+
for (let next2 = queue2.shift(); next2; next2 = queue2.shift()) {
|
|
407964
|
+
const [hash3, { bytes: bytes2, type }] = next2;
|
|
407965
|
+
await callJson(t3, "POST", `/files/${encodeURIComponent(key5)}/media`, {
|
|
407966
|
+
body: bytes2,
|
|
407967
|
+
contentType: type || "application/octet-stream",
|
|
407968
|
+
headers: { "x-media-hash": hash3 }
|
|
407969
|
+
});
|
|
407970
|
+
}
|
|
407971
|
+
};
|
|
407972
|
+
await Promise.all(Array.from({ length: Math.min(4, queue2.length) }, worker2));
|
|
407973
|
+
}
|
|
407974
|
+
function gzipJson(value3) {
|
|
407975
|
+
return { body: gzipSync(JSON.stringify(value3)), contentType: "application/json", headers: { "content-encoding": "gzip" } };
|
|
407976
|
+
}
|
|
407873
407977
|
async function runPull(args2, flags, target2, out) {
|
|
407874
407978
|
const [key5, dest] = args2;
|
|
407875
407979
|
if (!key5) throw usage("Usage: popcraft pull <key> [file.popcraft]");
|
|
@@ -409792,7 +409896,7 @@ init_resources();
|
|
|
409792
409896
|
init_desktop();
|
|
409793
409897
|
init_hypery();
|
|
409794
409898
|
import { createInterface } from "node:readline";
|
|
409795
|
-
var VERSION2 = "0.
|
|
409899
|
+
var VERSION2 = "0.34.0";
|
|
409796
409900
|
var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
|
|
409797
409901
|
|
|
409798
409902
|
Files (headless, on .popcraft files):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@popcraft/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "The PopCraft command line: edit .popcraft files headlessly, call the REST API, publish to the marketplace and manage the desktop app's local plugins, themes, fonts, skills and agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://popcraft.app/docs/api/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"esbuild": "0.28.2"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@popcraft/kit": "0.
|
|
37
|
+
"@popcraft/kit": "0.34.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "node build.mjs",
|