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/index.d.ts CHANGED
@@ -189,6 +189,7 @@ interface WizardConfig {
189
189
  version?: string;
190
190
  description?: string;
191
191
  review?: boolean;
192
+ icon?: string;
192
193
  };
193
194
  theme?: ThemeConfig;
194
195
  steps: StepConfig[];
@@ -440,6 +441,7 @@ interface RunWizardOptions {
440
441
  mru?: boolean;
441
442
  resume?: boolean;
442
443
  configFilePath?: string;
444
+ optionsProvider?: (stepId: string, answers: Record<string, unknown>) => Promise<SelectOption[] | undefined>;
443
445
  }
444
446
  declare function runPreFlightChecks(checks: PreFlightCheck[], theme: ResolvedTheme, renderer?: WizardRenderer): void;
445
447
  declare function runWizard(config: WizardConfig, options?: RunWizardOptions): Promise<Record<string, unknown>>;
@@ -482,6 +484,7 @@ declare function resolveTemplateStrict(template: string, answers: Record<string,
482
484
  */
483
485
  declare function renderBanner(name: string, theme: ResolvedTheme, options?: {
484
486
  plain?: boolean;
487
+ icon?: string;
485
488
  }): string;
486
489
 
487
490
  declare function slugify(name: string): string;
package/dist/index.js CHANGED
@@ -242,7 +242,8 @@ var init_schema = __esm({
242
242
  name: z.string(),
243
243
  version: z.string().optional(),
244
244
  description: z.string().optional(),
245
- review: z.boolean().optional()
245
+ review: z.boolean().optional(),
246
+ icon: z.string().optional()
246
247
  }),
247
248
  theme: themeConfigSchema.optional(),
248
249
  steps: z.array(stepConfigSchema).min(1),
@@ -1188,8 +1189,10 @@ import figlet from "figlet";
1188
1189
  import gradient from "gradient-string";
1189
1190
  var GRIMOIRE_GRADIENT = gradient(["#C084FC", "#5B9BD5", "#6BCB77"]);
1190
1191
  function renderBanner(name, theme, options) {
1192
+ const icon = options?.icon;
1193
+ const prefix = icon ? `${icon} ` : "";
1191
1194
  if (options?.plain) {
1192
- return ` ${theme.bold(name)}`;
1195
+ return ` ${prefix}${theme.bold(name)}`;
1193
1196
  }
1194
1197
  try {
1195
1198
  const art = figlet.textSync(name, {
@@ -1197,9 +1200,11 @@ function renderBanner(name, theme, options) {
1197
1200
  horizontalLayout: "default"
1198
1201
  });
1199
1202
  const lines = art.split("\n").map((line) => ` ${line}`).join("\n");
1200
- return GRIMOIRE_GRADIENT(lines);
1203
+ const banner = GRIMOIRE_GRADIENT(lines);
1204
+ return icon ? ` ${icon}
1205
+ ${banner}` : banner;
1201
1206
  } catch {
1202
- return ` ${theme.bold(name)}`;
1207
+ return ` ${prefix}${theme.bold(name)}`;
1203
1208
  }
1204
1209
  }
1205
1210
 
@@ -1441,11 +1446,14 @@ function emitEvent(renderer, event, theme) {
1441
1446
  function runPreFlightChecks(checks, theme, renderer) {
1442
1447
  if (renderer) emitEvent(renderer, { type: "checks:start", checks }, theme);
1443
1448
  for (const check of checks) {
1449
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: check.name }, theme);
1444
1450
  try {
1445
1451
  execSync(check.run, { stdio: "pipe" });
1452
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: `${check.name}` }, theme);
1446
1453
  console.log(` ${theme.success("\u2713")} ${check.name}`);
1447
1454
  if (renderer) emitEvent(renderer, { type: "check:pass", name: check.name }, theme);
1448
1455
  } catch {
1456
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1449
1457
  console.log(` ${theme.error("\u2717")} ${check.name}: ${check.message}`);
1450
1458
  if (renderer) emitEvent(renderer, { type: "check:fail", name: check.name, message: check.message }, theme);
1451
1459
  throw new Error(`Pre-flight check failed: ${check.name} \u2014 ${check.message}`);
@@ -1565,8 +1573,17 @@ async function runWizard(config, options) {
1565
1573
  const withTemplate = options?.templateAnswers ? applyTemplateDefaults(resolvedStep, options.templateAnswers) : resolvedStep;
1566
1574
  const templatedStep = resolveStepTemplates(withTemplate, state.answers);
1567
1575
  const mruStep = mruEnabled ? applyMruOrdering(templatedStep, config.meta.name) : templatedStep;
1576
+ let finalStep = mruStep;
1577
+ if (!isMock && options?.optionsProvider && isSelectLikeStep(currentStep.type)) {
1578
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: resolvedMessage }, theme);
1579
+ const dynamicOptions = await options.optionsProvider(currentStep.id, state.answers);
1580
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: resolvedMessage }, theme);
1581
+ if (dynamicOptions) {
1582
+ finalStep = { ...mruStep, options: dynamicOptions };
1583
+ }
1584
+ }
1568
1585
  try {
1569
- const value = isMock ? getMockValue(mruStep, mockAnswers) : pluginStep ? await pluginStep.render(toStepRecord(mruStep), state, theme) : await renderStep(renderer, mruStep, state, theme);
1586
+ const value = isMock ? getMockValue(finalStep, mockAnswers) : pluginStep ? await pluginStep.render(toStepRecord(finalStep), state, theme) : await renderStep(renderer, finalStep, state, theme);
1570
1587
  if (pluginStep?.validate) {
1571
1588
  const pluginError = pluginStep.validate(value, toStepRecord(templatedStep));
1572
1589
  if (pluginError) {
@@ -1905,6 +1922,7 @@ function resolveStepTemplates(step, answers) {
1905
1922
  }
1906
1923
  async function executeOnComplete(handlerPath, configFilePath, answers, config, theme, renderer) {
1907
1924
  if (renderer) emitEvent(renderer, { type: "oncomplete:start" }, theme);
1925
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: `Running onComplete handler...` }, theme);
1908
1926
  const resolvedPath = configFilePath ? resolve2(dirname2(configFilePath), handlerPath) : resolve2(handlerPath);
1909
1927
  try {
1910
1928
  const mod = await import(pathToFileURL(resolvedPath).href);
@@ -1912,9 +1930,11 @@ async function executeOnComplete(handlerPath, configFilePath, answers, config, t
1912
1930
  throw new Error(`onComplete handler "${handlerPath}" must export a default function`);
1913
1931
  }
1914
1932
  await mod.default({ answers, config });
1933
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: "Handler complete" }, theme);
1915
1934
  if (renderer) emitEvent(renderer, { type: "oncomplete:pass" }, theme);
1916
1935
  } catch (error) {
1917
1936
  const message = error instanceof Error ? error.message : String(error);
1937
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1918
1938
  if (renderer) emitEvent(renderer, { type: "oncomplete:fail", error: message }, theme);
1919
1939
  console.log(`
1920
1940
  ${theme.error("\u2717")} onComplete handler failed: ${message}
@@ -1934,11 +1954,14 @@ async function executeActions(actions, answers, theme, renderer) {
1934
1954
  const resolvedCommand = resolveTemplateStrict(action.run, answers);
1935
1955
  const resolvedName = action.name ? resolveTemplateStrict(action.name, answers) : void 0;
1936
1956
  const label = resolvedName ?? resolvedCommand;
1957
+ if (renderer) emitEvent(renderer, { type: "spinner:start", message: label }, theme);
1937
1958
  try {
1938
1959
  execSync(resolvedCommand, { stdio: "pipe" });
1960
+ if (renderer) emitEvent(renderer, { type: "spinner:stop", message: label }, theme);
1939
1961
  console.log(` ${theme.success("\u2713")} ${label}`);
1940
1962
  if (renderer) emitEvent(renderer, { type: "action:pass", name: label }, theme);
1941
1963
  } catch {
1964
+ if (renderer) emitEvent(renderer, { type: "spinner:stop" }, theme);
1942
1965
  console.log(` ${theme.error("\u2717")} ${label}`);
1943
1966
  if (renderer) emitEvent(renderer, { type: "action:fail", name: label }, theme);
1944
1967
  throw new Error(`Action failed: ${label}`);
@@ -1948,7 +1971,7 @@ async function executeActions(actions, answers, theme, renderer) {
1948
1971
  }
1949
1972
  function printWizardHeader(config, theme, plain) {
1950
1973
  console.log();
1951
- console.log(renderBanner(config.meta.name, theme, { plain }));
1974
+ console.log(renderBanner(config.meta.name, theme, { plain, icon: config.meta.icon }));
1952
1975
  if (config.meta.description) {
1953
1976
  console.log(` ${theme.muted(config.meta.description)}`);
1954
1977
  }