@algolia/wizard 0.38.0-rc.131.269 → 0.38.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/main.js +193 -263
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -258,14 +258,10 @@ var useWizard = create((set, get) => ({
258
258
  error: null,
259
259
  inputReq: null,
260
260
  _resolve: null,
261
- settingUpAppId: null,
262
- setSettingUpApp: (appId) => set({ settingUpAppId: appId }),
263
261
  // `endAuth` lands on 'preflight', not 'idle': sign-in happens after the
264
262
  // welcome screen, so going back would gate the run a second time.
265
263
  beginAuth: () => set({ phase: "authenticating", cliOutput: [] }),
266
- endAuth: () => set(
267
- (s) => s.phase === "authenticating" ? { phase: "preflight", cliOutput: [] } : {}
268
- ),
264
+ endAuth: () => set((s) => s.phase === "authenticating" ? { phase: "preflight" } : {}),
269
265
  confirmStart: () => set(
270
266
  (s) => s.phase === "idle" ? { phase: "preflight", homeScreen: "home" } : {}
271
267
  ),
@@ -409,8 +405,7 @@ var useWizard = create((set, get) => ({
409
405
  logs: [],
410
406
  error: null,
411
407
  inputReq: null,
412
- _resolve: null,
413
- settingUpAppId: null
408
+ _resolve: null
414
409
  });
415
410
  }
416
411
  }));
@@ -658,27 +653,25 @@ function SelectRow({
658
653
  labelWidth,
659
654
  highlightBackground = true,
660
655
  usePadding = false,
661
- disabled = false,
662
656
  children
663
657
  }) {
664
- const active = highlighted && !disabled;
665
- const labelColor = disabled ? COLORS.dim : active ? highlightBackground ? COLORS.highlight.fg : COLORS.success : COLORS.primary;
658
+ const labelColor = highlighted ? highlightBackground ? COLORS.highlight.fg : COLORS.success : COLORS.primary;
666
659
  return /* @__PURE__ */ jsxs3(
667
660
  Box4,
668
661
  {
669
662
  width,
670
663
  paddingX: usePadding ? 1 : 0,
671
664
  paddingY: usePadding ? 1 : 0,
672
- backgroundColor: active && highlightBackground ? COLORS.highlight.bg : void 0,
665
+ backgroundColor: highlighted && highlightBackground ? COLORS.highlight.bg : void 0,
673
666
  children: [
674
667
  /* @__PURE__ */ jsx3(Box4, { width: labelWidth, children: /* @__PURE__ */ jsxs3(
675
668
  Text4,
676
669
  {
677
670
  color: labelColor,
678
- bold: active && !highlightBackground,
671
+ bold: highlighted && !highlightBackground,
679
672
  wrap: "truncate",
680
673
  children: [
681
- active ? "\u276F " : " ",
674
+ highlighted ? "\u276F " : " ",
682
675
  label
683
676
  ]
684
677
  }
@@ -877,14 +870,6 @@ var ARROW_WIDTH = 4;
877
870
  var COLUMN_GAP = 2;
878
871
  var BAR_PADDING = 2;
879
872
  var ROW_HEIGHT = 3;
880
- function nextSelectableIndex(start, dir, rowCount, isDisabled) {
881
- let i = start;
882
- for (let step = 0; step < rowCount; step++) {
883
- i = (i + dir + rowCount) % rowCount;
884
- if (!isDisabled(i)) return i;
885
- }
886
- return start;
887
- }
888
873
  function SelectPrompt({
889
874
  options,
890
875
  onSelect,
@@ -896,18 +881,15 @@ function SelectPrompt({
896
881
  multi,
897
882
  cancelable,
898
883
  secondary,
899
- disabled,
900
884
  defaultSelectedIndex = 0
901
885
  }) {
886
+ const [index, setIndex] = useState5(
887
+ () => defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0
888
+ );
889
+ const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
902
890
  const hasCancel = Boolean(multi || cancelable);
903
891
  const rows = hasCancel ? [...options, "Cancel"] : options;
904
892
  const cancelIndex = hasCancel ? options.length : -1;
905
- const isDisabled = (i) => i !== cancelIndex && Boolean(disabled?.[i]);
906
- const [index, setIndex] = useState5(() => {
907
- const start = defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0;
908
- return isDisabled(start) ? nextSelectableIndex(start, 1, rows.length, isDisabled) : start;
909
- });
910
- const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
911
893
  const hints = [];
912
894
  if (rows.length > 1) hints.push({ key: "[\u2191] [\u2193]", label: "move" });
913
895
  if (multi) hints.push({ key: "[space]", label: "select" });
@@ -947,15 +929,9 @@ function SelectPrompt({
947
929
  useInput2((input, key) => {
948
930
  if (rows.length === 0) return;
949
931
  if (key.upArrow || input === "k") {
950
- setIndex((i) => {
951
- const next = (i - 1 + rows.length) % rows.length;
952
- return isDisabled(next) ? i : next;
953
- });
932
+ setIndex((i) => (i - 1 + rows.length) % rows.length);
954
933
  } else if (key.downArrow || input === "j") {
955
- setIndex((i) => {
956
- const next = (i + 1) % rows.length;
957
- return isDisabled(next) ? i : next;
958
- });
934
+ setIndex((i) => (i + 1) % rows.length);
959
935
  } else if (multi && input === " " && index !== cancelIndex) {
960
936
  setChecked((prev) => {
961
937
  const next = new Set(prev);
@@ -966,7 +942,6 @@ function SelectPrompt({
966
942
  } else if (key.return) {
967
943
  if (index === cancelIndex) {
968
944
  onSelect(CANCEL);
969
- } else if (isDisabled(index)) {
970
945
  } else if (!multi) {
971
946
  onSelect(options[index]);
972
947
  } else if (checked.size > 0) {
@@ -991,12 +966,10 @@ function SelectPrompt({
991
966
  const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
992
967
  const sec = isCancel ? void 0 : secondary?.[i];
993
968
  const isText = sec?.kind === "text";
994
- const rowDisabled = isDisabled(i);
995
969
  return /* @__PURE__ */ jsxs7(
996
970
  SelectRow,
997
971
  {
998
972
  highlighted,
999
- disabled: rowDisabled,
1000
973
  width: isText ? "100%" : barWidth,
1001
974
  labelWidth: isText ? labelWidth : barLabelWidth,
1002
975
  label: `${bullet}${option}`,
@@ -1006,7 +979,7 @@ function SelectPrompt({
1006
979
  Text8,
1007
980
  {
1008
981
  wrap: "truncate",
1009
- color: rowDisabled ? COLORS.dim : highlighted ? COLORS.primary : COLORS.muted,
982
+ color: highlighted ? COLORS.primary : COLORS.muted,
1010
983
  children: sec.value
1011
984
  }
1012
985
  ) }),
@@ -1068,7 +1041,6 @@ function PromptInput() {
1068
1041
  table: inputReq.table,
1069
1042
  options: inputReq.options,
1070
1043
  secondary: inputReq.secondary,
1071
- disabled: inputReq.disabled,
1072
1044
  defaultSelectedIndex: inputReq.defaultSelectedIndex,
1073
1045
  cancelable: inputReq.cancelable,
1074
1046
  error: inputReq.error,
@@ -1140,7 +1112,7 @@ function PromptInput() {
1140
1112
  inputReq.prompt,
1141
1113
  " "
1142
1114
  ] }),
1143
- /* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: /* @__PURE__ */ jsx7(
1115
+ /* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, children: /* @__PURE__ */ jsx7(
1144
1116
  TextInput,
1145
1117
  {
1146
1118
  value: draft,
@@ -1432,10 +1404,6 @@ function reconcileWorkflowState(state, workflow) {
1432
1404
  }
1433
1405
  return state;
1434
1406
  }
1435
- async function loadResumableState(workflow) {
1436
- const persisted = await loadWorkflowState(workflow.id);
1437
- return persisted ? reconcileWorkflowState(persisted, workflow) : null;
1438
- }
1439
1407
  function initWorkflowState(workflow, now) {
1440
1408
  return {
1441
1409
  workflowId: workflow.id,
@@ -1538,11 +1506,11 @@ async function runStep(state, index, step, appId) {
1538
1506
  durationMs: Date.now() - startedAt
1539
1507
  });
1540
1508
  }
1541
- async function runWorkflow(workflow, appId, resumableState) {
1509
+ async function runWorkflow(workflow, appId) {
1542
1510
  const store = useWizard.getState();
1543
1511
  try {
1544
- const resolved2 = resumableState !== void 0 ? resumableState : await loadResumableState(workflow);
1545
- const state = resolved2 ?? initWorkflowState(workflow, nowIso());
1512
+ const persisted = await loadWorkflowState(workflow.id);
1513
+ const state = (persisted && reconcileWorkflowState(persisted, workflow)) ?? initWorkflowState(workflow, nowIso());
1546
1514
  ensureExecutedStepCount(state);
1547
1515
  store.startWorkflow(
1548
1516
  {
@@ -1632,89 +1600,14 @@ async function listIndices() {
1632
1600
  return items.map((i) => ({ name: i.name, entries: i.entries })).sort((a, b) => a.name.localeCompare(b.name));
1633
1601
  }
1634
1602
 
1635
- // src/lib/algoliaApp.ts
1636
- import { z as z5 } from "zod";
1637
- var applicationSchema = z5.object({
1638
- id: z5.string().min(1),
1639
- name: z5.string().default(""),
1640
- plan: z5.string().optional()
1641
- });
1642
- var listSchema = z5.array(
1643
- z5.object({
1644
- id: z5.string().min(1),
1645
- name: z5.string().default(""),
1646
- plan_label: z5.string().optional(),
1647
- status: z5.string().optional(),
1648
- acl: z5.array(z5.string()).optional()
1649
- }).transform(({ id, name, plan_label, status, acl }) => ({
1650
- id,
1651
- name,
1652
- plan: plan_label,
1653
- status,
1654
- acl
1655
- }))
1656
- );
1657
- function canSelectApplication(app) {
1658
- return app.status === "active" && (app.acl ?? []).includes("keys");
1659
- }
1660
- async function currentApplication() {
1661
- let raw;
1662
- try {
1663
- raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
1664
- } catch {
1665
- return null;
1666
- }
1667
- const parsed = applicationSchema.safeParse(parseJson(raw));
1668
- return parsed.success ? parsed.data : null;
1669
- }
1670
- async function requireApplication() {
1671
- const app = await currentApplication();
1672
- if (!app) {
1673
- throw new Error(
1674
- "No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
1675
- );
1676
- }
1677
- return app;
1678
- }
1679
- async function listApplications() {
1680
- const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
1681
- const parsed = listSchema.safeParse(parseJson(raw));
1682
- if (!parsed.success) {
1683
- throw new Error("Could not read the list of Algolia applications.");
1684
- }
1685
- return parsed.data;
1686
- }
1687
- async function selectApplication(id) {
1688
- const raw = await runAlgoliaCli(
1689
- ["application", "select", "--non-interactive", "--app-id", id],
1690
- { onOutput: stderrSink }
1691
- );
1692
- const parsed = applicationSchema.safeParse(parseJson(raw));
1693
- if (!parsed.success) {
1694
- throw new Error(
1695
- `Selected application ${id}, but the Algolia CLI returned an unreadable result.`
1696
- );
1697
- }
1698
- return parsed.data;
1699
- }
1700
- function parseJson(text) {
1701
- try {
1702
- return JSON.parse(text);
1703
- } catch {
1704
- return void 0;
1705
- }
1706
- }
1707
-
1708
1603
  // src/actions/selectIndex.ts
1709
1604
  var CREATE_NEW_INDEX = "Create a new index\u2026";
1710
1605
  var selectIndexStep = async (ctx) => {
1711
- await requireApplication();
1712
1606
  const indices = await listIndices();
1713
1607
  const names = indices.map((i) => i.name);
1714
1608
  const hasIndices = names.length > 0;
1715
1609
  let error;
1716
- let chosen;
1717
- while (chosen === void 0) {
1610
+ for (; ; ) {
1718
1611
  const selection = hasIndices ? await ctx.requestUserInput({
1719
1612
  prompt: "Which index do you want to ingest into?",
1720
1613
  promptType: "multipleChoice",
@@ -1733,9 +1626,9 @@ var selectIndexStep = async (ctx) => {
1733
1626
  if (typeof selection !== "string") {
1734
1627
  throw new Error("selectIndex received an unexpected non-text result");
1735
1628
  }
1736
- let candidate;
1629
+ let chosen;
1737
1630
  if (!hasIndices) {
1738
- candidate = selection.trim();
1631
+ chosen = selection.trim();
1739
1632
  } else if (selection === CREATE_NEW_INDEX) {
1740
1633
  const name = await ctx.requestUserInput({
1741
1634
  prompt: "Name the new index:",
@@ -1745,18 +1638,17 @@ var selectIndexStep = async (ctx) => {
1745
1638
  if (typeof name !== "string") {
1746
1639
  throw new Error("selectIndex received an unexpected non-text result");
1747
1640
  }
1748
- candidate = name.trim();
1641
+ chosen = name.trim();
1749
1642
  } else {
1750
- candidate = selection;
1643
+ chosen = selection;
1751
1644
  }
1752
- if (!candidate) {
1645
+ if (!chosen) {
1753
1646
  error = "Index name cannot be empty.";
1754
1647
  continue;
1755
1648
  }
1756
- chosen = candidate;
1649
+ ctx.setUserInput("index", chosen);
1650
+ return { selection: chosen };
1757
1651
  }
1758
- ctx.setUserInput("index", chosen);
1759
- return { selection: chosen };
1760
1652
  };
1761
1653
 
1762
1654
  // src/lib/agent.ts
@@ -1769,7 +1661,7 @@ import "zod";
1769
1661
 
1770
1662
  // src/lib/tools/listFiles.ts
1771
1663
  import { tool } from "ai";
1772
- import z6 from "zod";
1664
+ import z5 from "zod";
1773
1665
  import { readdir } from "node:fs/promises";
1774
1666
 
1775
1667
  // src/lib/tools/path.ts
@@ -1805,8 +1697,8 @@ async function hasSymlinkParent(ctx, target) {
1805
1697
  function listFilesTool(ctx) {
1806
1698
  return tool({
1807
1699
  description: 'List files in a directory (default: the current working directory). Pass path to list a subdirectory directly \u2014 e.g. "packages/api" \u2014 without first changeDirectory-ing into it.',
1808
- inputSchema: z6.object({
1809
- path: z6.string().optional().describe("Directory to list, relative to cwd (default: cwd)")
1700
+ inputSchema: z5.object({
1701
+ path: z5.string().optional().describe("Directory to list, relative to cwd (default: cwd)")
1810
1702
  }),
1811
1703
  execute: async ({ path = "." }) => {
1812
1704
  logger.info({ path }, "called listFiles tool");
@@ -1827,13 +1719,13 @@ function listFilesTool(ctx) {
1827
1719
 
1828
1720
  // src/lib/tools/changeDirectory.ts
1829
1721
  import { tool as tool2 } from "ai";
1830
- import z7 from "zod";
1722
+ import z6 from "zod";
1831
1723
  import { stat } from "node:fs/promises";
1832
1724
  function changeDirectoryTool(ctx) {
1833
1725
  return tool2({
1834
1726
  description: "Change the current working directory. Subsequent file operations resolve relative to it. Returns the new working directory.",
1835
- inputSchema: z7.object({
1836
- path: z7.string().describe("Directory to change into")
1727
+ inputSchema: z6.object({
1728
+ path: z6.string().describe("Directory to change into")
1837
1729
  }),
1838
1730
  execute: async ({ path }) => {
1839
1731
  logger.info({ path }, "called changeDirectory tool");
@@ -1855,13 +1747,13 @@ function changeDirectoryTool(ctx) {
1855
1747
 
1856
1748
  // src/lib/tools/reportStatus.ts
1857
1749
  import { tool as tool3 } from "ai";
1858
- import z8 from "zod";
1750
+ import z7 from "zod";
1859
1751
  function reportStatusTool(output) {
1860
1752
  return tool3({
1861
1753
  description: "Report the status of your execution. Return a reason in case of failure.",
1862
- inputSchema: z8.object({
1863
- status: z8.enum(["success", "fail"]),
1864
- reason: z8.string().optional(),
1754
+ inputSchema: z7.object({
1755
+ status: z7.enum(["success", "fail"]),
1756
+ reason: z7.string().optional(),
1865
1757
  output
1866
1758
  }),
1867
1759
  execute: async ({ status, reason, output: output2 }) => {
@@ -1873,7 +1765,7 @@ function reportStatusTool(output) {
1873
1765
 
1874
1766
  // src/lib/tools/readFile.ts
1875
1767
  import { tool as tool4 } from "ai";
1876
- import z9 from "zod";
1768
+ import z8 from "zod";
1877
1769
  import { readFile as readFile3 } from "node:fs/promises";
1878
1770
 
1879
1771
  // src/lib/tools/env.ts
@@ -1901,8 +1793,8 @@ function redactEnvValues(content) {
1901
1793
  function readFileTool(ctx) {
1902
1794
  return tool4({
1903
1795
  description: "Read the contents of a file at the given path",
1904
- inputSchema: z9.object({
1905
- filePath: z9.string().describe("Path to the file to read")
1796
+ inputSchema: z8.object({
1797
+ filePath: z8.string().describe("Path to the file to read")
1906
1798
  }),
1907
1799
  execute: async ({ filePath }) => {
1908
1800
  if (++ctx.counts.read > ctx.limits.read) {
@@ -1923,15 +1815,15 @@ function readFileTool(ctx) {
1923
1815
 
1924
1816
  // src/lib/tools/writeFile.ts
1925
1817
  import { tool as tool5 } from "ai";
1926
- import z10 from "zod";
1818
+ import z9 from "zod";
1927
1819
  import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
1928
1820
  import { dirname as dirname3 } from "node:path";
1929
1821
  function writeFileTool(ctx) {
1930
1822
  return tool5({
1931
1823
  description: "Write content to a file at the given path, overwriting it. Writes to secret env files (.env, .env.local, etc.) are refused by this tool \u2014 call it anyway and the tool will tell you how to proceed.",
1932
- inputSchema: z10.object({
1933
- filePath: z10.string().describe("Path to the file to write"),
1934
- content: z10.string().describe("Content to write to the file")
1824
+ inputSchema: z9.object({
1825
+ filePath: z9.string().describe("Path to the file to write"),
1826
+ content: z9.string().describe("Content to write to the file")
1935
1827
  }),
1936
1828
  execute: async ({ filePath, content }) => {
1937
1829
  logger.info({ filePath }, "called writeFile tool");
@@ -1961,6 +1853,68 @@ import z13 from "zod";
1961
1853
  import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
1962
1854
  import { dirname as dirname4, relative as relative3 } from "node:path";
1963
1855
 
1856
+ // src/lib/algoliaApp.ts
1857
+ import { z as z10 } from "zod";
1858
+ var applicationSchema = z10.object({
1859
+ id: z10.string().min(1),
1860
+ name: z10.string().default(""),
1861
+ plan: z10.string().optional()
1862
+ });
1863
+ var listSchema = z10.array(
1864
+ z10.object({
1865
+ id: z10.string().min(1),
1866
+ name: z10.string().default(""),
1867
+ plan_label: z10.string().optional()
1868
+ }).transform(({ id, name, plan_label }) => ({ id, name, plan: plan_label }))
1869
+ );
1870
+ async function currentApplication() {
1871
+ let raw;
1872
+ try {
1873
+ raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
1874
+ } catch {
1875
+ return null;
1876
+ }
1877
+ const parsed = applicationSchema.safeParse(parseJson(raw));
1878
+ return parsed.success ? parsed.data : null;
1879
+ }
1880
+ async function requireApplication() {
1881
+ const app = await currentApplication();
1882
+ if (!app) {
1883
+ throw new Error(
1884
+ "No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
1885
+ );
1886
+ }
1887
+ return app;
1888
+ }
1889
+ async function listApplications() {
1890
+ const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
1891
+ const parsed = listSchema.safeParse(parseJson(raw));
1892
+ if (!parsed.success) {
1893
+ throw new Error("Could not read the list of Algolia applications.");
1894
+ }
1895
+ return parsed.data;
1896
+ }
1897
+ async function selectApplication(id) {
1898
+ const raw = await runAlgoliaCli(
1899
+ ["application", "select", "--non-interactive", "--app-id", id],
1900
+ { onOutput: stderrSink }
1901
+ );
1902
+ const parsed = applicationSchema.safeParse(parseJson(raw));
1903
+ if (!parsed.success) {
1904
+ throw new Error(
1905
+ `Selected application ${id}, but the Algolia CLI returned an unreadable result.`
1906
+ );
1907
+ }
1908
+ return parsed.data;
1909
+ }
1910
+ function parseJson(text) {
1911
+ try {
1912
+ return JSON.parse(text);
1913
+ } catch {
1914
+ return void 0;
1915
+ }
1916
+ }
1917
+
1964
1918
  // src/lib/algoliaApiKey.ts
1965
1919
  import { z as z12 } from "zod";
1966
1920
 
@@ -1968,13 +1922,13 @@ import { z as z12 } from "zod";
1968
1922
  import { deletePassword, getPassword, setPassword } from "cross-keychain";
1969
1923
  import { z as z11 } from "zod";
1970
1924
  var SERVICE = "algolia-wizard";
1971
- var account = (userId) => `api-keys:${userId}`;
1925
+ var ACCOUNT = "api-keys";
1972
1926
  var storedKeysSchema = z11.record(z11.string(), z11.string());
1973
1927
  function entryId(kind, index, appId) {
1974
1928
  return `${kind}:${appId}:${index}`;
1975
1929
  }
1976
- async function loadKeys(userId) {
1977
- const raw = await getPassword(SERVICE, account(userId));
1930
+ async function loadKeys() {
1931
+ const raw = await getPassword(SERVICE, ACCOUNT);
1978
1932
  if (!raw) return {};
1979
1933
  let payload;
1980
1934
  try {
@@ -1996,47 +1950,47 @@ function serialized(op) {
1996
1950
  });
1997
1951
  return next;
1998
1952
  }
1999
- async function readStoredKey(kind, userId, index, appId) {
1953
+ async function readStoredKey(kind, index, appId) {
2000
1954
  try {
2001
- return (await loadKeys(userId))[entryId(kind, index, appId)] ?? null;
1955
+ return (await loadKeys())[entryId(kind, index, appId)] ?? null;
2002
1956
  } catch (err) {
2003
1957
  logger.warn(
2004
- { err: err.message, kind, index, appId, userId },
1958
+ { err: err.message, kind, index, appId },
2005
1959
  "could not read the API key from the keychain"
2006
1960
  );
2007
1961
  return null;
2008
1962
  }
2009
1963
  }
2010
- function storeKey(kind, userId, index, appId, value) {
1964
+ function storeKey(kind, index, appId, value) {
2011
1965
  return serialized(async () => {
2012
1966
  const id = entryId(kind, index, appId);
2013
1967
  try {
2014
- const keys = await loadKeys(userId);
1968
+ const keys = await loadKeys();
2015
1969
  await setPassword(
2016
1970
  SERVICE,
2017
- account(userId),
1971
+ ACCOUNT,
2018
1972
  JSON.stringify({ ...keys, [id]: value })
2019
1973
  );
2020
- if ((await loadKeys(userId))[id] !== value) {
1974
+ if ((await loadKeys())[id] !== value) {
2021
1975
  throw new Error("the keychain did not store the value");
2022
1976
  }
2023
1977
  } catch (err) {
2024
1978
  logger.warn(
2025
- { err: err.message, kind, index, appId, userId },
1979
+ { err: err.message, kind, index, appId },
2026
1980
  "could not store the API key in the keychain; the next run will create another"
2027
1981
  );
2028
1982
  }
2029
1983
  });
2030
1984
  }
2031
- function deleteStoredKeys(userId) {
1985
+ function deleteStoredKeys() {
2032
1986
  return serialized(async () => {
2033
1987
  try {
2034
- await deletePassword(SERVICE, account(userId));
1988
+ await deletePassword(SERVICE, ACCOUNT);
2035
1989
  } catch (err) {
2036
1990
  const message = err.message;
2037
1991
  if (/not found/i.test(message)) return;
2038
1992
  logger.warn(
2039
- { err: message, userId },
1993
+ { err: message },
2040
1994
  "could not delete the API keys from the keychain"
2041
1995
  );
2042
1996
  }
@@ -2044,16 +1998,6 @@ function deleteStoredKeys(userId) {
2044
1998
  }
2045
1999
 
2046
2000
  // src/lib/algoliaApiKey.ts
2047
- function requireUserId() {
2048
- const userId = useWizard.getState().user?.userId;
2049
- if (!userId) {
2050
- throw new Error("No Algolia user is signed in; cannot scope the API key.");
2051
- }
2052
- return userId;
2053
- }
2054
- async function currentUserId() {
2055
- return useWizard.getState().user?.userId ?? (await getUser())?.userId ?? null;
2056
- }
2057
2001
  var WRITE_ACLS = [
2058
2002
  "addObject",
2059
2003
  "deleteObject",
@@ -2100,30 +2044,23 @@ async function keyExists(key) {
2100
2044
  var resolved = /* @__PURE__ */ new Map();
2101
2045
  async function forgetResolvedKeys() {
2102
2046
  resolved.clear();
2103
- const userId = await currentUserId();
2104
- if (userId) await deleteStoredKeys(userId);
2047
+ await deleteStoredKeys();
2105
2048
  }
2106
2049
  function resolveKey(kind, index, appId, acls, description) {
2107
- const userId = requireUserId();
2108
- const cacheKey = `${userId}:${kind}:${appId}:${index}`;
2050
+ const cacheKey = `${kind}:${appId}:${index}`;
2109
2051
  const cached = resolved.get(cacheKey);
2110
2052
  if (cached) return cached;
2111
- const pending = provisionKey(
2112
- kind,
2113
- userId,
2114
- index,
2115
- appId,
2116
- acls,
2117
- description
2118
- ).catch((err) => {
2119
- resolved.delete(cacheKey);
2120
- throw err;
2121
- });
2053
+ const pending = provisionKey(kind, index, appId, acls, description).catch(
2054
+ (err) => {
2055
+ resolved.delete(cacheKey);
2056
+ throw err;
2057
+ }
2058
+ );
2122
2059
  resolved.set(cacheKey, pending);
2123
2060
  return pending;
2124
2061
  }
2125
- async function provisionKey(kind, userId, index, appId, acls, description) {
2126
- const stored = await readStoredKey(kind, userId, index, appId);
2062
+ async function provisionKey(kind, index, appId, acls, description) {
2063
+ const stored = await readStoredKey(kind, index, appId);
2127
2064
  if (stored) {
2128
2065
  if (await keyExists(stored)) {
2129
2066
  logger.info({ kind, index, appId }, "reusing the stored API key");
@@ -2135,7 +2072,7 @@ async function provisionKey(kind, userId, index, appId, acls, description) {
2135
2072
  );
2136
2073
  }
2137
2074
  const key = await createKey(index, acls, description);
2138
- await storeKey(kind, userId, index, appId, key);
2075
+ await storeKey(kind, index, appId, key);
2139
2076
  return { key, source: "created" };
2140
2077
  }
2141
2078
  function resolveWriteKey(index, appId) {
@@ -3330,7 +3267,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3330
3267
  // package.json
3331
3268
  var package_default = {
3332
3269
  name: "@algolia/wizard",
3333
- version: "0.38.0-rc.131.269",
3270
+ version: "0.38.0",
3334
3271
  description: "Magically implement Algolia functionality in your codebase",
3335
3272
  type: "module",
3336
3273
  engines: {
@@ -4217,10 +4154,6 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
4217
4154
  if (useCases.includes("ingestion")) {
4218
4155
  ingestAppId = appId ?? (await requireApplication()).id;
4219
4156
  }
4220
- let ingestWriteKey;
4221
- if (useCases.includes("ingestion") && ingestAppId) {
4222
- ingestWriteKey = (await resolveWriteKey(targetIndex, ingestAppId)).key;
4223
- }
4224
4157
  let uploadFilePath;
4225
4158
  let uploadWarning;
4226
4159
  if (ingestionSource === "fileUpload") {
@@ -4283,9 +4216,9 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
4283
4216
  let ingestDurationMs;
4284
4217
  let ingestOutcomeMessage;
4285
4218
  const ingestKeyAppId = ingestAppId;
4286
- const ingestionTools = ingestKeyAppId && ingestWriteKey ? makeToolContext(repoRoot, async () => ({
4219
+ const ingestionTools = ingestKeyAppId ? makeToolContext(repoRoot, async () => ({
4287
4220
  [APP_ID_VAR]: ingestKeyAppId,
4288
- [API_KEY_VAR]: ingestWriteKey,
4221
+ [API_KEY_VAR]: (await resolveWriteKey(targetIndex, ingestKeyAppId)).key,
4289
4222
  [INDEX_NAME_VAR]: targetIndex
4290
4223
  })) : void 0;
4291
4224
  const searchTools = makeToolContext(repoRoot);
@@ -5440,8 +5373,7 @@ function App() {
5440
5373
  steps,
5441
5374
  inputReq,
5442
5375
  user,
5443
- workflow,
5444
- settingUpAppId
5376
+ workflow
5445
5377
  } = useWizard();
5446
5378
  const { exit } = useApp();
5447
5379
  const { columns, rows } = useWindowSize7();
@@ -5456,7 +5388,7 @@ function App() {
5456
5388
  const isCommandApprovalPrompt = isAwaitingUserInput && inputReq?.promptType === "commandApproval";
5457
5389
  const promptPending = isAwaitingUserInput && !isCommandApprovalPrompt;
5458
5390
  const holdForTip = stepHasTips && promptPending && tipState === "revealing";
5459
- const showTips = stepHasTips && (phase === "running" && currentStep?.status === "running" || isCommandApprovalPrompt || holdForTip);
5391
+ const showTips = stepHasTips && (phase === "running" || isCommandApprovalPrompt || holdForTip);
5460
5392
  const showNoticesInMain = !stepHasTips;
5461
5393
  const showNotices = !isAwaitingUserInput || holdForTip;
5462
5394
  useInput6(
@@ -5541,12 +5473,6 @@ function App() {
5541
5473
  ] }),
5542
5474
  /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
5543
5475
  ] }),
5544
- settingUpAppId && /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
5545
- /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
5546
- " Setting up Wizard using app",
5547
- " ",
5548
- settingUpAppId
5549
- ] }) }),
5550
5476
  /* @__PURE__ */ jsx17(CliOutput, {}),
5551
5477
  showTips && currentStep && /* @__PURE__ */ jsx17(
5552
5478
  Tips,
@@ -5616,72 +5542,50 @@ function readValue(raw) {
5616
5542
  }
5617
5543
 
5618
5544
  // src/lib/algoliaAppPicker.ts
5619
- function blockReasonFor(app) {
5620
- return app.status !== "active" ? "Paused" : "Missing permissions";
5621
- }
5622
- function secondaryFor(app, highlightId) {
5623
- if (!canSelectApplication(app)) {
5624
- return { kind: "text", value: blockReasonFor(app) };
5625
- }
5626
- if (app.id === highlightId) {
5627
- return { kind: "badge", value: "[DETECTED]" };
5628
- }
5545
+ function secondaryFor(app) {
5629
5546
  return app.plan ? { kind: "badge", value: app.plan } : void 0;
5630
5547
  }
5631
5548
  function labelFor(app) {
5632
5549
  return app.name.trim() ? `${app.name} \u2014 ${app.id}` : app.id;
5633
5550
  }
5634
- async function isEligible(app) {
5635
- const apps = await listApplications();
5636
- const full = apps.find((candidate) => candidate.id === app.id);
5637
- return full != null && canSelectApplication(full);
5638
- }
5639
- async function selectAndReport(app) {
5640
- const store = useWizard.getState();
5641
- store.setSettingUpApp(app.id);
5642
- try {
5643
- return await selectApplication(app.id);
5644
- } finally {
5645
- store.setSettingUpApp(null);
5646
- }
5551
+ function selectAndReport(app) {
5552
+ useWizard.getState().pushCliOutput(
5553
+ "stdout",
5554
+ `Selecting ${labelFor(app)} \u2014 provisioning its API key\u2026`
5555
+ );
5556
+ return selectApplication(app.id);
5647
5557
  }
5648
- async function promptForApplication(highlight) {
5558
+ async function promptForApplication(leadIn = []) {
5649
5559
  const store = useWizard.getState();
5650
- const unordered = await listApplications();
5651
- if (unordered.length === 0) {
5560
+ const apps = await listApplications();
5561
+ if (apps.length === 0) {
5652
5562
  throw new Error(
5653
5563
  "This Algolia account has no applications. Create one in the Algolia dashboard, or with `npx @algolia/cli@latest application create`, then restart the wizard."
5654
5564
  );
5655
5565
  }
5656
- if (!unordered.some(canSelectApplication)) {
5657
- throw new Error(
5658
- "None of the applications on this Algolia account are usable \u2014 each is either paused or missing key-management access. Activate one, or grant it the `keys` ACL, then restart the wizard."
5566
+ if (apps.length === 1) {
5567
+ const only = apps[0];
5568
+ logger.info(
5569
+ { app: only.id },
5570
+ "single application on the account; selecting it"
5659
5571
  );
5572
+ for (const line of leadIn) store.pushCliOutput("stdout", line);
5573
+ return selectAndReport(only);
5660
5574
  }
5661
- const apps = [
5662
- ...unordered.filter(canSelectApplication),
5663
- ...unordered.filter((app) => !canSelectApplication(app))
5575
+ const messages = [
5576
+ ...leadIn,
5577
+ "Which Algolia application should the wizard work in?"
5664
5578
  ];
5665
- const envApp = highlight ? unordered.find((app) => app.id === highlight.id) : void 0;
5666
- const highlightIndex = envApp && canSelectApplication(envApp) ? apps.indexOf(envApp) : -1;
5667
- const messages = [];
5668
- if (highlight && highlightIndex < 0) {
5669
- messages.push(
5670
- envApp ? `Could not use ${highlight.id} from ${highlight.file} \u2014 it\u2019s ${blockReasonFor(envApp).toLowerCase()}. Pick another below.` : `Could not use ${highlight.id} from ${highlight.file} \u2014 it may have been removed, or this account may not have access to it.`
5671
- );
5672
- }
5673
5579
  for (; ; ) {
5674
5580
  const choice = await store.requestUserInput({
5675
- prompt: "Which Algolia application should the wizard work in?",
5581
+ prompt: "Select an application",
5676
5582
  promptType: "multipleChoice",
5677
5583
  options: apps.map(labelFor),
5678
- secondary: apps.map((app) => secondaryFor(app, highlight?.id)),
5679
- disabled: apps.map((app) => !canSelectApplication(app)),
5680
- ...highlightIndex >= 0 ? { defaultSelectedIndex: highlightIndex } : {},
5584
+ secondary: apps.map(secondaryFor),
5681
5585
  messages
5682
5586
  });
5683
5587
  const chosen = apps.find((app) => labelFor(app) === choice);
5684
- if (!chosen || !canSelectApplication(chosen)) {
5588
+ if (!chosen) {
5685
5589
  throw new Error("Application picker received an unexpected selection");
5686
5590
  }
5687
5591
  try {
@@ -5697,15 +5601,42 @@ async function promptForApplication(highlight) {
5697
5601
  }
5698
5602
  }
5699
5603
  }
5700
- async function ensureApplication(isResuming) {
5701
- const current = await currentApplication();
5702
- if (isResuming) {
5703
- if (current && await isEligible(current)) return current;
5704
- return promptForApplication();
5604
+ async function confirmEnvApplication(env, current) {
5605
+ const useEnv = `Use ${env.id} (from ${env.file})`;
5606
+ const choice = await useWizard.getState().requestUserInput({
5607
+ prompt: "Select an application",
5608
+ promptType: "multipleChoice",
5609
+ options: [
5610
+ useEnv,
5611
+ current ? `Use ${labelFor(current)} (already selected)` : "Pick a different application"
5612
+ ],
5613
+ messages: [
5614
+ `${env.file} already sets ${env.name}=${env.id}.`,
5615
+ "Which Algolia application should the wizard work in?"
5616
+ ]
5617
+ });
5618
+ return choice === useEnv;
5619
+ }
5620
+ async function selectEnvApplication(env) {
5621
+ try {
5622
+ return await selectAndReport({ id: env.id, name: "" });
5623
+ } catch (err) {
5624
+ logger.warn(
5625
+ { app: env.id, err: err.message },
5626
+ "could not select the application named in env; falling back to the picker"
5627
+ );
5628
+ return promptForApplication([
5629
+ `Could not select ${env.id} from ${env.file} \u2014 it may have been removed, or this account may not have access to it.`
5630
+ ]);
5705
5631
  }
5632
+ }
5633
+ async function ensureApplication() {
5634
+ const current = await currentApplication();
5706
5635
  const env = await findEnvApplicationId();
5707
- if (!env) return promptForApplication();
5708
- return promptForApplication({ id: env.id, file: env.file });
5636
+ if (env && env.id !== current?.id && await confirmEnvApplication(env, current)) {
5637
+ return selectEnvApplication(env);
5638
+ }
5639
+ return current ?? await promptForApplication();
5709
5640
  }
5710
5641
 
5711
5642
  // src/lib/seed.ts
@@ -6069,15 +6000,14 @@ async function run(workflow) {
6069
6000
  }
6070
6001
  store.setUser(user);
6071
6002
  let app;
6072
- const resumableState = await loadResumableState(workflow);
6073
6003
  try {
6074
- app = await ensureApplication(resumableState != null);
6004
+ app = await ensureApplication();
6075
6005
  } catch (err) {
6076
6006
  store.setError(err instanceof Error ? err.message : String(err));
6077
6007
  await instance.waitUntilExit();
6078
6008
  process.exit(1);
6079
6009
  }
6080
- runWorkflow(workflow, app.id, resumableState);
6010
+ runWorkflow(workflow, app.id);
6081
6011
  }
6082
6012
  await requestTerminalSize();
6083
6013
  var started = await startup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.38.0-rc.131.269",
3
+ "version": "0.38.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {