grimoire-wizard 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -208,7 +208,8 @@ var wizardConfigSchema = z.object({
208
208
  name: z.string(),
209
209
  version: z.string().optional(),
210
210
  description: z.string().optional(),
211
- review: z.boolean().optional()
211
+ review: z.boolean().optional(),
212
+ icon: z.string().optional()
212
213
  }),
213
214
  theme: themeConfigSchema.optional(),
214
215
  steps: z.array(stepConfigSchema).min(1),
@@ -1141,8 +1142,10 @@ import figlet from "figlet";
1141
1142
  import gradient from "gradient-string";
1142
1143
  var GRIMOIRE_GRADIENT = gradient(["#C084FC", "#5B9BD5", "#6BCB77"]);
1143
1144
  function renderBanner(name, theme, options) {
1145
+ const icon = options?.icon;
1146
+ const prefix = icon ? `${icon} ` : "";
1144
1147
  if (options?.plain) {
1145
- return ` ${theme.bold(name)}`;
1148
+ return ` ${prefix}${theme.bold(name)}`;
1146
1149
  }
1147
1150
  try {
1148
1151
  const art = figlet.textSync(name, {
@@ -1150,9 +1153,11 @@ function renderBanner(name, theme, options) {
1150
1153
  horizontalLayout: "default"
1151
1154
  });
1152
1155
  const lines = art.split("\n").map((line) => ` ${line}`).join("\n");
1153
- return GRIMOIRE_GRADIENT(lines);
1156
+ const banner = GRIMOIRE_GRADIENT(lines);
1157
+ return icon ? ` ${icon}
1158
+ ${banner}` : banner;
1154
1159
  } catch {
1155
- return ` ${theme.bold(name)}`;
1160
+ return ` ${prefix}${theme.bold(name)}`;
1156
1161
  }
1157
1162
  }
1158
1163
 
@@ -1385,11 +1390,14 @@ function emitEvent(renderer, event, theme) {
1385
1390
  function runPreFlightChecks(checks, theme, renderer) {
1386
1391
  if (renderer) emitEvent(renderer, { type: "checks:start", checks }, theme);
1387
1392
  for (const check of checks) {
1393
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: check.name }, theme);
1388
1394
  try {
1389
1395
  execSync(check.run, { stdio: "pipe" });
1396
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: `${check.name}` }, theme);
1390
1397
  console.log(` ${theme.success("\u2713")} ${check.name}`);
1391
1398
  if (renderer) emitEvent(renderer, { type: "check:pass", name: check.name }, theme);
1392
1399
  } catch {
1400
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1393
1401
  console.log(` ${theme.error("\u2717")} ${check.name}: ${check.message}`);
1394
1402
  if (renderer) emitEvent(renderer, { type: "check:fail", name: check.name, message: check.message }, theme);
1395
1403
  throw new Error(`Pre-flight check failed: ${check.name} \u2014 ${check.message}`);
@@ -1509,8 +1517,17 @@ async function runWizard(config, options) {
1509
1517
  const withTemplate = options?.templateAnswers ? applyTemplateDefaults(resolvedStep, options.templateAnswers) : resolvedStep;
1510
1518
  const templatedStep = resolveStepTemplates(withTemplate, state.answers);
1511
1519
  const mruStep = mruEnabled ? applyMruOrdering(templatedStep, config.meta.name) : templatedStep;
1520
+ let finalStep = mruStep;
1521
+ if (!isMock && options?.optionsProvider && isSelectLikeStep(currentStep.type)) {
1522
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: resolvedMessage }, theme);
1523
+ const dynamicOptions = await options.optionsProvider(currentStep.id, state.answers);
1524
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: resolvedMessage }, theme);
1525
+ if (dynamicOptions) {
1526
+ finalStep = { ...mruStep, options: dynamicOptions };
1527
+ }
1528
+ }
1512
1529
  try {
1513
- const value = isMock ? getMockValue(mruStep, mockAnswers) : pluginStep ? await pluginStep.render(toStepRecord(mruStep), state, theme) : await renderStep(renderer, mruStep, state, theme);
1530
+ const value = isMock ? getMockValue(finalStep, mockAnswers) : pluginStep ? await pluginStep.render(toStepRecord(finalStep), state, theme) : await renderStep(renderer, finalStep, state, theme);
1514
1531
  if (pluginStep?.validate) {
1515
1532
  const pluginError = pluginStep.validate(value, toStepRecord(templatedStep));
1516
1533
  if (pluginError) {
@@ -1849,6 +1866,7 @@ function resolveStepTemplates(step, answers) {
1849
1866
  }
1850
1867
  async function executeOnComplete(handlerPath, configFilePath, answers, config, theme, renderer) {
1851
1868
  if (renderer) emitEvent(renderer, { type: "oncomplete:start" }, theme);
1869
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: `Running onComplete handler...` }, theme);
1852
1870
  const resolvedPath = configFilePath ? resolve2(dirname2(configFilePath), handlerPath) : resolve2(handlerPath);
1853
1871
  try {
1854
1872
  const mod = await import(pathToFileURL(resolvedPath).href);
@@ -1856,9 +1874,11 @@ async function executeOnComplete(handlerPath, configFilePath, answers, config, t
1856
1874
  throw new Error(`onComplete handler "${handlerPath}" must export a default function`);
1857
1875
  }
1858
1876
  await mod.default({ answers, config });
1877
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: "Handler complete" }, theme);
1859
1878
  if (renderer) emitEvent(renderer, { type: "oncomplete:pass" }, theme);
1860
1879
  } catch (error) {
1861
1880
  const message = error instanceof Error ? error.message : String(error);
1881
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1862
1882
  if (renderer) emitEvent(renderer, { type: "oncomplete:fail", error: message }, theme);
1863
1883
  console.log(`
1864
1884
  ${theme.error("\u2717")} onComplete handler failed: ${message}
@@ -1878,11 +1898,14 @@ async function executeActions(actions, answers, theme, renderer) {
1878
1898
  const resolvedCommand = resolveTemplateStrict(action.run, answers);
1879
1899
  const resolvedName = action.name ? resolveTemplateStrict(action.name, answers) : void 0;
1880
1900
  const label = resolvedName ?? resolvedCommand;
1901
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: label }, theme);
1881
1902
  try {
1882
1903
  execSync(resolvedCommand, { stdio: "pipe" });
1904
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: label }, theme);
1883
1905
  console.log(` ${theme.success("\u2713")} ${label}`);
1884
1906
  if (renderer) emitEvent(renderer, { type: "action:pass", name: label }, theme);
1885
1907
  } catch {
1908
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1886
1909
  console.log(` ${theme.error("\u2717")} ${label}`);
1887
1910
  if (renderer) emitEvent(renderer, { type: "action:fail", name: label }, theme);
1888
1911
  throw new Error(`Action failed: ${label}`);
@@ -1892,7 +1915,7 @@ async function executeActions(actions, answers, theme, renderer) {
1892
1915
  }
1893
1916
  function printWizardHeader(config, theme, plain) {
1894
1917
  console.log();
1895
- console.log(renderBanner(config.meta.name, theme, { plain }));
1918
+ console.log(renderBanner(config.meta.name, theme, { plain, icon: config.meta.icon }));
1896
1919
  if (config.meta.description) {
1897
1920
  console.log(` ${theme.muted(config.meta.description)}`);
1898
1921
  }