From c5f8af5449ad7bafcef078c065c6eef599a9ea73 Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Fri, 13 Dec 2024 12:24:06 +0800 Subject: [PATCH 1/5] add `isStorybookSvelteCSFError` util & use it inside indexer parser --- src/indexer/index.ts | 6 ++++++ src/utils/error.ts | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/indexer/index.ts b/src/indexer/index.ts index 60d5f29..e9fb7d0 100644 --- a/src/indexer/index.ts +++ b/src/indexer/index.ts @@ -9,6 +9,7 @@ import { } from '#utils/error/parser/extract/svelte'; import { LegacyTemplateNotEnabledError } from '#utils/error/legacy-api/index'; import { NoDestructuredDefineMetaCallError } from '#utils/error/parser/analyse/define-meta'; +import { isStorybookSvelteCSFError } from '#utils/error'; export const createIndexer = (legacyTemplate: boolean): Indexer => ({ test: /\.svelte$/, @@ -39,6 +40,11 @@ export const createIndexer = (legacyTemplate: boolean): Indexer => ({ throw new LegacyTemplateNotEnabledError(filename); } + // WARN: We can't use instance of `StorybookSvelteCSFError`, because is an _abstract_ class :sob: + if (isStorybookSvelteCSFError(error)) { + throw error; + } + throw new IndexerParseError(); } }, diff --git a/src/utils/error.ts b/src/utils/error.ts index 7779915..c24b408 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -80,7 +80,7 @@ export abstract class StorybookSvelteCSFError extends Error { * Generates the error message along with additional documentation link (if applicable). */ get message() { - if(this.customMessage) { + if (this.customMessage) { return this.customMessage; } @@ -178,3 +178,18 @@ export abstract class StorybookSvelteCSFError extends Error { return ``; } } + +// WARN: We can't use instance of `StorybookSvelteCSFError`, because is an _abstract_ class :sob: +export function isStorybookSvelteCSFError(error: unknown) { + if (typeof error !== 'object' || error === null) { + return false; + } + + for (const key of ['category', 'code', 'data', 'documentation', 'fullErrorCode', 'template']) { + if (!Object.hasOwn(error, key)) { + return false; + } + } + + return true; +} From 3b5e794c033191938818a667bcbec6eb3f3a6092 Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Fri, 13 Dec 2024 18:16:53 +0800 Subject: [PATCH 2/5] check for the existence of a static property in the prototype --- src/utils/error.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/utils/error.ts b/src/utils/error.ts index c24b408..6408aad 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -10,6 +10,7 @@ import type { SvelteAST } from '#parser/ast'; * and modified for this addon needs. */ export abstract class StorybookSvelteCSFError extends Error { + public static isStorybookCSFSvelteError = true; public static packageName = pkg.name; public static packageVersion = pkg.version; @@ -179,17 +180,10 @@ export abstract class StorybookSvelteCSFError extends Error { } } -// WARN: We can't use instance of `StorybookSvelteCSFError`, because is an _abstract_ class :sob: -export function isStorybookSvelteCSFError(error: unknown) { - if (typeof error !== 'object' || error === null) { - return false; - } - - for (const key of ['category', 'code', 'data', 'documentation', 'fullErrorCode', 'template']) { - if (!Object.hasOwn(error, key)) { - return false; - } - } - - return true; +// WARN: We can't use `instanceof StorybookSvelteCSFError`, because is an _abstract_ class +export function isStorybookSvelteCSFError(error: unknown): error is StorybookSvelteCSFError { + return Boolean( + (Object.getPrototypeOf(error)?.constructor as typeof StorybookSvelteCSFError) + ?.isStorybookCSFSvelteError + ); } From f2dbec30125669fbbb5f34cfc9feffa66e4eb00e Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Fri, 13 Dec 2024 21:12:56 +0800 Subject: [PATCH 3/5] Tweak to add ability of passing `ErrorOptions` and pass cause to `IndexerParseError` throw --- src/indexer/index.ts | 8 +++++--- src/utils/error.ts | 19 +++++++++++-------- src/utils/error/parser/extract/svelte.ts | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/indexer/index.ts b/src/indexer/index.ts index e9fb7d0..f897a4e 100644 --- a/src/indexer/index.ts +++ b/src/indexer/index.ts @@ -15,7 +15,9 @@ export const createIndexer = (legacyTemplate: boolean): Indexer => ({ test: /\.svelte$/, createIndex: async (filename, { makeTitle }) => { try { - const { meta, stories } = await parseForIndexer(filename, { legacyTemplate }); + const { meta, stories } = await parseForIndexer(filename, { + legacyTemplate, + }); return stories.map((story) => { return { @@ -40,12 +42,12 @@ export const createIndexer = (legacyTemplate: boolean): Indexer => ({ throw new LegacyTemplateNotEnabledError(filename); } - // WARN: We can't use instance of `StorybookSvelteCSFError`, because is an _abstract_ class :sob: + // WARN: We can't use `instanceof StorybookSvelteCSFError`, because is an _abstract_ class if (isStorybookSvelteCSFError(error)) { throw error; } - throw new IndexerParseError(); + throw new IndexerParseError({ cause: error }); } }, }); diff --git a/src/utils/error.ts b/src/utils/error.ts index 6408aad..f3cf847 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -116,14 +116,17 @@ export abstract class StorybookSvelteCSFError extends Error { */ readonly component?: SvelteAST.Component; - constructor({ - filename, - component: component, - }: { - filename?: StorybookSvelteCSFError['filename']; - component?: StorybookSvelteCSFError['component']; - }) { - super(); + constructor( + { + filename, + component: component, + }: { + filename?: StorybookSvelteCSFError['filename']; + component?: StorybookSvelteCSFError['component']; + }, + options?: ConstructorParameters[1] + ) { + super('', options); this.filename = filename; this.component = component; diff --git a/src/utils/error/parser/extract/svelte.ts b/src/utils/error/parser/extract/svelte.ts index bf1650f..47f09bb 100644 --- a/src/utils/error/parser/extract/svelte.ts +++ b/src/utils/error/parser/extract/svelte.ts @@ -218,8 +218,8 @@ export class IndexerParseError extends StorybookSvelteCSFError { readonly code = 9; public documentation = true; - constructor() { - super({}); + constructor(options?: ConstructorParameters[1]) { + super({}, options); } template() { From 9c4d33c10d7030bec367a5086e26250392a7a540 Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Fri, 13 Dec 2024 21:17:36 +0800 Subject: [PATCH 4/5] Fix message override from `super()` --- src/utils/error.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/error.ts b/src/utils/error.ts index f3cf847..d145ef7 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -126,8 +126,8 @@ export abstract class StorybookSvelteCSFError extends Error { }, options?: ConstructorParameters[1] ) { - super('', options); - + super(); + this.cause = options?.cause; this.filename = filename; this.component = component; } From 541b6061ee7bf0d74c0d1df6dfabb69cd0b09f6b Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Fri, 13 Dec 2024 23:36:57 +0800 Subject: [PATCH 5/5] apply feedback --- src/indexer/index.ts | 2 +- src/utils/error/legacy-api/index.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/indexer/index.ts b/src/indexer/index.ts index f897a4e..9913260 100644 --- a/src/indexer/index.ts +++ b/src/indexer/index.ts @@ -39,7 +39,7 @@ export const createIndexer = (legacyTemplate: boolean): Indexer => ({ error instanceof GetDefineMetaFirstArgumentError ) { const { filename } = error; - throw new LegacyTemplateNotEnabledError(filename); + throw new LegacyTemplateNotEnabledError(filename, { cause: error }); } // WARN: We can't use `instanceof StorybookSvelteCSFError`, because is an _abstract_ class diff --git a/src/utils/error/legacy-api/index.ts b/src/utils/error/legacy-api/index.ts index b678346..34a9a6e 100644 --- a/src/utils/error/legacy-api/index.ts +++ b/src/utils/error/legacy-api/index.ts @@ -36,8 +36,9 @@ export class LegacyTemplateNotEnabledError extends StorybookSvelteCSFError { readonly code = 2; public documentation = true; - constructor(filename?: string) { + constructor(filename?: string, options?: ConstructorParameters[1]) { super({ filename }); + this.cause = options?.cause; } template(): string {