@stackable-labs/cli-app-extension 1.86.1 → 1.87.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.
Files changed (2) hide show
  1. package/dist/index.js +99 -28
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -567,18 +567,30 @@ var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
567
567
  };
568
568
 
569
569
  // src/lib/manifest-diff.ts
570
- var diffManifestValues = (localValues, registryValues) => {
571
- const localSet = new Set(localValues ?? []);
572
- const registrySet = new Set(registryValues);
573
- const all = /* @__PURE__ */ new Set([...localSet, ...registrySet]);
574
- return [...all].map((value) => {
575
- const inLocal = localSet.has(value);
576
- const inRegistry = registrySet.has(value);
577
- if (!inLocal) {
578
- return { value, status: "removed", enabled: false };
579
- }
580
- return inRegistry ? { value, status: "unchanged", enabled: true } : { value, status: "new", enabled: false };
581
- });
570
+ var diffItems = (previous, next, getKey) => {
571
+ const prevMap = new Map(previous.map((item) => [getKey(item), item]));
572
+ const nextMap = new Map(next.map((item) => [getKey(item), item]));
573
+ const allKeys = /* @__PURE__ */ new Set([...prevMap.keys(), ...nextMap.keys()]);
574
+ const items = [];
575
+ for (const key of allKeys) {
576
+ const before = prevMap.get(key);
577
+ const after = nextMap.get(key);
578
+ if (before && after) {
579
+ const changed = JSON.stringify(before) !== JSON.stringify(after);
580
+ items.push({
581
+ key,
582
+ status: changed ? "changed" : "unchanged",
583
+ enabled: true,
584
+ before,
585
+ after
586
+ });
587
+ } else if (after) {
588
+ items.push({ key, status: "new", enabled: false, after });
589
+ } else {
590
+ items.push({ key, status: "removed", enabled: false, before });
591
+ }
592
+ }
593
+ return items;
582
594
  };
583
595
  var statusLabel = (status) => {
584
596
  switch (status) {
@@ -586,6 +598,8 @@ var statusLabel = (status) => {
586
598
  return "(+ added)";
587
599
  case "removed":
588
600
  return "(- removed)";
601
+ case "changed":
602
+ return "(~ changed)";
589
603
  case "unchanged":
590
604
  return void 0;
591
605
  }
@@ -596,6 +610,8 @@ var statusColor = (status) => {
596
610
  return "green";
597
611
  case "removed":
598
612
  return "red";
613
+ case "changed":
614
+ return "yellow";
599
615
  case "unchanged":
600
616
  return void 0;
601
617
  }
@@ -606,27 +622,35 @@ var ManifestReviewPrompt = ({
606
622
  onSubmit,
607
623
  onBack
608
624
  }) => {
609
- const [permItems, setPermItems] = useState(() => diffManifestValues(localManifest?.permissions, registryManifest.permissions));
610
- const [domainItems, setDomainItems] = useState(() => diffManifestValues(localManifest?.allowedDomains, registryManifest.allowedDomains));
625
+ const [permItems, setPermItems] = useState(() => diffItems(registryManifest.permissions, localManifest?.permissions ?? [], (v) => v));
626
+ const [domainItems, setDomainItems] = useState(() => diffItems(registryManifest.allowedDomains, localManifest?.allowedDomains ?? [], (v) => v));
627
+ const [schemaItems, setSchemaItems] = useState(() => diffItems(registryManifest.settingsSchema ?? [], localManifest?.settingsSchema ?? [], (f) => f.identifier));
611
628
  const [cursor, setCursor] = useState(0);
612
- const totalItems = permItems.length + domainItems.length;
613
- const cursorInPerms = cursor < permItems.length;
614
- const cursorInDomains = cursor >= permItems.length;
629
+ const domainSectionStart = permItems.length;
630
+ const schemaSectionStart = domainSectionStart + domainItems.length;
631
+ const totalItems = permItems.length + domainItems.length + schemaItems.length;
632
+ const cursorInPerms = cursor < domainSectionStart;
633
+ const cursorInDomains = cursor >= domainSectionStart && cursor < schemaSectionStart;
634
+ const cursorInSchema = cursor >= schemaSectionStart;
615
635
  const toggle = (index) => {
616
- if (index < permItems.length) {
636
+ if (index < domainSectionStart) {
617
637
  setPermItems((prev) => prev.map((item, i) => i === index ? { ...item, enabled: !item.enabled } : item));
618
- } else {
619
- const domainIndex = index - permItems.length;
638
+ } else if (index < schemaSectionStart) {
639
+ const domainIndex = index - domainSectionStart;
620
640
  setDomainItems((prev) => prev.map((item, i) => i === domainIndex ? { ...item, enabled: !item.enabled } : item));
641
+ } else {
642
+ const schemaIndex = index - schemaSectionStart;
643
+ setSchemaItems((prev) => prev.map((item, i) => i === schemaIndex ? { ...item, enabled: !item.enabled } : item));
621
644
  }
622
645
  };
623
646
  const handleSubmit = () => {
647
+ const enabledSchema = schemaItems.filter((i) => i.enabled);
624
648
  onSubmit({
625
- permissions: permItems.filter((i) => i.enabled).map((i) => i.value),
626
- allowedDomains: domainItems.filter((i) => i.enabled).map((i) => i.value)
649
+ permissions: permItems.filter((i) => i.enabled).map((i) => i.key),
650
+ allowedDomains: domainItems.filter((i) => i.enabled).map((i) => i.key),
651
+ settingsSchema: enabledSchema.map((i) => i.after ?? i.before)
627
652
  });
628
653
  };
629
- const domainSectionStart = permItems.length;
630
654
  useInput((input, key) => {
631
655
  if (key.downArrow) {
632
656
  setCursor((c) => Math.min(c + 1, totalItems - 1));
@@ -641,12 +665,18 @@ var ManifestReviewPrompt = ({
641
665
  if (c < domainSectionStart && domainItems.length > 0) {
642
666
  return domainSectionStart;
643
667
  }
668
+ if (c < schemaSectionStart && schemaItems.length > 0) {
669
+ return schemaSectionStart;
670
+ }
644
671
  return c;
645
672
  });
646
673
  return;
647
674
  }
648
675
  if (key.tab && key.shift) {
649
676
  setCursor((c) => {
677
+ if (c >= schemaSectionStart && domainItems.length > 0) {
678
+ return domainSectionStart;
679
+ }
650
680
  if (c >= domainSectionStart) {
651
681
  return 0;
652
682
  }
@@ -667,9 +697,40 @@ var ManifestReviewPrompt = ({
667
697
  return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
668
698
  /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
669
699
  /* @__PURE__ */ jsx(Text, { color: item.enabled ? "green" : "gray", children: item.enabled ? "\u25C9" : "\u25CB" }),
670
- /* @__PURE__ */ jsx(Text, { bold: isCursor, children: item.value }),
700
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: item.key }),
671
701
  statusLabel(item.status) && /* @__PURE__ */ jsx(Text, { color: statusColor(item.status), dimColor: true, children: statusLabel(item.status) })
672
- ] }, item.value);
702
+ ] }, item.key);
703
+ };
704
+ const renderSchemaItem = (item, index) => {
705
+ const globalIndex = schemaSectionStart + index;
706
+ const isCursor = globalIndex === cursor;
707
+ const field = item.after ?? item.before;
708
+ const detail = field ? `${field.type}${field.secret ? ", secret" : ""}` : "";
709
+ let changeDetail;
710
+ if (item.status === "changed" && item.before && item.after) {
711
+ const parts = [];
712
+ if (item.before.type !== item.after.type) {
713
+ parts.push(`type ${item.before.type} \u2192 ${item.after.type}`);
714
+ }
715
+ if (item.before.secret !== item.after.secret) {
716
+ parts.push(`secret ${!!item.before.secret} \u2192 ${!!item.after.secret}`);
717
+ }
718
+ if (item.before.label !== item.after.label) {
719
+ parts.push(`label "${item.before.label}" \u2192 "${item.after.label}"`);
720
+ }
721
+ if (JSON.stringify(item.before.options) !== JSON.stringify(item.after.options)) {
722
+ parts.push("options changed");
723
+ }
724
+ changeDetail = parts.length > 0 ? parts.join(", ") : "properties changed";
725
+ }
726
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
727
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
728
+ /* @__PURE__ */ jsx(Text, { color: item.enabled ? "green" : "gray", children: item.enabled ? "\u25C9" : "\u25CB" }),
729
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: item.key }),
730
+ detail && /* @__PURE__ */ jsx(Text, { dimColor: true, children: `(${detail})` }),
731
+ statusLabel(item.status) && /* @__PURE__ */ jsx(Text, { color: statusColor(item.status), dimColor: true, children: statusLabel(item.status) }),
732
+ changeDetail && /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: changeDetail })
733
+ ] }, item.key);
673
734
  };
674
735
  return /* @__PURE__ */ jsx(
675
736
  StepShell,
@@ -689,9 +750,16 @@ var ManifestReviewPrompt = ({
689
750
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
690
751
  /* @__PURE__ */ jsx(Text, { dimColor: !cursorInDomains, bold: cursorInDomains, children: "Allowed Domains".padEnd(14) }),
691
752
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [
692
- domainItems.length > 0 ? domainItems.map((item, i) => renderItem(item, i + permItems.length)) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (none)" }),
753
+ domainItems.length > 0 ? domainItems.map((item, i) => renderItem(item, i + domainSectionStart)) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (none)" }),
693
754
  cursorInDomains && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (space to toggle)" })
694
755
  ] })
756
+ ] }),
757
+ schemaItems.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
758
+ /* @__PURE__ */ jsx(Text, { dimColor: !cursorInSchema, bold: cursorInSchema, children: "Settings Schema".padEnd(14) }),
759
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [
760
+ schemaItems.map((item, i) => renderSchemaItem(item, i)),
761
+ cursorInSchema && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (space to toggle)" })
762
+ ] })
695
763
  ] })
696
764
  ] })
697
765
  }
@@ -2078,6 +2146,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2078
2146
  const [localManifest, setLocalManifest] = useState(null);
2079
2147
  const [confirmedPermissions, setConfirmedPermissions] = useState([]);
2080
2148
  const [confirmedAllowedDomains, setConfirmedAllowedDomains] = useState([]);
2149
+ const [confirmedSettingsSchema, setConfirmedSettingsSchema] = useState([]);
2081
2150
  const [userEditedAllowedDomains, setUserEditedAllowedDomains] = useState([]);
2082
2151
  const [outputDir, setOutputDir] = useState("");
2083
2152
  const [studioProject, setStudioProject] = useState(null);
@@ -2315,7 +2384,8 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2315
2384
  version: resolvedVersion,
2316
2385
  targets,
2317
2386
  permissions: confirmedPermissions,
2318
- allowedDomains: confirmedAllowedDomains
2387
+ allowedDomains: confirmedAllowedDomains,
2388
+ ...confirmedSettingsSchema.length > 0 && { settingsSchema: confirmedSettingsSchema }
2319
2389
  },
2320
2390
  bundleUrl: bundleUrl || void 0,
2321
2391
  enabled
@@ -2565,6 +2635,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2565
2635
  onSubmit: (result) => {
2566
2636
  setConfirmedPermissions(result.permissions);
2567
2637
  setConfirmedAllowedDomains(result.allowedDomains);
2638
+ setConfirmedSettingsSchema(result.settingsSchema);
2568
2639
  goForward();
2569
2640
  },
2570
2641
  onBack: goBack
@@ -3121,7 +3192,7 @@ var isValidManifest = (data) => {
3121
3192
  return false;
3122
3193
  }
3123
3194
  const m = data;
3124
- return typeof m.name === "string" && m.name.length > 0 && typeof m.version === "string" && Array.isArray(m.targets) && Array.isArray(m.permissions) && Array.isArray(m.allowedDomains);
3195
+ return typeof m.name === "string" && m.name.length > 0 && typeof m.version === "string" && Array.isArray(m.targets) && Array.isArray(m.permissions) && Array.isArray(m.allowedDomains) && (m.settingsSchema === void 0 || Array.isArray(m.settingsSchema));
3125
3196
  };
3126
3197
  var isExtensionProject = (dir) => {
3127
3198
  const manifestPath = join(dir, "packages/extension/public/manifest.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackable-labs/cli-app-extension",
3
- "version": "1.86.1",
3
+ "version": "1.87.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "bin": {