@popcraft/cli 0.5.0 → 0.5.1

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.
Files changed (2) hide show
  1. package/dist/popcraft.mjs +43 -57
  2. package/package.json +2 -2
package/dist/popcraft.mjs CHANGED
@@ -1166,7 +1166,7 @@ function operations(spec = openapi) {
1166
1166
  }
1167
1167
  async function call(target2, method, path, opts = {}) {
1168
1168
  const qs = new URLSearchParams(opts.query ?? {}).toString();
1169
- const headers = { "user-agent": `popcraft-cli/${"0.5.0"}`, ...opts.headers };
1169
+ const headers = { "user-agent": `popcraft-cli/${"0.5.1"}`, ...opts.headers };
1170
1170
  if (target2.token) headers.authorization = `Bearer ${target2.token}`;
1171
1171
  if (opts.contentType) headers["content-type"] = opts.contentType;
1172
1172
  try {
@@ -89015,7 +89015,6 @@ function estimateBpm(onsets) {
89015
89015
  var WINDOW, HOP, NEIGHBOURS, MIN_GAP_MS, RISE_BACK, SILENCE, QUIET_DB;
89016
89016
  var init_audio_onsets = __esm({
89017
89017
  "lib/motion/audio-onsets.ts"() {
89018
- "use strict";
89019
89018
  WINDOW = 1024;
89020
89019
  HOP = 256;
89021
89020
  NEIGHBOURS = 16;
@@ -248677,7 +248676,6 @@ function removeRecords(doc2, ids2) {
248677
248676
  var COLLECTION_LIMITS, slugify2, dataMemo, withData, ITEM_RECORD, MARK, itemMark, templateRecord, compare, TOKEN2, hasItemToken, layerId, copyRecord, coerce3, newId;
248678
248677
  var init_collections = __esm({
248679
248678
  "lib/document/collections.ts"() {
248680
- "use strict";
248681
248679
  init_expressions2();
248682
248680
  init_variables();
248683
248681
  init_contract();
@@ -293016,7 +293014,6 @@ function playSegments(tr, elapsed, horizon) {
293016
293014
  var MIX_SAMPLE_RATE, toSample, sourceKey2;
293017
293015
  var init_audio_plan = __esm({
293018
293016
  "lib/motion/audio-plan.ts"() {
293019
- "use strict";
293020
293017
  init_audio_clips();
293021
293018
  MIX_SAMPLE_RATE = 48e3;
293022
293019
  toSample = (ms2, rate) => Math.round(ms2 * rate / 1e3);
@@ -297252,7 +297249,6 @@ function downloadBlob(blob, filename) {
297252
297249
  }
297253
297250
  var init_download = __esm({
297254
297251
  "lib/io/download.ts"() {
297255
- "use strict";
297256
297252
  }
297257
297253
  });
297258
297254
 
@@ -298125,7 +298121,6 @@ function applyTextPath(layout2, path, tp, rebase = true) {
298125
298121
  var defaultCircleRadius, ownsPath, mapPoint;
298126
298122
  var init_text_path = __esm({
298127
298123
  "lib/engine/text/text-path.ts"() {
298128
- "use strict";
298129
298124
  init_scene_graph();
298130
298125
  init_transform();
298131
298126
  init_shape_to_path();
@@ -298243,7 +298238,6 @@ function areaBounds(rings) {
298243
298238
  }
298244
298239
  var init_text_area = __esm({
298245
298240
  "lib/engine/text/text-area.ts"() {
298246
- "use strict";
298247
298241
  }
298248
298242
  });
298249
298243
 
@@ -301132,7 +301126,6 @@ ${photoCreditsText(credits).replace(/]]>/g, "]]]]><![CDATA[>")}]]></metadata>` :
301132
301126
  var resolvedFills2, resolvedStrokes2, roundedRectPath, shapePathFor, childrenOf2, rootMatrix2;
301133
301127
  var init_svg_export = __esm({
301134
301128
  "lib/io/svg-export.ts"() {
301135
- "use strict";
301136
301129
  init_credits();
301137
301130
  init_media_store();
301138
301131
  init_pattern_fill();
@@ -302310,7 +302303,6 @@ async function writeImage(w, img, color4) {
302310
302303
  var PT, MARK_LEN, MARK_GAP, MAX_TEX, MAX_RASTER_PIXELS, posterFrames, pdfOptionsFor;
302311
302304
  var init_pdf = __esm({
302312
302305
  "lib/io/pdf/index.ts"() {
302313
- "use strict";
302314
302306
  init_credits();
302315
302307
  init_scene_graph();
302316
302308
  init_export_fills();
@@ -302475,7 +302467,6 @@ async function exportSettingFile(renderer, node2, setting, doc2, styles) {
302475
302467
  var MIME, DEFAULT_EXPORT, exportSettingsOf;
302476
302468
  var init_export = __esm({
302477
302469
  "lib/io/export.ts"() {
302478
- "use strict";
302479
302470
  init_download();
302480
302471
  init_scene_graph();
302481
302472
  init_codecs();
@@ -308589,7 +308580,6 @@ var init_motion_shared = __esm({
308589
308580
  var layer, CODE_FORMATS, CODE_FORMAT_IDS, codeFormat, isLayerFormat, layerFormats, downloadFormats;
308590
308581
  var init_formats = __esm({
308591
308582
  "lib/io/web/formats.ts"() {
308592
- "use strict";
308593
308583
  layer = (o) => ({ scope: "layer", download: true, pictures: "svg", platform: "WEB", plays: false, ...o });
308594
308584
  CODE_FORMATS = {
308595
308585
  css: layer({ label: "CSS", note: "The stylesheet alone.", extension: "css", mime: "text/css", plays: true, download: false }),
@@ -312741,7 +312731,7 @@ var init_package = __esm({
312741
312731
  "packages/runtime/package.json"() {
312742
312732
  package_default = {
312743
312733
  name: "@popcraft/runtime",
312744
- version: "0.5.0",
312734
+ version: "0.5.1",
312745
312735
  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.",
312746
312736
  license: "MIT",
312747
312737
  homepage: "https://popcraft.app/docs/exporting/nextjs",
@@ -337094,7 +337084,6 @@ function hashOf(text) {
337094
337084
  }
337095
337085
  var init_hash = __esm({
337096
337086
  "lib/code/hash.ts"() {
337097
- "use strict";
337098
337087
  }
337099
337088
  });
337100
337089
 
@@ -337594,7 +337583,6 @@ function fieldPart(nodes, id3) {
337594
337583
  var cleanName2;
337595
337584
  var init_controls = __esm({
337596
337585
  "lib/document/controls.ts"() {
337597
- "use strict";
337598
337586
  cleanName2 = (raw) => raw.trim().replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
337599
337587
  }
337600
337588
  });
@@ -338538,7 +338526,6 @@ function routesOf(screens) {
338538
338526
  var slug2;
338539
338527
  var init_routes = __esm({
338540
338528
  "lib/document/routes.ts"() {
338541
- "use strict";
338542
338529
  slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
338543
338530
  }
338544
338531
  });
@@ -338837,7 +338824,6 @@ function webTreeFor(doc2, nodeId2, lang, opts = {}) {
338837
338824
  var WEB_LANGUAGES, assetKindFor, playsMotion, WRITERS, serializeFor, extensionFor;
338838
338825
  var init_web = __esm({
338839
338826
  "lib/io/web/index.ts"() {
338840
- "use strict";
338841
338827
  init_compose2();
338842
338828
  init_email();
338843
338829
  init_html();
@@ -339030,7 +339016,6 @@ function rendererAssetResolvers(doc2, scale = 2) {
339030
339016
  var nodeFor, mainNodeFor, asDataURL;
339031
339017
  var init_resolvers = __esm({
339032
339018
  "lib/io/web/resolvers.ts"() {
339033
- "use strict";
339034
339019
  init_scene_graph();
339035
339020
  init_renderer_registry();
339036
339021
  init_export();
@@ -341397,7 +341382,6 @@ function diagnosticsText(diagnostics) {
341397
341382
  var HARNESS_NAMES, plainDiagnostics;
341398
341383
  var init_shader_diagnostics = __esm({
341399
341384
  "lib/engine/shader-diagnostics.ts"() {
341400
- "use strict";
341401
341385
  HARNESS_NAMES = ["ShaderUniforms", "VOut", "vs_main", "fs_main", "u", "p"];
341402
341386
  plainDiagnostics = (errors2) => errors2.map((message) => ({ line: null, column: null, message, severity: "error" }));
341403
341387
  }
@@ -344863,7 +344847,6 @@ function designRecorder() {
344863
344847
  var installed;
344864
344848
  var init_recorders = __esm({
344865
344849
  "lib/agent/design-script/recorders.ts"() {
344866
- "use strict";
344867
344850
  installed = null;
344868
344851
  }
344869
344852
  });
@@ -392622,6 +392605,7 @@ var init_pictures = __esm({
392622
392605
  var template_exports = {};
392623
392606
  __export(template_exports, {
392624
392607
  ownCopy: () => ownCopy,
392608
+ rankOfficial: () => rankOfficial,
392625
392609
  runTemplate: () => runTemplate,
392626
392610
  sourceFiles: () => sourceFiles
392627
392611
  });
@@ -392648,32 +392632,27 @@ function sourceFiles(paths) {
392648
392632
  });
392649
392633
  }
392650
392634
  async function loadSource(file2) {
392651
- let mod;
392652
- try {
392653
- mod = await import(pathToFileURL2(file2).href);
392654
- } catch (e) {
392655
- throw new CliError(`${relative4(process.cwd(), file2)}: ${e.message}`);
392656
- }
392635
+ const mod = await import(pathToFileURL2(file2).href);
392657
392636
  const s = mod.default;
392658
392637
  return s && typeof s === "object" && typeof s.id === "string" && s.meta && typeof s.build === "function" ? s : null;
392659
392638
  }
392660
392639
  async function buildAll(files, out, appUrl, o) {
392661
392640
  if (!files.length) throw usage("No template sources (files whose default export is `defineTemplate({ \u2026 })`).");
392641
+ process.env.POPCRAFT_APP_URL ??= appUrl;
392662
392642
  const { kit } = await projectKit(dirname3(files[0]));
392663
392643
  await kit.prepareFonts(files.map((f2) => readFileSync11(f2, "utf8")));
392664
392644
  const built = [];
392645
+ let broken2 = 0;
392665
392646
  for (const file2 of files) {
392666
- const source3 = await loadSource(file2);
392667
- if (!source3) continue;
392668
- let template2;
392669
- for (let tries = 0; !template2; tries++) {
392670
- try {
392671
- template2 = kit.buildTemplateSource(source3);
392672
- } catch (e) {
392673
- const hash3 = e.hash;
392674
- if (!hash3 || tries > 64) throw new CliError(`${relative4(process.cwd(), file2)}: ${e.message}`);
392675
- await fetchShippedMedia(appUrl, hash3, o);
392676
- }
392647
+ let source3, template2;
392648
+ try {
392649
+ source3 = await loadSource(file2);
392650
+ if (!source3) continue;
392651
+ template2 = await kit.buildFromSource(source3, { appUrl });
392652
+ } catch (e) {
392653
+ o.info(`\u2716 ${relative4(process.cwd(), file2)}: ${e.message}`);
392654
+ broken2++;
392655
+ continue;
392677
392656
  }
392678
392657
  const dir = resolve4(out, source3.id);
392679
392658
  mkdirSync7(join10(dir, "media"), { recursive: true });
@@ -392683,15 +392662,7 @@ async function buildAll(files, out, appUrl, o) {
392683
392662
  o.info(`\u2713 ${relative4(process.cwd(), file2)} \u2192 ${relative4(process.cwd(), dir)} ${template2.meta.sizes ? template2.meta.sizes.join(", ") : ""}`);
392684
392663
  built.push({ file: file2, source: source3, template: template2, dir });
392685
392664
  }
392686
- return built;
392687
- }
392688
- async function fetchShippedMedia(appUrl, hash3, o) {
392689
- const dir = process.env.POPCRAFT_MEDIA_DIR ?? join10((await import("node:os")).homedir(), ".cache", "popcraft", "media");
392690
- o.info(` fetching PopCraft media ${hash3}\u2026`);
392691
- const res = await fetch(`${appUrl}/templates/media/${hash3}`).catch(() => null);
392692
- if (!res?.ok) throw new CliError(`Could not fetch ${appUrl}/templates/media/${hash3}`);
392693
- mkdirSync7(dir, { recursive: true });
392694
- writeFileSync8(join10(dir, hash3), new Uint8Array(await res.arrayBuffer()));
392665
+ return Object.assign(built, { broken: broken2 });
392695
392666
  }
392696
392667
  async function checkAll(built, o) {
392697
392668
  const { kit } = await projectKit(dirname3(built[0].file));
@@ -392708,6 +392679,16 @@ async function checkAll(built, o) {
392708
392679
  }
392709
392680
  return ok2;
392710
392681
  }
392682
+ function rankOfficial(index2, query2, f2 = {}) {
392683
+ const words = query2.toLowerCase().split(/\s+/).filter(Boolean);
392684
+ const one = (text, w) => new RegExp(`(^|[^a-z0-9])${w.replace(/[^a-z0-9]/g, "")}(e?s)?([^a-z0-9]|$)`).test(text);
392685
+ const has = (text, w) => one(text, w) || w.length > 3 && (one(text, w.replace(/es$/, "")) || one(text, w.replace(/s$/, "")));
392686
+ return Object.entries(index2).filter(([, e]) => (!f2.platform || e.platforms.includes(f2.platform)) && (!f2.format || e.formats.includes(f2.format)) && (!f2.useCase || e.useCases.includes(f2.useCase)) && (!f2.category || e.category === f2.category) && (!f2.kind || e.kind === f2.kind.toUpperCase()) && (!f2.animated || !!e.animated)).map(([id3, e]) => {
392687
+ const name2 = `${id3} ${e.name}`.toLowerCase(), tags = [...e.tags, ...e.formats, ...e.platforms, ...e.useCases, e.category].join(" ").toLowerCase(), about = e.description.toLowerCase();
392688
+ const per = words.map((w) => (has(name2, w) ? 3 : 0) + (has(tags, w) ? 2 : 0) + (has(about, w) ? 1 : 0));
392689
+ return { id: id3, e, matched: per.filter(Boolean).length, score: per.reduce((a, b) => a + b, 0) };
392690
+ }).filter((r) => !words.length || r.score > 0).sort((a, b) => b.matched - a.matched || b.score - a.score || a.id.localeCompare(b.id)).map(({ matched: _m, ...r }) => r);
392691
+ }
392711
392692
  function ownCopy(text, path, officialId, id3) {
392712
392693
  const from2 = ["src", ...path.split("/").slice(0, -1)];
392713
392694
  const kitPath = (rel) => {
@@ -392752,6 +392733,7 @@ async function runTemplate(argv, flags, ctx2) {
392752
392733
  if (!file2) throw usage("popcraft template new <file.ts> [--from <official id>]");
392753
392734
  if (existsSync11(file2)) throw usage(`${file2} exists`);
392754
392735
  const id3 = basename2(file2).replace(/\.(ts|js|mjs)$/, "");
392736
+ if (!/^[a-z0-9][a-z0-9-]{2,63}$/.test(id3)) throw usage(`The file name is the template's id: 3\u201364 lowercase letters, digits and dashes (${JSON.stringify(id3)} is not one). Try templates/spring-sale.ts`);
392755
392737
  const from2 = flagString(flags, "from");
392756
392738
  mkdirSync7(dirname3(resolve4(file2)), { recursive: true });
392757
392739
  writeFileSync8(file2, from2 ? copyOfficial((await projectKit(dirname3(resolve4(file2)))).root, from2, id3) : BLANK(id3));
@@ -392760,14 +392742,16 @@ async function runTemplate(argv, flags, ctx2) {
392760
392742
  }
392761
392743
  case "list": {
392762
392744
  const index2 = officialIndex((await projectKit(process.cwd())).root);
392763
- const words = paths.join(" ").toLowerCase().split(/\s+/).filter(Boolean);
392764
- const facet = (k2, v) => (e) => !v || [].concat(e[k2]).includes(v);
392765
- const rows = Object.entries(index2).filter(([, e]) => facet("platforms", flagString(flags, "platform"))(e) && facet("formats", flagString(flags, "format"))(e) && facet("useCases", flagString(flags, "useCase"))(e) && facet("category", flagString(flags, "category"))(e)).filter(([, e]) => (!flagBool(flags, "animated") || !!e.animated) && (!flagString(flags, "kind") || e.kind === flagString(flags, "kind").toUpperCase())).map(([id3, e]) => {
392766
- const hay = [id3, e.name, e.description, ...e.tags, ...e.formats, ...e.platforms, ...e.useCases].join(" ").toLowerCase();
392767
- return { id: id3, e, score: words.reduce((n, w) => n + (hay.includes(w) ? 1 : 0), 0) };
392768
- }).filter((r) => !words.length || r.score > 0).sort((a, b) => b.score - a.score || a.id.localeCompare(b.id)).slice(0, Number(flagString(flags, "limit") ?? 30));
392745
+ const rows = rankOfficial(index2, paths.join(" "), {
392746
+ platform: flagString(flags, "platform"),
392747
+ format: flagString(flags, "format"),
392748
+ useCase: flagString(flags, "useCase"),
392749
+ category: flagString(flags, "category"),
392750
+ kind: flagString(flags, "kind"),
392751
+ animated: flagBool(flags, "animated")
392752
+ }).slice(0, Number(flagString(flags, "limit") ?? 30));
392769
392753
  if (o.json) o.result(`${rows.length} templates`, rows.map((r) => ({ id: r.id, ...r.e })));
392770
- else for (const r of rows) o.line(`${r.id.padEnd(44)} ${r.e.name}${r.e.animated ? " (animated)" : ""}
392754
+ else for (const r of rows) o.line(`${r.id.padEnd(44)} ${r.e.name}${r.e.animated && !/animated/i.test(r.e.name) ? " (animated)" : ""}
392771
392755
  ${"".padEnd(44)} ${r.e.formats.join(", ")} \xB7 ${r.e.platforms.join(", ")}`);
392772
392756
  return 0;
392773
392757
  }
@@ -392791,15 +392775,17 @@ ${"".padEnd(44)} ${r.e.formats.join(", ")} \xB7 ${r.e.platforms.join(", ")}`);
392791
392775
  return 0;
392792
392776
  }
392793
392777
  case "build": {
392794
- await buildAll(sourceFiles(paths), out, ctx2.appUrl, o);
392778
+ const built = await buildAll(sourceFiles(paths), out, ctx2.appUrl, o);
392779
+ if (built.broken) throw new CliError(`${built.broken} source${built.broken === 1 ? "" : "s"} did not build`);
392795
392780
  return 0;
392796
392781
  }
392797
392782
  case "check":
392798
392783
  case "pictures":
392799
392784
  case "publish": {
392800
392785
  const built = await buildAll(sourceFiles(paths), out, ctx2.appUrl, o);
392801
- if (!built.length) throw usage("No template sources found.");
392802
- if (!await checkAll(built, o)) throw new CliError("Fix what the checks say, then run it again.");
392786
+ if (!built.length && !built.broken) throw usage("No template sources found.");
392787
+ const passed = built.length ? await checkAll(built, o) : true;
392788
+ if (built.broken || !passed) throw new CliError(`${built.broken ? `${built.broken} did not build. ` : ""}Fix what it says, then run it again.`);
392803
392789
  if (verb === "check") return 0;
392804
392790
  if (verb === "pictures" || !flagBool(flags, "noPictures")) {
392805
392791
  for (const b of built) await runPictures(b.dir, ctx2.appUrl, o);
@@ -392808,7 +392794,7 @@ ${"".padEnd(44)} ${r.e.formats.join(", ")} \xB7 ${r.e.platforms.join(", ")}`);
392808
392794
  return 0;
392809
392795
  }
392810
392796
  default:
392811
- throw usage("popcraft template new|build|check|pictures|publish \u2014 see `popcraft --help`");
392797
+ throw usage("popcraft template list|new|build|check|look|pictures|publish \u2014 see `popcraft --help`");
392812
392798
  }
392813
392799
  }
392814
392800
  var BLANK, officialIndex;
@@ -393178,7 +393164,7 @@ init_resources();
393178
393164
  init_desktop();
393179
393165
  init_hypery();
393180
393166
  import { createInterface } from "node:readline";
393181
- var VERSION2 = "0.5.0";
393167
+ var VERSION2 = "0.5.1";
393182
393168
  var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
393183
393169
 
393184
393170
  Files (headless, on .popcraft files):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popcraft/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
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.5.0"
37
+ "@popcraft/kit": "0.5.1"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "node build.mjs",