Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create error categorization framework #23511

Closed
Tracked by #23510
yannbf opened this issue Jul 19, 2023 · 0 comments · Fixed by #23653
Closed
Tracked by #23510

Create error categorization framework #23511

yannbf opened this issue Jul 19, 2023 · 0 comments · Fixed by #23653
Assignees

Comments

@yannbf
Copy link
Member

yannbf commented Jul 19, 2023

There will be categories of errors (which will grow over time) and a base error class, which will hold metadata such as category, code and message. This will be useful when going through these errors in telemetry:

enum Category {
  INIT = 'I',
  RUNTIME = 'R',
  COMPILE = 'C',
  // ... and many more
}

// StorybookError, to keep metadata in its object which can be 
class StorybookError extends Error {
  constructor(public category: Category, public code: string, message: string) {
    super(message);
  }
}

Errors would all be objects created via a factory function, which could take care of message formatting, would provide a flag to send telemetry, a flag for documentation, and could be used to display warnings without having to instantiate errors:

function create<T, C extends string>({
  category,
  code,
  template,
  documentation,
  telemetry,
}: {
  category: Category;
  code: C;
  template(data: T): string;
  // either true or a link to a specific documentation
  documentation?: boolean | string;
  telemetry?: boolean;
}): {
  code: C;
  error: (data: T) => StorybookError;
  message: (data: T) => string;
} {
  const page =
    documentation === true
      ? `https://storybook.js.org/error/${code}`
      : typeof documentation === 'string'
      ? documentation
      : undefined;
  const message = documentation
    ? (data: T) =>
        `SB_${category}_${code} - ${template(data)}\n\nMore info: ${page}`
    : (data: T) => `SB_${category}_${code} - ${template(data)}`

  const error = (data: T) => {
    // telemetry would be injected globally and accessed to send errors if needed
    if (telemetry && globalThis.telemetry) {
      globalThis.telemetry({ code, category, data, message: message(data) });
    }
    return new StorybookError(category, code, message(data));
  };
  return { code, error, message };
}

Example of the creation of errors:

// --- definition --- //

export const INSTALL_FAILURE = create({
  category: Category.INIT,
  code: '0001',
  // if linked is true, append code in sb errors page
  linked: true,
  template: ({ reason }: { reason: string }) =>
    `Failed to install: ${reason}`,
});

export const MISSING_MAIN_JS = create({
  category: Category.COMPILE,
  code: '0001',
  // if linked is a string, use it instead of the default /error/<code> url
  linked: 'https://storybook.js.org/docs/faq#common-issue-and-how-to-solve-it',
  template: ({ location }: { location: string }) =>
    `Missing main.js file at ${location}`,
});

Example of usage:

// --- usage --- //

if ('we detected a problem, ow no!') {
  // can be used in warning messages without having to instantiate the error
  const foo = INSTALL_FAILURE.error({ reason: 'Unsupported Vite version.' });

  // Failed to install: Unsupported Vite version. More info https://storybook.js.org/error/I0001
  console.warn(foo.message);
}

if ('we detected a problem, ow no!') {
  // Missing main.js file at xyz. More info https://storybook.js.org/docs/faq#common-issue-and-how-to-solve-it
  throw MISSING_MAIN_JS.error({
    location: 'main.js',
  });
}

Prototype

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

1 participant