feat(workflow-utils): add withDryRun role wrapper #254

Closed
opened 2026-04-29 12:55:53 +00:00 by xiaoju · 0 comments
Owner

What

Extract the repeated dry-run + error-handling pattern into a reusable withDryRun wrapper in @uncaged/nerve-workflow-utils.

Current pattern (repeated 3+ times in workspace)

return async (start, messages) => {
  if (isDryRun(start)) {
    return { content: "[dry-run] committer skipped", meta: { committed: true } };
  }
  try {
    return await innerRole(start, messages);
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    return { content: `committer failed: ${msg}`, meta: { committed: false } };
  }
};

Proposed API

// packages/workflow-utils/src/with-dry-run.ts

export type WithDryRunOptions<M> = {
  label: string;              // e.g. "committer", "publish" — used in skip/fail messages
  dryRunMeta: M;              // meta to return when dry-run (e.g. { committed: true })
  failMeta: M;                // meta to return on error (e.g. { committed: false })
};

export function withDryRun<M extends Record<string, unknown>>(
  role: Role<M>,
  opts: WithDryRunOptions<M>,
): Role<M> {
  return async (start, messages) => {
    if (isDryRun(start)) {
      return {
        content: `[dry-run] ${opts.label} skipped`,
        meta: opts.dryRunMeta,
      };
    }
    try {
      return await role(start, messages);
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      return {
        content: `${opts.label} failed: ${msg}`,
        meta: opts.failMeta,
      };
    }
  };
}

Export from packages/workflow-utils/src/index.ts.

Usage (in workspace, after this lands)

export function createWorkspaceCommitterRole(adapter, extract) {
  const inner = createRole(adapter, prompt, committerMetaSchema, extract);
  return withDryRun(inner, {
    label: "committer",
    dryRunMeta: { committed: true },
    failMeta: { committed: false },
  });
}

Scope

  • packages/workflow-utils/src/with-dry-run.ts — new file
  • packages/workflow-utils/src/index.ts — export it
  • Add a basic test if test infra exists
  • pnpm build must pass
## What Extract the repeated dry-run + error-handling pattern into a reusable `withDryRun` wrapper in `@uncaged/nerve-workflow-utils`. ## Current pattern (repeated 3+ times in workspace) ```ts return async (start, messages) => { if (isDryRun(start)) { return { content: "[dry-run] committer skipped", meta: { committed: true } }; } try { return await innerRole(start, messages); } catch (e) { const msg = e instanceof Error ? e.message : String(e); return { content: `committer failed: ${msg}`, meta: { committed: false } }; } }; ``` ## Proposed API ```ts // packages/workflow-utils/src/with-dry-run.ts export type WithDryRunOptions<M> = { label: string; // e.g. "committer", "publish" — used in skip/fail messages dryRunMeta: M; // meta to return when dry-run (e.g. { committed: true }) failMeta: M; // meta to return on error (e.g. { committed: false }) }; export function withDryRun<M extends Record<string, unknown>>( role: Role<M>, opts: WithDryRunOptions<M>, ): Role<M> { return async (start, messages) => { if (isDryRun(start)) { return { content: `[dry-run] ${opts.label} skipped`, meta: opts.dryRunMeta, }; } try { return await role(start, messages); } catch (e) { const msg = e instanceof Error ? e.message : String(e); return { content: `${opts.label} failed: ${msg}`, meta: opts.failMeta, }; } }; } ``` Export from `packages/workflow-utils/src/index.ts`. ## Usage (in workspace, after this lands) ```ts export function createWorkspaceCommitterRole(adapter, extract) { const inner = createRole(adapter, prompt, committerMetaSchema, extract); return withDryRun(inner, { label: "committer", dryRunMeta: { committed: true }, failMeta: { committed: false }, }); } ``` ## Scope - `packages/workflow-utils/src/with-dry-run.ts` — new file - `packages/workflow-utils/src/index.ts` — export it - Add a basic test if test infra exists - `pnpm build` must pass
This repo is archived. You cannot comment on issues.
No Label
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/nerve#254