@algolia/wizard 0.46.0 → 0.47.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/main.js +284 -209
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -5,7 +5,7 @@ import { render } from "ink";
|
|
|
5
5
|
|
|
6
6
|
// src/ui/App.tsx
|
|
7
7
|
import { Box as Box20, Text as Text20, useApp, useInput as useInput7, useWindowSize as useWindowSize7 } from "ink";
|
|
8
|
-
import
|
|
8
|
+
import Spinner3 from "ink-spinner";
|
|
9
9
|
|
|
10
10
|
// src/core/store.ts
|
|
11
11
|
import { create } from "zustand";
|
|
@@ -259,10 +259,14 @@ var useWizard = create((set, get) => ({
|
|
|
259
259
|
error: null,
|
|
260
260
|
inputReq: null,
|
|
261
261
|
_resolve: null,
|
|
262
|
+
settingUpAppId: null,
|
|
263
|
+
setSettingUpApp: (appId) => set({ settingUpAppId: appId }),
|
|
262
264
|
// `endAuth` lands on 'preflight', not 'idle': sign-in happens after the
|
|
263
265
|
// welcome screen, so going back would gate the run a second time.
|
|
264
266
|
beginAuth: () => set({ phase: "authenticating", cliOutput: [] }),
|
|
265
|
-
endAuth: () => set(
|
|
267
|
+
endAuth: () => set(
|
|
268
|
+
(s) => s.phase === "authenticating" ? { phase: "preflight", cliOutput: [] } : {}
|
|
269
|
+
),
|
|
266
270
|
confirmStart: () => set(
|
|
267
271
|
(s) => s.phase === "idle" ? { phase: "preflight", homeScreen: "home" } : {}
|
|
268
272
|
),
|
|
@@ -409,7 +413,8 @@ var useWizard = create((set, get) => ({
|
|
|
409
413
|
logs: [],
|
|
410
414
|
error: null,
|
|
411
415
|
inputReq: null,
|
|
412
|
-
_resolve: null
|
|
416
|
+
_resolve: null,
|
|
417
|
+
settingUpAppId: null
|
|
413
418
|
});
|
|
414
419
|
}
|
|
415
420
|
}));
|
|
@@ -637,6 +642,7 @@ function Notices({
|
|
|
637
642
|
|
|
638
643
|
// src/ui/PromptInput.tsx
|
|
639
644
|
import { Box as Box9, Text as Text9 } from "ink";
|
|
645
|
+
import Spinner from "ink-spinner";
|
|
640
646
|
import TextInput from "ink-text-input";
|
|
641
647
|
import { useState as useState6 } from "react";
|
|
642
648
|
|
|
@@ -657,25 +663,27 @@ function SelectRow({
|
|
|
657
663
|
labelWidth,
|
|
658
664
|
highlightBackground = true,
|
|
659
665
|
usePadding = false,
|
|
666
|
+
disabled = false,
|
|
660
667
|
children
|
|
661
668
|
}) {
|
|
662
|
-
const
|
|
669
|
+
const active = highlighted && !disabled;
|
|
670
|
+
const labelColor = disabled ? COLORS.dim : active ? highlightBackground ? COLORS.highlight.fg : COLORS.success : COLORS.primary;
|
|
663
671
|
return /* @__PURE__ */ jsxs3(
|
|
664
672
|
Box4,
|
|
665
673
|
{
|
|
666
674
|
width,
|
|
667
675
|
paddingX: usePadding ? 1 : 0,
|
|
668
676
|
paddingY: usePadding ? 1 : 0,
|
|
669
|
-
backgroundColor:
|
|
677
|
+
backgroundColor: active && highlightBackground ? COLORS.highlight.bg : void 0,
|
|
670
678
|
children: [
|
|
671
679
|
/* @__PURE__ */ jsx3(Box4, { width: labelWidth, children: /* @__PURE__ */ jsxs3(
|
|
672
680
|
Text4,
|
|
673
681
|
{
|
|
674
682
|
color: labelColor,
|
|
675
|
-
bold:
|
|
683
|
+
bold: active && !highlightBackground,
|
|
676
684
|
wrap: "truncate",
|
|
677
685
|
children: [
|
|
678
|
-
|
|
686
|
+
active ? "\u276F " : " ",
|
|
679
687
|
label
|
|
680
688
|
]
|
|
681
689
|
}
|
|
@@ -875,6 +883,14 @@ var ARROW_WIDTH = 4;
|
|
|
875
883
|
var COLUMN_GAP = 2;
|
|
876
884
|
var BAR_PADDING = 2;
|
|
877
885
|
var ROW_HEIGHT = 3;
|
|
886
|
+
function nextSelectableIndex(start, dir, rowCount, isDisabled) {
|
|
887
|
+
let i = start;
|
|
888
|
+
for (let step = 0; step < rowCount; step++) {
|
|
889
|
+
i = (i + dir + rowCount) % rowCount;
|
|
890
|
+
if (!isDisabled(i)) return i;
|
|
891
|
+
}
|
|
892
|
+
return start;
|
|
893
|
+
}
|
|
878
894
|
function SelectPrompt({
|
|
879
895
|
options,
|
|
880
896
|
onSelect,
|
|
@@ -886,15 +902,18 @@ function SelectPrompt({
|
|
|
886
902
|
multi,
|
|
887
903
|
cancelable,
|
|
888
904
|
secondary,
|
|
905
|
+
disabled,
|
|
889
906
|
defaultSelectedIndex = 0
|
|
890
907
|
}) {
|
|
891
|
-
const [index, setIndex] = useState5(
|
|
892
|
-
() => defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0
|
|
893
|
-
);
|
|
894
|
-
const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
|
|
895
908
|
const hasCancel = Boolean(multi || cancelable);
|
|
896
909
|
const rows = hasCancel ? [...options, "Cancel"] : options;
|
|
897
910
|
const cancelIndex = hasCancel ? options.length : -1;
|
|
911
|
+
const isDisabled = (i) => i !== cancelIndex && Boolean(disabled?.[i]);
|
|
912
|
+
const [index, setIndex] = useState5(() => {
|
|
913
|
+
const start = defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0;
|
|
914
|
+
return isDisabled(start) ? nextSelectableIndex(start, 1, rows.length, isDisabled) : start;
|
|
915
|
+
});
|
|
916
|
+
const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
|
|
898
917
|
const hints = [];
|
|
899
918
|
if (rows.length > 1) hints.push({ key: "[\u2191] [\u2193]", label: "move" });
|
|
900
919
|
if (multi) hints.push({ key: "[space]", label: "select" });
|
|
@@ -934,10 +953,10 @@ function SelectPrompt({
|
|
|
934
953
|
useInput2((input, key) => {
|
|
935
954
|
if (rows.length === 0) return;
|
|
936
955
|
if (key.upArrow || input === "k") {
|
|
937
|
-
setIndex((i) => (i -
|
|
956
|
+
setIndex((i) => nextSelectableIndex(i, -1, rows.length, isDisabled));
|
|
938
957
|
} else if (key.downArrow || input === "j") {
|
|
939
|
-
setIndex((i) => (i
|
|
940
|
-
} else if (multi && input === " " && index !== cancelIndex) {
|
|
958
|
+
setIndex((i) => nextSelectableIndex(i, 1, rows.length, isDisabled));
|
|
959
|
+
} else if (multi && input === " " && index !== cancelIndex && !isDisabled(index)) {
|
|
941
960
|
setChecked((prev) => {
|
|
942
961
|
const next = new Set(prev);
|
|
943
962
|
if (next.has(index)) next.delete(index);
|
|
@@ -947,10 +966,12 @@ function SelectPrompt({
|
|
|
947
966
|
} else if (key.return) {
|
|
948
967
|
if (index === cancelIndex) {
|
|
949
968
|
onSelect(CANCEL);
|
|
969
|
+
} else if (isDisabled(index)) {
|
|
950
970
|
} else if (!multi) {
|
|
951
971
|
onSelect(options[index]);
|
|
952
|
-
} else
|
|
953
|
-
|
|
972
|
+
} else {
|
|
973
|
+
const picked = options.filter((_, i) => checked.has(i) && !isDisabled(i));
|
|
974
|
+
if (picked.length > 0) onSelect(picked);
|
|
954
975
|
}
|
|
955
976
|
}
|
|
956
977
|
});
|
|
@@ -971,10 +992,12 @@ function SelectPrompt({
|
|
|
971
992
|
const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
|
|
972
993
|
const sec = isCancel ? void 0 : secondary?.[i];
|
|
973
994
|
const isText = sec?.kind === "text";
|
|
995
|
+
const rowDisabled = isDisabled(i);
|
|
974
996
|
return /* @__PURE__ */ jsxs7(
|
|
975
997
|
SelectRow,
|
|
976
998
|
{
|
|
977
999
|
highlighted,
|
|
1000
|
+
disabled: rowDisabled,
|
|
978
1001
|
width: isText ? "100%" : barWidth,
|
|
979
1002
|
labelWidth: isText ? labelWidth : barLabelWidth,
|
|
980
1003
|
label: `${bullet}${option}`,
|
|
@@ -984,7 +1007,7 @@ function SelectPrompt({
|
|
|
984
1007
|
Text8,
|
|
985
1008
|
{
|
|
986
1009
|
wrap: "truncate",
|
|
987
|
-
color: highlighted ? COLORS.primary : COLORS.muted,
|
|
1010
|
+
color: rowDisabled ? COLORS.dim : highlighted ? COLORS.primary : COLORS.muted,
|
|
988
1011
|
children: sec.value
|
|
989
1012
|
}
|
|
990
1013
|
) }),
|
|
@@ -1031,11 +1054,23 @@ function EnterToContinuePrompt({
|
|
|
1031
1054
|
function PromptInput() {
|
|
1032
1055
|
const { phase, inputReq, submitInput } = useWizard();
|
|
1033
1056
|
const [draft, setDraft] = useState6("");
|
|
1057
|
+
const [submittedReq, setSubmittedReq] = useState6(null);
|
|
1034
1058
|
const promptKey = inputReq && `${inputReq.promptType}:${inputReq.prompt}`;
|
|
1059
|
+
const submitting = inputReq != null && submittedReq === inputReq;
|
|
1035
1060
|
if (phase === "done" || phase === "error") {
|
|
1036
1061
|
return /* @__PURE__ */ jsx7(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text9, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
|
|
1037
1062
|
}
|
|
1038
1063
|
if (phase !== "awaitingInput" || !inputReq) return null;
|
|
1064
|
+
if (submitting) {
|
|
1065
|
+
return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsxs8(Text9, { color: COLORS.strong, bold: true, children: [
|
|
1066
|
+
/* @__PURE__ */ jsx7(Spinner, { type: "dots" }),
|
|
1067
|
+
" Continuing\u2026"
|
|
1068
|
+
] }) });
|
|
1069
|
+
}
|
|
1070
|
+
const handleSubmit = (value) => {
|
|
1071
|
+
setSubmittedReq(inputReq);
|
|
1072
|
+
submitInput(value);
|
|
1073
|
+
};
|
|
1039
1074
|
if (inputReq.promptType === "multipleChoice") {
|
|
1040
1075
|
return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
|
|
1041
1076
|
SelectPrompt,
|
|
@@ -1046,10 +1081,11 @@ function PromptInput() {
|
|
|
1046
1081
|
table: inputReq.table,
|
|
1047
1082
|
options: inputReq.options,
|
|
1048
1083
|
secondary: inputReq.secondary,
|
|
1084
|
+
disabled: inputReq.disabled,
|
|
1049
1085
|
defaultSelectedIndex: inputReq.defaultSelectedIndex,
|
|
1050
1086
|
cancelable: inputReq.cancelable,
|
|
1051
1087
|
error: inputReq.error,
|
|
1052
|
-
onSelect:
|
|
1088
|
+
onSelect: handleSubmit
|
|
1053
1089
|
},
|
|
1054
1090
|
promptKey
|
|
1055
1091
|
) });
|
|
@@ -1065,7 +1101,7 @@ function PromptInput() {
|
|
|
1065
1101
|
table: inputReq.table,
|
|
1066
1102
|
options: inputReq.options,
|
|
1067
1103
|
error: inputReq.error,
|
|
1068
|
-
onSelect:
|
|
1104
|
+
onSelect: handleSubmit
|
|
1069
1105
|
},
|
|
1070
1106
|
promptKey
|
|
1071
1107
|
) });
|
|
@@ -1077,7 +1113,7 @@ function PromptInput() {
|
|
|
1077
1113
|
question: inputReq.prompt,
|
|
1078
1114
|
messages: inputReq.messages,
|
|
1079
1115
|
options: ["Continue"],
|
|
1080
|
-
onSelect:
|
|
1116
|
+
onSelect: handleSubmit
|
|
1081
1117
|
},
|
|
1082
1118
|
promptKey
|
|
1083
1119
|
) });
|
|
@@ -1104,7 +1140,7 @@ function PromptInput() {
|
|
|
1104
1140
|
messages: inputReq.messages,
|
|
1105
1141
|
options: labels,
|
|
1106
1142
|
secondary: inputReq.secondary,
|
|
1107
|
-
onSelect: (value) =>
|
|
1143
|
+
onSelect: (value) => handleSubmit(value === labels[0])
|
|
1108
1144
|
},
|
|
1109
1145
|
promptKey
|
|
1110
1146
|
) });
|
|
@@ -1285,6 +1321,10 @@ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, rm } f
|
|
|
1285
1321
|
import { join as join4 } from "node:path";
|
|
1286
1322
|
var isStepVisible = (s) => s.visible !== false;
|
|
1287
1323
|
var stateFile = (workflowId) => join4(stateDir(), `state-${workflowId}.json`);
|
|
1324
|
+
function runAppId(state) {
|
|
1325
|
+
const appId = state.algoliaState.appId;
|
|
1326
|
+
return typeof appId === "string" && appId ? appId : void 0;
|
|
1327
|
+
}
|
|
1288
1328
|
async function loadWorkflowState(workflowId) {
|
|
1289
1329
|
try {
|
|
1290
1330
|
const raw = await readFile2(stateFile(workflowId), "utf8");
|
|
@@ -1564,7 +1604,11 @@ function reconcileWorkflowState(state, workflow) {
|
|
|
1564
1604
|
}
|
|
1565
1605
|
return state;
|
|
1566
1606
|
}
|
|
1567
|
-
function
|
|
1607
|
+
async function loadResumableState(workflow) {
|
|
1608
|
+
const persisted = await loadWorkflowState(workflow.id);
|
|
1609
|
+
return persisted ? reconcileWorkflowState(persisted, workflow) : null;
|
|
1610
|
+
}
|
|
1611
|
+
function initWorkflowState(workflow, now, appId) {
|
|
1568
1612
|
return {
|
|
1569
1613
|
workflowId: workflow.id,
|
|
1570
1614
|
startedAt: now,
|
|
@@ -1576,7 +1620,7 @@ function initWorkflowState(workflow, now) {
|
|
|
1576
1620
|
visible: s.visible,
|
|
1577
1621
|
status: "pending"
|
|
1578
1622
|
})),
|
|
1579
|
-
algoliaState: {},
|
|
1623
|
+
algoliaState: appId ? { appId } : {},
|
|
1580
1624
|
userInputs: {}
|
|
1581
1625
|
};
|
|
1582
1626
|
}
|
|
@@ -1666,11 +1710,11 @@ async function runStep(state, index, step, appId) {
|
|
|
1666
1710
|
durationMs: Date.now() - startedAt
|
|
1667
1711
|
});
|
|
1668
1712
|
}
|
|
1669
|
-
async function runWorkflow(workflow, appId) {
|
|
1713
|
+
async function runWorkflow(workflow, appId, resumableState) {
|
|
1670
1714
|
const store = useWizard.getState();
|
|
1671
1715
|
try {
|
|
1672
|
-
const
|
|
1673
|
-
const state =
|
|
1716
|
+
const resolved2 = resumableState !== void 0 ? resumableState : await loadResumableState(workflow);
|
|
1717
|
+
const state = resolved2 ?? initWorkflowState(workflow, nowIso(), appId);
|
|
1674
1718
|
ensureExecutedStepCount(state);
|
|
1675
1719
|
store.startWorkflow(
|
|
1676
1720
|
{
|
|
@@ -1762,14 +1806,89 @@ async function listIndices() {
|
|
|
1762
1806
|
return items.map((i) => ({ name: i.name, entries: i.entries })).sort((a, b) => a.name.localeCompare(b.name));
|
|
1763
1807
|
}
|
|
1764
1808
|
|
|
1809
|
+
// src/lib/algoliaApp.ts
|
|
1810
|
+
import { z as z5 } from "zod";
|
|
1811
|
+
var applicationSchema = z5.object({
|
|
1812
|
+
id: z5.string().min(1),
|
|
1813
|
+
name: z5.string().default(""),
|
|
1814
|
+
plan: z5.string().optional()
|
|
1815
|
+
});
|
|
1816
|
+
var listSchema = z5.array(
|
|
1817
|
+
z5.object({
|
|
1818
|
+
id: z5.string().min(1),
|
|
1819
|
+
name: z5.string().default(""),
|
|
1820
|
+
plan_label: z5.string().optional(),
|
|
1821
|
+
status: z5.string().optional(),
|
|
1822
|
+
acl: z5.array(z5.string()).optional()
|
|
1823
|
+
}).transform(({ id, name, plan_label, status, acl }) => ({
|
|
1824
|
+
id,
|
|
1825
|
+
name,
|
|
1826
|
+
plan: plan_label,
|
|
1827
|
+
status,
|
|
1828
|
+
acl
|
|
1829
|
+
}))
|
|
1830
|
+
);
|
|
1831
|
+
function canSelectApplication(app) {
|
|
1832
|
+
return app.status === "active" && (app.acl ?? []).includes("keys");
|
|
1833
|
+
}
|
|
1834
|
+
async function currentApplication() {
|
|
1835
|
+
let raw;
|
|
1836
|
+
try {
|
|
1837
|
+
raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
|
|
1838
|
+
} catch {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
1842
|
+
return parsed.success ? parsed.data : null;
|
|
1843
|
+
}
|
|
1844
|
+
async function requireApplication() {
|
|
1845
|
+
const app = await currentApplication();
|
|
1846
|
+
if (!app) {
|
|
1847
|
+
throw new Error(
|
|
1848
|
+
"No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
|
|
1849
|
+
);
|
|
1850
|
+
}
|
|
1851
|
+
return app;
|
|
1852
|
+
}
|
|
1853
|
+
async function listApplications() {
|
|
1854
|
+
const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
|
|
1855
|
+
const parsed = listSchema.safeParse(parseJson(raw));
|
|
1856
|
+
if (!parsed.success) {
|
|
1857
|
+
throw new Error("Could not read the list of Algolia applications.");
|
|
1858
|
+
}
|
|
1859
|
+
return parsed.data;
|
|
1860
|
+
}
|
|
1861
|
+
async function selectApplication(id) {
|
|
1862
|
+
const raw = await runAlgoliaCli(
|
|
1863
|
+
["application", "select", "--non-interactive", "--app-id", id],
|
|
1864
|
+
{ onOutput: stderrSink }
|
|
1865
|
+
);
|
|
1866
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
1867
|
+
if (!parsed.success) {
|
|
1868
|
+
throw new Error(
|
|
1869
|
+
`Selected application ${id}, but the Algolia CLI returned an unreadable result.`
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
1872
|
+
return parsed.data;
|
|
1873
|
+
}
|
|
1874
|
+
function parseJson(text) {
|
|
1875
|
+
try {
|
|
1876
|
+
return JSON.parse(text);
|
|
1877
|
+
} catch {
|
|
1878
|
+
return void 0;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1765
1882
|
// src/actions/selectIndex.ts
|
|
1766
1883
|
var CREATE_NEW_INDEX = "Create a new index\u2026";
|
|
1767
1884
|
var selectIndexStep = async (ctx) => {
|
|
1885
|
+
await requireApplication();
|
|
1768
1886
|
const indices = await listIndices();
|
|
1769
1887
|
const names = indices.map((i) => i.name);
|
|
1770
1888
|
const hasIndices = names.length > 0;
|
|
1771
1889
|
let error;
|
|
1772
|
-
|
|
1890
|
+
let chosen;
|
|
1891
|
+
while (chosen === void 0) {
|
|
1773
1892
|
const selection = hasIndices ? await ctx.requestUserInput({
|
|
1774
1893
|
prompt: "Which index do you want to ingest into?",
|
|
1775
1894
|
promptType: "multipleChoice",
|
|
@@ -1788,9 +1907,9 @@ var selectIndexStep = async (ctx) => {
|
|
|
1788
1907
|
if (typeof selection !== "string") {
|
|
1789
1908
|
throw new Error("selectIndex received an unexpected non-text result");
|
|
1790
1909
|
}
|
|
1791
|
-
let
|
|
1910
|
+
let candidate;
|
|
1792
1911
|
if (!hasIndices) {
|
|
1793
|
-
|
|
1912
|
+
candidate = selection.trim();
|
|
1794
1913
|
} else if (selection === CREATE_NEW_INDEX) {
|
|
1795
1914
|
const name = await ctx.requestUserInput({
|
|
1796
1915
|
prompt: "Name the new index:",
|
|
@@ -1800,17 +1919,18 @@ var selectIndexStep = async (ctx) => {
|
|
|
1800
1919
|
if (typeof name !== "string") {
|
|
1801
1920
|
throw new Error("selectIndex received an unexpected non-text result");
|
|
1802
1921
|
}
|
|
1803
|
-
|
|
1922
|
+
candidate = name.trim();
|
|
1804
1923
|
} else {
|
|
1805
|
-
|
|
1924
|
+
candidate = selection;
|
|
1806
1925
|
}
|
|
1807
|
-
if (!
|
|
1926
|
+
if (!candidate) {
|
|
1808
1927
|
error = "Index name cannot be empty.";
|
|
1809
1928
|
continue;
|
|
1810
1929
|
}
|
|
1811
|
-
|
|
1812
|
-
return { selection: chosen };
|
|
1930
|
+
chosen = candidate;
|
|
1813
1931
|
}
|
|
1932
|
+
ctx.setUserInput("index", chosen);
|
|
1933
|
+
return { selection: chosen };
|
|
1814
1934
|
};
|
|
1815
1935
|
|
|
1816
1936
|
// src/lib/agent.ts
|
|
@@ -1829,7 +1949,7 @@ import "zod";
|
|
|
1829
1949
|
|
|
1830
1950
|
// src/lib/tools/listFiles.ts
|
|
1831
1951
|
import { tool } from "ai";
|
|
1832
|
-
import
|
|
1952
|
+
import z6 from "zod";
|
|
1833
1953
|
import { readdir } from "node:fs/promises";
|
|
1834
1954
|
|
|
1835
1955
|
// src/lib/tools/path.ts
|
|
@@ -1865,8 +1985,8 @@ async function hasSymlinkParent(ctx, target) {
|
|
|
1865
1985
|
function listFilesTool(ctx) {
|
|
1866
1986
|
return tool({
|
|
1867
1987
|
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.',
|
|
1868
|
-
inputSchema:
|
|
1869
|
-
path:
|
|
1988
|
+
inputSchema: z6.object({
|
|
1989
|
+
path: z6.string().optional().describe("Directory to list, relative to cwd (default: cwd)")
|
|
1870
1990
|
}),
|
|
1871
1991
|
execute: async ({ path = "." }) => {
|
|
1872
1992
|
logger.info({ path }, "called listFiles tool");
|
|
@@ -1887,13 +2007,13 @@ function listFilesTool(ctx) {
|
|
|
1887
2007
|
|
|
1888
2008
|
// src/lib/tools/changeDirectory.ts
|
|
1889
2009
|
import { tool as tool2 } from "ai";
|
|
1890
|
-
import
|
|
2010
|
+
import z7 from "zod";
|
|
1891
2011
|
import { stat } from "node:fs/promises";
|
|
1892
2012
|
function changeDirectoryTool(ctx) {
|
|
1893
2013
|
return tool2({
|
|
1894
2014
|
description: "Change the current working directory. Subsequent file operations resolve relative to it. Returns the new working directory.",
|
|
1895
|
-
inputSchema:
|
|
1896
|
-
path:
|
|
2015
|
+
inputSchema: z7.object({
|
|
2016
|
+
path: z7.string().describe("Directory to change into")
|
|
1897
2017
|
}),
|
|
1898
2018
|
execute: async ({ path }) => {
|
|
1899
2019
|
logger.info({ path }, "called changeDirectory tool");
|
|
@@ -1915,13 +2035,13 @@ function changeDirectoryTool(ctx) {
|
|
|
1915
2035
|
|
|
1916
2036
|
// src/lib/tools/reportStatus.ts
|
|
1917
2037
|
import { tool as tool3 } from "ai";
|
|
1918
|
-
import
|
|
2038
|
+
import z8 from "zod";
|
|
1919
2039
|
function reportStatusTool(output) {
|
|
1920
2040
|
return tool3({
|
|
1921
2041
|
description: "Report the status of your execution. Return a reason in case of failure.",
|
|
1922
|
-
inputSchema:
|
|
1923
|
-
status:
|
|
1924
|
-
reason:
|
|
2042
|
+
inputSchema: z8.object({
|
|
2043
|
+
status: z8.enum(["success", "fail"]),
|
|
2044
|
+
reason: z8.string().optional(),
|
|
1925
2045
|
output
|
|
1926
2046
|
}),
|
|
1927
2047
|
execute: async ({ status, reason, output: output2 }) => {
|
|
@@ -1933,7 +2053,7 @@ function reportStatusTool(output) {
|
|
|
1933
2053
|
|
|
1934
2054
|
// src/lib/tools/readFile.ts
|
|
1935
2055
|
import { tool as tool4 } from "ai";
|
|
1936
|
-
import
|
|
2056
|
+
import z9 from "zod";
|
|
1937
2057
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
1938
2058
|
|
|
1939
2059
|
// src/lib/tools/env.ts
|
|
@@ -1961,8 +2081,8 @@ function redactEnvValues(content) {
|
|
|
1961
2081
|
function readFileTool(ctx) {
|
|
1962
2082
|
return tool4({
|
|
1963
2083
|
description: "Read the contents of a file at the given path",
|
|
1964
|
-
inputSchema:
|
|
1965
|
-
filePath:
|
|
2084
|
+
inputSchema: z9.object({
|
|
2085
|
+
filePath: z9.string().describe("Path to the file to read")
|
|
1966
2086
|
}),
|
|
1967
2087
|
execute: async ({ filePath }) => {
|
|
1968
2088
|
if (++ctx.counts.read > ctx.limits.read) {
|
|
@@ -1983,15 +2103,15 @@ function readFileTool(ctx) {
|
|
|
1983
2103
|
|
|
1984
2104
|
// src/lib/tools/writeFile.ts
|
|
1985
2105
|
import { tool as tool5 } from "ai";
|
|
1986
|
-
import
|
|
2106
|
+
import z10 from "zod";
|
|
1987
2107
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
1988
2108
|
import { dirname as dirname3 } from "node:path";
|
|
1989
2109
|
function writeFileTool(ctx) {
|
|
1990
2110
|
return tool5({
|
|
1991
2111
|
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.",
|
|
1992
|
-
inputSchema:
|
|
1993
|
-
filePath:
|
|
1994
|
-
content:
|
|
2112
|
+
inputSchema: z10.object({
|
|
2113
|
+
filePath: z10.string().describe("Path to the file to write"),
|
|
2114
|
+
content: z10.string().describe("Content to write to the file")
|
|
1995
2115
|
}),
|
|
1996
2116
|
execute: async ({ filePath, content }) => {
|
|
1997
2117
|
logger.info({ filePath }, "called writeFile tool");
|
|
@@ -2021,68 +2141,6 @@ import z13 from "zod";
|
|
|
2021
2141
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
|
|
2022
2142
|
import { dirname as dirname4, relative as relative3 } from "node:path";
|
|
2023
2143
|
|
|
2024
|
-
// src/lib/algoliaApp.ts
|
|
2025
|
-
import { z as z10 } from "zod";
|
|
2026
|
-
var applicationSchema = z10.object({
|
|
2027
|
-
id: z10.string().min(1),
|
|
2028
|
-
name: z10.string().default(""),
|
|
2029
|
-
plan: z10.string().optional()
|
|
2030
|
-
});
|
|
2031
|
-
var listSchema = z10.array(
|
|
2032
|
-
z10.object({
|
|
2033
|
-
id: z10.string().min(1),
|
|
2034
|
-
name: z10.string().default(""),
|
|
2035
|
-
plan_label: z10.string().optional()
|
|
2036
|
-
}).transform(({ id, name, plan_label }) => ({ id, name, plan: plan_label }))
|
|
2037
|
-
);
|
|
2038
|
-
async function currentApplication() {
|
|
2039
|
-
let raw;
|
|
2040
|
-
try {
|
|
2041
|
-
raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
|
|
2042
|
-
} catch {
|
|
2043
|
-
return null;
|
|
2044
|
-
}
|
|
2045
|
-
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
2046
|
-
return parsed.success ? parsed.data : null;
|
|
2047
|
-
}
|
|
2048
|
-
async function requireApplication() {
|
|
2049
|
-
const app = await currentApplication();
|
|
2050
|
-
if (!app) {
|
|
2051
|
-
throw new Error(
|
|
2052
|
-
"No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
|
|
2053
|
-
);
|
|
2054
|
-
}
|
|
2055
|
-
return app;
|
|
2056
|
-
}
|
|
2057
|
-
async function listApplications() {
|
|
2058
|
-
const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
|
|
2059
|
-
const parsed = listSchema.safeParse(parseJson(raw));
|
|
2060
|
-
if (!parsed.success) {
|
|
2061
|
-
throw new Error("Could not read the list of Algolia applications.");
|
|
2062
|
-
}
|
|
2063
|
-
return parsed.data;
|
|
2064
|
-
}
|
|
2065
|
-
async function selectApplication(id) {
|
|
2066
|
-
const raw = await runAlgoliaCli(
|
|
2067
|
-
["application", "select", "--non-interactive", "--app-id", id],
|
|
2068
|
-
{ onOutput: stderrSink }
|
|
2069
|
-
);
|
|
2070
|
-
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
2071
|
-
if (!parsed.success) {
|
|
2072
|
-
throw new Error(
|
|
2073
|
-
`Selected application ${id}, but the Algolia CLI returned an unreadable result.`
|
|
2074
|
-
);
|
|
2075
|
-
}
|
|
2076
|
-
return parsed.data;
|
|
2077
|
-
}
|
|
2078
|
-
function parseJson(text) {
|
|
2079
|
-
try {
|
|
2080
|
-
return JSON.parse(text);
|
|
2081
|
-
} catch {
|
|
2082
|
-
return void 0;
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
2144
|
// src/lib/algoliaApiKey.ts
|
|
2087
2145
|
import { z as z12 } from "zod";
|
|
2088
2146
|
|
|
@@ -2090,13 +2148,13 @@ import { z as z12 } from "zod";
|
|
|
2090
2148
|
import { deletePassword, getPassword, setPassword } from "cross-keychain";
|
|
2091
2149
|
import { z as z11 } from "zod";
|
|
2092
2150
|
var SERVICE = "algolia-wizard";
|
|
2093
|
-
var
|
|
2151
|
+
var account = (userId) => `api-keys:${userId}`;
|
|
2094
2152
|
var storedKeysSchema = z11.record(z11.string(), z11.string());
|
|
2095
2153
|
function entryId(kind, index, appId) {
|
|
2096
2154
|
return `${kind}:${appId}:${index}`;
|
|
2097
2155
|
}
|
|
2098
|
-
async function loadKeys() {
|
|
2099
|
-
const raw = await getPassword(SERVICE,
|
|
2156
|
+
async function loadKeys(userId) {
|
|
2157
|
+
const raw = await getPassword(SERVICE, account(userId));
|
|
2100
2158
|
if (!raw) return {};
|
|
2101
2159
|
let payload;
|
|
2102
2160
|
try {
|
|
@@ -2118,47 +2176,47 @@ function serialized(op) {
|
|
|
2118
2176
|
});
|
|
2119
2177
|
return next;
|
|
2120
2178
|
}
|
|
2121
|
-
async function readStoredKey(kind, index, appId) {
|
|
2179
|
+
async function readStoredKey(kind, userId, index, appId) {
|
|
2122
2180
|
try {
|
|
2123
|
-
return (await loadKeys())[entryId(kind, index, appId)] ?? null;
|
|
2181
|
+
return (await loadKeys(userId))[entryId(kind, index, appId)] ?? null;
|
|
2124
2182
|
} catch (err) {
|
|
2125
2183
|
logger.warn(
|
|
2126
|
-
{ err: err.message, kind, index, appId },
|
|
2184
|
+
{ err: err.message, kind, index, appId, userId },
|
|
2127
2185
|
"could not read the API key from the keychain"
|
|
2128
2186
|
);
|
|
2129
2187
|
return null;
|
|
2130
2188
|
}
|
|
2131
2189
|
}
|
|
2132
|
-
function storeKey(kind, index, appId, value) {
|
|
2190
|
+
function storeKey(kind, userId, index, appId, value) {
|
|
2133
2191
|
return serialized(async () => {
|
|
2134
2192
|
const id = entryId(kind, index, appId);
|
|
2135
2193
|
try {
|
|
2136
|
-
const keys = await loadKeys();
|
|
2194
|
+
const keys = await loadKeys(userId);
|
|
2137
2195
|
await setPassword(
|
|
2138
2196
|
SERVICE,
|
|
2139
|
-
|
|
2197
|
+
account(userId),
|
|
2140
2198
|
JSON.stringify({ ...keys, [id]: value })
|
|
2141
2199
|
);
|
|
2142
|
-
if ((await loadKeys())[id] !== value) {
|
|
2200
|
+
if ((await loadKeys(userId))[id] !== value) {
|
|
2143
2201
|
throw new Error("the keychain did not store the value");
|
|
2144
2202
|
}
|
|
2145
2203
|
} catch (err) {
|
|
2146
2204
|
logger.warn(
|
|
2147
|
-
{ err: err.message, kind, index, appId },
|
|
2205
|
+
{ err: err.message, kind, index, appId, userId },
|
|
2148
2206
|
"could not store the API key in the keychain; the next run will create another"
|
|
2149
2207
|
);
|
|
2150
2208
|
}
|
|
2151
2209
|
});
|
|
2152
2210
|
}
|
|
2153
|
-
function deleteStoredKeys() {
|
|
2211
|
+
function deleteStoredKeys(userId) {
|
|
2154
2212
|
return serialized(async () => {
|
|
2155
2213
|
try {
|
|
2156
|
-
await deletePassword(SERVICE,
|
|
2214
|
+
await deletePassword(SERVICE, account(userId));
|
|
2157
2215
|
} catch (err) {
|
|
2158
2216
|
const message = err.message;
|
|
2159
2217
|
if (/not found/i.test(message)) return;
|
|
2160
2218
|
logger.warn(
|
|
2161
|
-
{ err: message },
|
|
2219
|
+
{ err: message, userId },
|
|
2162
2220
|
"could not delete the API keys from the keychain"
|
|
2163
2221
|
);
|
|
2164
2222
|
}
|
|
@@ -2166,6 +2224,16 @@ function deleteStoredKeys() {
|
|
|
2166
2224
|
}
|
|
2167
2225
|
|
|
2168
2226
|
// src/lib/algoliaApiKey.ts
|
|
2227
|
+
function requireUserId() {
|
|
2228
|
+
const userId = useWizard.getState().user?.userId;
|
|
2229
|
+
if (!userId) {
|
|
2230
|
+
throw new Error("No Algolia user is signed in; cannot scope the API key.");
|
|
2231
|
+
}
|
|
2232
|
+
return userId;
|
|
2233
|
+
}
|
|
2234
|
+
async function currentUserId() {
|
|
2235
|
+
return useWizard.getState().user?.userId ?? (await getUser())?.userId ?? null;
|
|
2236
|
+
}
|
|
2169
2237
|
var WRITE_ACLS = [
|
|
2170
2238
|
"addObject",
|
|
2171
2239
|
"deleteObject",
|
|
@@ -2212,23 +2280,30 @@ async function keyExists(key) {
|
|
|
2212
2280
|
var resolved = /* @__PURE__ */ new Map();
|
|
2213
2281
|
async function forgetResolvedKeys() {
|
|
2214
2282
|
resolved.clear();
|
|
2215
|
-
await
|
|
2283
|
+
const userId = await currentUserId();
|
|
2284
|
+
if (userId) await deleteStoredKeys(userId);
|
|
2216
2285
|
}
|
|
2217
2286
|
function resolveKey(kind, index, appId, acls, description) {
|
|
2218
|
-
const
|
|
2287
|
+
const userId = requireUserId();
|
|
2288
|
+
const cacheKey = `${userId}:${kind}:${appId}:${index}`;
|
|
2219
2289
|
const cached = resolved.get(cacheKey);
|
|
2220
2290
|
if (cached) return cached;
|
|
2221
|
-
const pending = provisionKey(
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2291
|
+
const pending = provisionKey(
|
|
2292
|
+
kind,
|
|
2293
|
+
userId,
|
|
2294
|
+
index,
|
|
2295
|
+
appId,
|
|
2296
|
+
acls,
|
|
2297
|
+
description
|
|
2298
|
+
).catch((err) => {
|
|
2299
|
+
resolved.delete(cacheKey);
|
|
2300
|
+
throw err;
|
|
2301
|
+
});
|
|
2227
2302
|
resolved.set(cacheKey, pending);
|
|
2228
2303
|
return pending;
|
|
2229
2304
|
}
|
|
2230
|
-
async function provisionKey(kind, index, appId, acls, description) {
|
|
2231
|
-
const stored = await readStoredKey(kind, index, appId);
|
|
2305
|
+
async function provisionKey(kind, userId, index, appId, acls, description) {
|
|
2306
|
+
const stored = await readStoredKey(kind, userId, index, appId);
|
|
2232
2307
|
if (stored) {
|
|
2233
2308
|
if (await keyExists(stored)) {
|
|
2234
2309
|
logger.info({ kind, index, appId }, "reusing the stored API key");
|
|
@@ -2240,7 +2315,7 @@ async function provisionKey(kind, index, appId, acls, description) {
|
|
|
2240
2315
|
);
|
|
2241
2316
|
}
|
|
2242
2317
|
const key = await createKey(index, acls, description);
|
|
2243
|
-
await storeKey(kind, index, appId, key);
|
|
2318
|
+
await storeKey(kind, userId, index, appId, key);
|
|
2244
2319
|
return { key, source: "created" };
|
|
2245
2320
|
}
|
|
2246
2321
|
function resolveWriteKey(index, appId) {
|
|
@@ -3509,7 +3584,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
3509
3584
|
// package.json
|
|
3510
3585
|
var package_default = {
|
|
3511
3586
|
name: "@algolia/wizard",
|
|
3512
|
-
version: "0.
|
|
3587
|
+
version: "0.47.0",
|
|
3513
3588
|
description: "Magically implement Algolia functionality in your codebase",
|
|
3514
3589
|
type: "module",
|
|
3515
3590
|
engines: {
|
|
@@ -4435,6 +4510,10 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
4435
4510
|
if (useCases.includes("ingestion")) {
|
|
4436
4511
|
ingestAppId = appId ?? (await requireApplication()).id;
|
|
4437
4512
|
}
|
|
4513
|
+
let ingestWriteKey;
|
|
4514
|
+
if (useCases.includes("ingestion") && ingestAppId) {
|
|
4515
|
+
ingestWriteKey = (await resolveWriteKey(targetIndex, ingestAppId)).key;
|
|
4516
|
+
}
|
|
4438
4517
|
let uploadFilePath;
|
|
4439
4518
|
let uploadWarning;
|
|
4440
4519
|
if (ingestionSource === "fileUpload") {
|
|
@@ -4497,9 +4576,9 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
4497
4576
|
let ingestDurationMs;
|
|
4498
4577
|
let ingestOutcomeMessage;
|
|
4499
4578
|
const ingestKeyAppId = ingestAppId;
|
|
4500
|
-
const ingestionTools = ingestKeyAppId ? makeToolContext(repoRoot, async () => ({
|
|
4579
|
+
const ingestionTools = ingestKeyAppId && ingestWriteKey ? makeToolContext(repoRoot, async () => ({
|
|
4501
4580
|
[APP_ID_VAR]: ingestKeyAppId,
|
|
4502
|
-
[API_KEY_VAR]:
|
|
4581
|
+
[API_KEY_VAR]: ingestWriteKey,
|
|
4503
4582
|
[INDEX_NAME_VAR]: targetIndex
|
|
4504
4583
|
})) : void 0;
|
|
4505
4584
|
const searchTools = makeToolContext(repoRoot);
|
|
@@ -5094,13 +5173,13 @@ import { Box as Box15, Text as Text15 } from "ink";
|
|
|
5094
5173
|
|
|
5095
5174
|
// src/ui/Steps.tsx
|
|
5096
5175
|
import { Box as Box13, Text as Text13 } from "ink";
|
|
5097
|
-
import
|
|
5176
|
+
import Spinner2 from "ink-spinner";
|
|
5098
5177
|
import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5099
5178
|
function Steps() {
|
|
5100
5179
|
const { steps } = useWizard();
|
|
5101
5180
|
const visibleSteps = steps.filter(isStepVisible);
|
|
5102
5181
|
return /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status[s.status], children: [
|
|
5103
|
-
s.status === "running" ? /* @__PURE__ */ jsx11(
|
|
5182
|
+
s.status === "running" ? /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }) : MARKER[s.status],
|
|
5104
5183
|
" ",
|
|
5105
5184
|
s.title
|
|
5106
5185
|
] }) }, s.id)) });
|
|
@@ -5110,7 +5189,7 @@ function CurrentStep() {
|
|
|
5110
5189
|
const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
|
|
5111
5190
|
if (!currentStep) return null;
|
|
5112
5191
|
return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status.running, children: [
|
|
5113
|
-
/* @__PURE__ */ jsx11(
|
|
5192
|
+
/* @__PURE__ */ jsx11(Spinner2, { type: "dots" }),
|
|
5114
5193
|
" ",
|
|
5115
5194
|
` ${currentStep.title}`
|
|
5116
5195
|
] });
|
|
@@ -5655,6 +5734,7 @@ function App() {
|
|
|
5655
5734
|
inputReq,
|
|
5656
5735
|
user,
|
|
5657
5736
|
workflow,
|
|
5737
|
+
settingUpAppId,
|
|
5658
5738
|
review: review2
|
|
5659
5739
|
} = useWizard();
|
|
5660
5740
|
const { exit } = useApp();
|
|
@@ -5670,7 +5750,7 @@ function App() {
|
|
|
5670
5750
|
const isCommandApprovalPrompt = isAwaitingUserInput && inputReq?.promptType === "commandApproval";
|
|
5671
5751
|
const promptPending = isAwaitingUserInput && !isCommandApprovalPrompt;
|
|
5672
5752
|
const holdForTip = stepHasTips && promptPending && tipState === "revealing";
|
|
5673
|
-
const showTips = stepHasTips && (phase === "running" || isCommandApprovalPrompt || holdForTip);
|
|
5753
|
+
const showTips = stepHasTips && (phase === "running" && currentStep?.status === "running" || isCommandApprovalPrompt || holdForTip);
|
|
5674
5754
|
const showNoticesInMain = !stepHasTips;
|
|
5675
5755
|
const showNotices = (!isAwaitingUserInput || holdForTip) && !review2;
|
|
5676
5756
|
useInput7(
|
|
@@ -5741,20 +5821,26 @@ function App() {
|
|
|
5741
5821
|
children: [
|
|
5742
5822
|
/* @__PURE__ */ jsxs18(Box20, { flexGrow: 2, flexDirection: "column", children: [
|
|
5743
5823
|
phase === "preflight" && !user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
|
|
5744
|
-
/* @__PURE__ */ jsx18(
|
|
5824
|
+
/* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
|
|
5745
5825
|
" Signing in to Algolia"
|
|
5746
5826
|
] }) }),
|
|
5747
5827
|
phase === "preflight" && user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
|
|
5748
|
-
/* @__PURE__ */ jsx18(
|
|
5828
|
+
/* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
|
|
5749
5829
|
" Getting things ready"
|
|
5750
5830
|
] }) }),
|
|
5751
5831
|
phase === "authenticating" && /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
|
|
5752
5832
|
/* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
|
|
5753
|
-
/* @__PURE__ */ jsx18(
|
|
5833
|
+
/* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
|
|
5754
5834
|
" Signing in to Algolia"
|
|
5755
5835
|
] }),
|
|
5756
5836
|
/* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
|
|
5757
5837
|
] }),
|
|
5838
|
+
settingUpAppId && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
|
|
5839
|
+
/* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
|
|
5840
|
+
" Setting up Wizard using app",
|
|
5841
|
+
" ",
|
|
5842
|
+
settingUpAppId
|
|
5843
|
+
] }) }),
|
|
5758
5844
|
/* @__PURE__ */ jsx18(CliOutput, {}),
|
|
5759
5845
|
showTips && currentStep && /* @__PURE__ */ jsx18(
|
|
5760
5846
|
Tips,
|
|
@@ -5825,54 +5911,71 @@ function readValue(raw) {
|
|
|
5825
5911
|
}
|
|
5826
5912
|
|
|
5827
5913
|
// src/lib/algoliaAppPicker.ts
|
|
5828
|
-
function
|
|
5914
|
+
function blockReasonFor(app) {
|
|
5915
|
+
return app.status !== "active" ? "Paused" : "Missing permissions";
|
|
5916
|
+
}
|
|
5917
|
+
function secondaryFor(app, highlightId) {
|
|
5918
|
+
if (!canSelectApplication(app)) {
|
|
5919
|
+
return { kind: "text", value: blockReasonFor(app) };
|
|
5920
|
+
}
|
|
5921
|
+
if (app.id === highlightId) {
|
|
5922
|
+
return { kind: "badge", value: "[DETECTED]" };
|
|
5923
|
+
}
|
|
5829
5924
|
return app.plan ? { kind: "badge", value: app.plan } : void 0;
|
|
5830
5925
|
}
|
|
5831
5926
|
function labelFor(app) {
|
|
5832
5927
|
return app.name.trim() ? `${app.name} \u2014 ${app.id}` : app.id;
|
|
5833
5928
|
}
|
|
5834
|
-
function selectAndReport(
|
|
5835
|
-
useWizard.getState()
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5929
|
+
async function selectAndReport(id) {
|
|
5930
|
+
const store = useWizard.getState();
|
|
5931
|
+
store.setSettingUpApp(id);
|
|
5932
|
+
try {
|
|
5933
|
+
return await selectApplication(id);
|
|
5934
|
+
} finally {
|
|
5935
|
+
store.setSettingUpApp(null);
|
|
5936
|
+
}
|
|
5840
5937
|
}
|
|
5841
|
-
async function promptForApplication(
|
|
5938
|
+
async function promptForApplication(highlight) {
|
|
5842
5939
|
const store = useWizard.getState();
|
|
5843
|
-
const
|
|
5844
|
-
if (
|
|
5940
|
+
const unordered = await listApplications();
|
|
5941
|
+
if (unordered.length === 0) {
|
|
5845
5942
|
throw new Error(
|
|
5846
5943
|
"This Algolia account has no applications. Create one in the Algolia dashboard, or with `npx @algolia/cli@latest application create`, then restart the wizard."
|
|
5847
5944
|
);
|
|
5848
5945
|
}
|
|
5849
|
-
if (
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
{ app: only.id },
|
|
5853
|
-
"single application on the account; selecting it"
|
|
5946
|
+
if (!unordered.some(canSelectApplication)) {
|
|
5947
|
+
throw new Error(
|
|
5948
|
+
"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."
|
|
5854
5949
|
);
|
|
5855
|
-
for (const line of leadIn) store.pushCliOutput("stdout", line);
|
|
5856
|
-
return selectAndReport(only);
|
|
5857
5950
|
}
|
|
5858
|
-
const
|
|
5859
|
-
...
|
|
5860
|
-
|
|
5951
|
+
const apps = [
|
|
5952
|
+
...unordered.filter(canSelectApplication),
|
|
5953
|
+
...unordered.filter((app) => !canSelectApplication(app))
|
|
5861
5954
|
];
|
|
5955
|
+
const envApp = highlight ? unordered.find((app) => app.id === highlight.id) : void 0;
|
|
5956
|
+
const highlightIndex = envApp && canSelectApplication(envApp) ? apps.indexOf(envApp) : -1;
|
|
5957
|
+
const messages = [];
|
|
5958
|
+
if (highlight && highlightIndex < 0) {
|
|
5959
|
+
messages.push(
|
|
5960
|
+
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.`
|
|
5961
|
+
);
|
|
5962
|
+
}
|
|
5862
5963
|
for (; ; ) {
|
|
5863
5964
|
const choice = await store.requestUserInput({
|
|
5864
|
-
prompt: "
|
|
5965
|
+
prompt: "Which Algolia application should the wizard work in?",
|
|
5865
5966
|
promptType: "multipleChoice",
|
|
5866
5967
|
options: apps.map(labelFor),
|
|
5867
|
-
secondary: apps.map(secondaryFor),
|
|
5968
|
+
secondary: apps.map((app) => secondaryFor(app, highlight?.id)),
|
|
5969
|
+
disabled: apps.map((app) => !canSelectApplication(app)),
|
|
5970
|
+
...highlightIndex >= 0 ? { defaultSelectedIndex: highlightIndex } : {},
|
|
5868
5971
|
messages
|
|
5869
5972
|
});
|
|
5870
5973
|
const chosen = apps.find((app) => labelFor(app) === choice);
|
|
5871
|
-
if (!chosen) {
|
|
5974
|
+
if (!chosen || !canSelectApplication(chosen)) {
|
|
5872
5975
|
throw new Error("Application picker received an unexpected selection");
|
|
5873
5976
|
}
|
|
5874
5977
|
try {
|
|
5875
|
-
return await selectAndReport(chosen);
|
|
5978
|
+
return await selectAndReport(chosen.id);
|
|
5876
5979
|
} catch (err) {
|
|
5877
5980
|
logger.warn(
|
|
5878
5981
|
{ app: chosen.id, err: err.message },
|
|
@@ -5884,42 +5987,11 @@ async function promptForApplication(leadIn = []) {
|
|
|
5884
5987
|
}
|
|
5885
5988
|
}
|
|
5886
5989
|
}
|
|
5887
|
-
async function
|
|
5888
|
-
|
|
5889
|
-
const choice = await useWizard.getState().requestUserInput({
|
|
5890
|
-
prompt: "Select an application",
|
|
5891
|
-
promptType: "multipleChoice",
|
|
5892
|
-
options: [
|
|
5893
|
-
useEnv,
|
|
5894
|
-
current ? `Use ${labelFor(current)} (already selected)` : "Pick a different application"
|
|
5895
|
-
],
|
|
5896
|
-
messages: [
|
|
5897
|
-
`${env.file} already sets ${env.name}=${env.id}.`,
|
|
5898
|
-
"Which Algolia application should the wizard work in?"
|
|
5899
|
-
]
|
|
5900
|
-
});
|
|
5901
|
-
return choice === useEnv;
|
|
5902
|
-
}
|
|
5903
|
-
async function selectEnvApplication(env) {
|
|
5904
|
-
try {
|
|
5905
|
-
return await selectAndReport({ id: env.id, name: "" });
|
|
5906
|
-
} catch (err) {
|
|
5907
|
-
logger.warn(
|
|
5908
|
-
{ app: env.id, err: err.message },
|
|
5909
|
-
"could not select the application named in env; falling back to the picker"
|
|
5910
|
-
);
|
|
5911
|
-
return promptForApplication([
|
|
5912
|
-
`Could not select ${env.id} from ${env.file} \u2014 it may have been removed, or this account may not have access to it.`
|
|
5913
|
-
]);
|
|
5914
|
-
}
|
|
5915
|
-
}
|
|
5916
|
-
async function ensureApplication() {
|
|
5917
|
-
const current = await currentApplication();
|
|
5990
|
+
async function ensureApplication(resumeAppId) {
|
|
5991
|
+
if (resumeAppId) return selectAndReport(resumeAppId);
|
|
5918
5992
|
const env = await findEnvApplicationId();
|
|
5919
|
-
if (env
|
|
5920
|
-
|
|
5921
|
-
}
|
|
5922
|
-
return current ?? await promptForApplication();
|
|
5993
|
+
if (!env) return promptForApplication();
|
|
5994
|
+
return promptForApplication({ id: env.id, file: env.file });
|
|
5923
5995
|
}
|
|
5924
5996
|
|
|
5925
5997
|
// src/lib/seed.ts
|
|
@@ -6283,14 +6355,17 @@ async function run(workflow) {
|
|
|
6283
6355
|
}
|
|
6284
6356
|
store.setUser(user);
|
|
6285
6357
|
let app;
|
|
6358
|
+
const resumableState = await loadResumableState(workflow);
|
|
6286
6359
|
try {
|
|
6287
|
-
app = await ensureApplication(
|
|
6360
|
+
app = await ensureApplication(
|
|
6361
|
+
resumableState ? runAppId(resumableState) : void 0
|
|
6362
|
+
);
|
|
6288
6363
|
} catch (err) {
|
|
6289
6364
|
store.setError(err instanceof Error ? err.message : String(err));
|
|
6290
6365
|
await instance.waitUntilExit();
|
|
6291
6366
|
process.exit(1);
|
|
6292
6367
|
}
|
|
6293
|
-
runWorkflow(workflow, app.id);
|
|
6368
|
+
runWorkflow(workflow, app.id, resumableState);
|
|
6294
6369
|
}
|
|
6295
6370
|
await requestTerminalSize();
|
|
6296
6371
|
var started = await startup();
|