@dsai-io/tools 1.0.7 → 1.2.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.
@@ -11,6 +11,10 @@ interface DsaiConfig {
11
11
  tokens?: TokensConfig;
12
12
  /** Icon generation configuration */
13
13
  icons?: IconsConfig;
14
+ /** Path aliases for component installation */
15
+ aliases?: AliasesConfig;
16
+ /** Component distribution configuration */
17
+ components?: ComponentsConfig;
14
18
  /** Global settings */
15
19
  global?: GlobalConfig;
16
20
  }
@@ -638,6 +642,37 @@ interface IconsConfig {
638
642
  */
639
643
  prefix?: string;
640
644
  }
645
+ /**
646
+ * Path aliases for component installation.
647
+ * Controls where `dsai add` writes files in the consumer's project.
648
+ */
649
+ interface AliasesConfig {
650
+ /** Import alias prefix used in tsconfig paths (e.g., "@/", "~/", "@dsai/") @default '@/' */
651
+ importAlias?: string;
652
+ /** Where UI components are installed @default 'src/components/ui' */
653
+ ui?: string;
654
+ /** Where shared hooks are installed @default 'src/hooks' */
655
+ hooks?: string;
656
+ /** Where utility functions are installed @default 'src/lib/utils' */
657
+ utils?: string;
658
+ /** Where higher-level composed components go @default 'src/components' */
659
+ components?: string;
660
+ /** Where lib files go @default 'src/lib' */
661
+ lib?: string;
662
+ }
663
+ /**
664
+ * Configuration for component distribution (shadcn-style).
665
+ */
666
+ interface ComponentsConfig {
667
+ /** Enable component distribution features @default true */
668
+ enabled?: boolean;
669
+ /** Registry URL or local path @default 'https://registry.dsai.dev' */
670
+ registryUrl?: string;
671
+ /** Whether to use TypeScript (.tsx) or JavaScript (.jsx) @default true */
672
+ tsx?: boolean;
673
+ /** Overwrite existing files when adding components @default false */
674
+ overwrite?: boolean;
675
+ }
641
676
  /**
642
677
  * Resolved theme definition with all required fields
643
678
  */
@@ -731,6 +766,26 @@ interface ResolvedIconsConfig {
731
766
  optimize: boolean;
732
767
  prefix: string;
733
768
  }
769
+ /**
770
+ * Resolved aliases config with all defaults applied
771
+ */
772
+ interface ResolvedAliasesConfig {
773
+ importAlias: string;
774
+ ui: string;
775
+ hooks: string;
776
+ utils: string;
777
+ components: string;
778
+ lib: string;
779
+ }
780
+ /**
781
+ * Resolved components config with all defaults applied
782
+ */
783
+ interface ResolvedComponentsConfig {
784
+ enabled: boolean;
785
+ registryUrl: string;
786
+ tsx: boolean;
787
+ overwrite: boolean;
788
+ }
734
789
  /**
735
790
  * Resolved global config with all defaults applied
736
791
  */
@@ -745,6 +800,8 @@ interface ResolvedGlobalConfig {
745
800
  interface ResolvedConfig {
746
801
  tokens: ResolvedTokensConfig;
747
802
  icons: ResolvedIconsConfig;
803
+ aliases: ResolvedAliasesConfig;
804
+ components: ResolvedComponentsConfig;
748
805
  global: ResolvedGlobalConfig;
749
806
  /** Absolute path to config file (if loaded from file) */
750
807
  configPath?: string;
@@ -776,4 +833,4 @@ interface LoadConfigResult {
776
833
  warnings: string[];
777
834
  }
778
835
 
779
- export type { BuildSummary as B, CustomTransform as C, DsaiConfig as D, FrameworkTarget as F, GlobalConfig as G, IconsConfig as I, LoadConfigOptions as L, OutputFormat as O, Platform as P, ResolvedConfig as R, ScssOutputConfig as S, TokensConfig as T, ThemesConfig as a, ThemeDefinition as b, ThemeSelectorPattern as c, FrameworkMappingConfig as d, FrameworkMappingPattern as e, ResolvedGlobalConfig as f, ResolvedTokensConfig as g, ResolvedIconsConfig as h, ResolvedThemesConfig as i, ResolvedThemeDefinition as j, CustomFormat as k, CustomPreprocessor as l, CustomFilter as m, TokenData as n, TransformOptions as o, FormatArgs as p, Dictionary as q, FileConfig as r, LoadConfigResult as s, LogLevel as t, IconFramework as u };
836
+ export type { AliasesConfig as A, BuildSummary as B, ComponentsConfig as C, Dictionary as D, FileConfig as F, GlobalConfig as G, IconFramework as I, LoadConfigOptions as L, OutputFormat as O, Platform as P, ResolvedAliasesConfig as R, ScssOutputConfig as S, ThemeDefinition as T, ResolvedComponentsConfig as a, CustomFilter as b, CustomFormat as c, CustomPreprocessor as d, CustomTransform as e, DsaiConfig as f, FormatArgs as g, FrameworkMappingConfig as h, FrameworkMappingPattern as i, FrameworkTarget as j, IconsConfig as k, LoadConfigResult as l, LogLevel as m, ResolvedConfig as n, ResolvedGlobalConfig as o, ResolvedIconsConfig as p, ResolvedThemeDefinition as q, ResolvedThemesConfig as r, ResolvedTokensConfig as s, ThemeSelectorPattern as t, ThemesConfig as u, TokenData as v, TokensConfig as w, TransformOptions as x };
@@ -11,6 +11,10 @@ interface DsaiConfig {
11
11
  tokens?: TokensConfig;
12
12
  /** Icon generation configuration */
13
13
  icons?: IconsConfig;
14
+ /** Path aliases for component installation */
15
+ aliases?: AliasesConfig;
16
+ /** Component distribution configuration */
17
+ components?: ComponentsConfig;
14
18
  /** Global settings */
15
19
  global?: GlobalConfig;
16
20
  }
@@ -638,6 +642,37 @@ interface IconsConfig {
638
642
  */
639
643
  prefix?: string;
640
644
  }
645
+ /**
646
+ * Path aliases for component installation.
647
+ * Controls where `dsai add` writes files in the consumer's project.
648
+ */
649
+ interface AliasesConfig {
650
+ /** Import alias prefix used in tsconfig paths (e.g., "@/", "~/", "@dsai/") @default '@/' */
651
+ importAlias?: string;
652
+ /** Where UI components are installed @default 'src/components/ui' */
653
+ ui?: string;
654
+ /** Where shared hooks are installed @default 'src/hooks' */
655
+ hooks?: string;
656
+ /** Where utility functions are installed @default 'src/lib/utils' */
657
+ utils?: string;
658
+ /** Where higher-level composed components go @default 'src/components' */
659
+ components?: string;
660
+ /** Where lib files go @default 'src/lib' */
661
+ lib?: string;
662
+ }
663
+ /**
664
+ * Configuration for component distribution (shadcn-style).
665
+ */
666
+ interface ComponentsConfig {
667
+ /** Enable component distribution features @default true */
668
+ enabled?: boolean;
669
+ /** Registry URL or local path @default 'https://registry.dsai.dev' */
670
+ registryUrl?: string;
671
+ /** Whether to use TypeScript (.tsx) or JavaScript (.jsx) @default true */
672
+ tsx?: boolean;
673
+ /** Overwrite existing files when adding components @default false */
674
+ overwrite?: boolean;
675
+ }
641
676
  /**
642
677
  * Resolved theme definition with all required fields
643
678
  */
@@ -731,6 +766,26 @@ interface ResolvedIconsConfig {
731
766
  optimize: boolean;
732
767
  prefix: string;
733
768
  }
769
+ /**
770
+ * Resolved aliases config with all defaults applied
771
+ */
772
+ interface ResolvedAliasesConfig {
773
+ importAlias: string;
774
+ ui: string;
775
+ hooks: string;
776
+ utils: string;
777
+ components: string;
778
+ lib: string;
779
+ }
780
+ /**
781
+ * Resolved components config with all defaults applied
782
+ */
783
+ interface ResolvedComponentsConfig {
784
+ enabled: boolean;
785
+ registryUrl: string;
786
+ tsx: boolean;
787
+ overwrite: boolean;
788
+ }
734
789
  /**
735
790
  * Resolved global config with all defaults applied
736
791
  */
@@ -745,6 +800,8 @@ interface ResolvedGlobalConfig {
745
800
  interface ResolvedConfig {
746
801
  tokens: ResolvedTokensConfig;
747
802
  icons: ResolvedIconsConfig;
803
+ aliases: ResolvedAliasesConfig;
804
+ components: ResolvedComponentsConfig;
748
805
  global: ResolvedGlobalConfig;
749
806
  /** Absolute path to config file (if loaded from file) */
750
807
  configPath?: string;
@@ -776,4 +833,4 @@ interface LoadConfigResult {
776
833
  warnings: string[];
777
834
  }
778
835
 
779
- export type { BuildSummary as B, CustomTransform as C, DsaiConfig as D, FrameworkTarget as F, GlobalConfig as G, IconsConfig as I, LoadConfigOptions as L, OutputFormat as O, Platform as P, ResolvedConfig as R, ScssOutputConfig as S, TokensConfig as T, ThemesConfig as a, ThemeDefinition as b, ThemeSelectorPattern as c, FrameworkMappingConfig as d, FrameworkMappingPattern as e, ResolvedGlobalConfig as f, ResolvedTokensConfig as g, ResolvedIconsConfig as h, ResolvedThemesConfig as i, ResolvedThemeDefinition as j, CustomFormat as k, CustomPreprocessor as l, CustomFilter as m, TokenData as n, TransformOptions as o, FormatArgs as p, Dictionary as q, FileConfig as r, LoadConfigResult as s, LogLevel as t, IconFramework as u };
836
+ export type { AliasesConfig as A, BuildSummary as B, ComponentsConfig as C, Dictionary as D, FileConfig as F, GlobalConfig as G, IconFramework as I, LoadConfigOptions as L, OutputFormat as O, Platform as P, ResolvedAliasesConfig as R, ScssOutputConfig as S, ThemeDefinition as T, ResolvedComponentsConfig as a, CustomFilter as b, CustomFormat as c, CustomPreprocessor as d, CustomTransform as e, DsaiConfig as f, FormatArgs as g, FrameworkMappingConfig as h, FrameworkMappingPattern as i, FrameworkTarget as j, IconsConfig as k, LoadConfigResult as l, LogLevel as m, ResolvedConfig as n, ResolvedGlobalConfig as o, ResolvedIconsConfig as p, ResolvedThemeDefinition as q, ResolvedThemesConfig as r, ResolvedTokensConfig as s, ThemeSelectorPattern as t, ThemesConfig as u, TokenData as v, TokensConfig as w, TransformOptions as x };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/circuit-breaker.ts"],"names":["CircuitState"],"mappings":"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","file":"circuit-breaker.cjs","sourcesContent":["/**\n * @fileoverview Circuit Breaker pattern implementation\n * Prevents cascade failures by tracking error rates and temporarily blocking requests\n */\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n /** Normal operation - requests are allowed */\n CLOSED = 'CLOSED',\n /** Failing - all requests are rejected immediately */\n OPEN = 'OPEN',\n /** Testing recovery - limited requests are allowed */\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker configuration\n */\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit */\n failureThreshold?: number;\n /** Time in ms before attempting to close circuit */\n cooldownMs?: number;\n /** Request timeout in ms */\n timeout?: number;\n /** Name for logging */\n name?: string;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n /** Current state */\n state: CircuitState;\n /** Total failures */\n failures: number;\n /** Total successes */\n successes: number;\n /** Total calls */\n totalCalls: number;\n /** Time circuit opened (if open) */\n openedAt?: Date;\n /** Time circuit will attempt to close */\n resetAt?: Date;\n /** Last error */\n lastError?: string;\n}\n\n/**\n * Circuit breaker error thrown when circuit is open\n */\nexport class CircuitBreakerOpenError extends Error {\n constructor(\n public readonly circuitName: string,\n public readonly resetAt: Date\n ) {\n super(`Circuit breaker \"${circuitName}\" is open. Will retry at ${resetAt.toISOString()}`);\n this.name = 'CircuitBreakerOpenError';\n }\n}\n\n/**\n * Circuit breaker implementation\n * Tracks failures and opens circuit to prevent cascade failures\n */\nexport class CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private totalCalls = 0;\n private openedAt?: Date;\n private resetAt?: Date;\n private lastError?: string;\n\n private readonly failureThreshold: number;\n private readonly cooldownMs: number;\n private readonly timeout: number;\n private readonly name: string;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.failureThreshold = config.failureThreshold ?? 5;\n this.cooldownMs = config.cooldownMs ?? 30000; // 30 seconds\n this.timeout = config.timeout ?? 10000; // 10 seconds\n this.name = config.name ?? 'CircuitBreaker';\n }\n\n /**\n * Execute a function with circuit breaker protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n this.totalCalls++;\n\n // Check if circuit should transition from OPEN to HALF_OPEN\n if (this.state === CircuitState.OPEN && this.canAttemptReset()) {\n this.state = CircuitState.HALF_OPEN;\n this.failures = 0; // Reset failure count for half-open state\n }\n\n // Reject immediately if circuit is open\n if (this.state === CircuitState.OPEN) {\n if (!this.resetAt) {\n throw new Error(`Circuit breaker \"${this.name}\" is open but has no reset time`);\n }\n throw new CircuitBreakerOpenError(this.name, this.resetAt);\n }\n\n try {\n // Execute with timeout\n const result = await this.executeWithTimeout(fn);\n\n // Record success\n this.onSuccess();\n\n return result;\n } catch (error) {\n // Record failure\n this.onFailure(error);\n throw error;\n }\n }\n\n /**\n * Execute function with timeout\n */\n private async executeWithTimeout<T>(fn: () => Promise<T>): Promise<T> {\n return Promise.race([\n fn(),\n new Promise<T>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Circuit breaker timeout after ${this.timeout}ms`));\n }, this.timeout);\n }),\n ]);\n }\n\n /**\n * Handle successful execution\n */\n private onSuccess(): void {\n this.successes++;\n\n if (this.state === CircuitState.HALF_OPEN) {\n // Successful call in HALF_OPEN state closes the circuit\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.openedAt = undefined;\n this.resetAt = undefined;\n this.lastError = undefined;\n }\n }\n\n /**\n * Handle failed execution\n */\n private onFailure(error: unknown): void {\n this.failures++;\n this.lastError = error instanceof Error ? error.message : String(error);\n\n if (this.state === CircuitState.HALF_OPEN) {\n // Failure in HALF_OPEN state immediately reopens circuit\n this.openCircuit();\n } else if (this.failures >= this.failureThreshold) {\n // Threshold reached, open circuit\n this.openCircuit();\n }\n }\n\n /**\n * Open the circuit\n */\n private openCircuit(): void {\n this.state = CircuitState.OPEN;\n this.openedAt = new Date();\n this.resetAt = new Date(Date.now() + this.cooldownMs);\n }\n\n /**\n * Check if circuit can attempt reset\n */\n private canAttemptReset(): boolean {\n if (!this.resetAt) {\n return false;\n }\n return Date.now() >= this.resetAt.getTime();\n }\n\n /**\n * Get current circuit breaker state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n totalCalls: this.totalCalls,\n openedAt: this.openedAt,\n resetAt: this.resetAt,\n lastError: this.lastError,\n };\n }\n\n /**\n * Manually reset circuit breaker\n */\n reset(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.successes = 0;\n this.totalCalls = 0;\n this.openedAt = undefined;\n this.resetAt = undefined;\n this.lastError = undefined;\n }\n\n /**\n * Check if circuit is open\n */\n isOpen(): boolean {\n return this.state === CircuitState.OPEN;\n }\n\n /**\n * Check if circuit is closed\n */\n isClosed(): boolean {\n return this.state === CircuitState.CLOSED;\n }\n\n /**\n * Check if circuit is half-open\n */\n isHalfOpen(): boolean {\n return this.state === CircuitState.HALF_OPEN;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/circuit-breaker.ts"],"names":["CircuitState"],"mappings":"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","file":"circuit-breaker.cjs","sourcesContent":["/**\r\n * @fileoverview Circuit Breaker pattern implementation\r\n * Prevents cascade failures by tracking error rates and temporarily blocking requests\r\n */\r\n\r\n/**\r\n * Circuit breaker states\r\n */\r\nexport enum CircuitState {\r\n /** Normal operation - requests are allowed */\r\n CLOSED = 'CLOSED',\r\n /** Failing - all requests are rejected immediately */\r\n OPEN = 'OPEN',\r\n /** Testing recovery - limited requests are allowed */\r\n HALF_OPEN = 'HALF_OPEN',\r\n}\r\n\r\n/**\r\n * Circuit breaker configuration\r\n */\r\nexport interface CircuitBreakerConfig {\r\n /** Number of failures before opening circuit */\r\n failureThreshold?: number;\r\n /** Time in ms before attempting to close circuit */\r\n cooldownMs?: number;\r\n /** Request timeout in ms */\r\n timeout?: number;\r\n /** Name for logging */\r\n name?: string;\r\n}\r\n\r\n/**\r\n * Circuit breaker statistics\r\n */\r\nexport interface CircuitBreakerStats {\r\n /** Current state */\r\n state: CircuitState;\r\n /** Total failures */\r\n failures: number;\r\n /** Total successes */\r\n successes: number;\r\n /** Total calls */\r\n totalCalls: number;\r\n /** Time circuit opened (if open) */\r\n openedAt?: Date;\r\n /** Time circuit will attempt to close */\r\n resetAt?: Date;\r\n /** Last error */\r\n lastError?: string;\r\n}\r\n\r\n/**\r\n * Circuit breaker error thrown when circuit is open\r\n */\r\nexport class CircuitBreakerOpenError extends Error {\r\n constructor(\r\n public readonly circuitName: string,\r\n public readonly resetAt: Date\r\n ) {\r\n super(`Circuit breaker \"${circuitName}\" is open. Will retry at ${resetAt.toISOString()}`);\r\n this.name = 'CircuitBreakerOpenError';\r\n }\r\n}\r\n\r\n/**\r\n * Circuit breaker implementation\r\n * Tracks failures and opens circuit to prevent cascade failures\r\n */\r\nexport class CircuitBreaker {\r\n private state: CircuitState = CircuitState.CLOSED;\r\n private failures = 0;\r\n private successes = 0;\r\n private totalCalls = 0;\r\n private openedAt?: Date;\r\n private resetAt?: Date;\r\n private lastError?: string;\r\n\r\n private readonly failureThreshold: number;\r\n private readonly cooldownMs: number;\r\n private readonly timeout: number;\r\n private readonly name: string;\r\n\r\n constructor(config: CircuitBreakerConfig = {}) {\r\n this.failureThreshold = config.failureThreshold ?? 5;\r\n this.cooldownMs = config.cooldownMs ?? 30000; // 30 seconds\r\n this.timeout = config.timeout ?? 10000; // 10 seconds\r\n this.name = config.name ?? 'CircuitBreaker';\r\n }\r\n\r\n /**\r\n * Execute a function with circuit breaker protection\r\n */\r\n async execute<T>(fn: () => Promise<T>): Promise<T> {\r\n this.totalCalls++;\r\n\r\n // Check if circuit should transition from OPEN to HALF_OPEN\r\n if (this.state === CircuitState.OPEN && this.canAttemptReset()) {\r\n this.state = CircuitState.HALF_OPEN;\r\n this.failures = 0; // Reset failure count for half-open state\r\n }\r\n\r\n // Reject immediately if circuit is open\r\n if (this.state === CircuitState.OPEN) {\r\n if (!this.resetAt) {\r\n throw new Error(`Circuit breaker \"${this.name}\" is open but has no reset time`);\r\n }\r\n throw new CircuitBreakerOpenError(this.name, this.resetAt);\r\n }\r\n\r\n try {\r\n // Execute with timeout\r\n const result = await this.executeWithTimeout(fn);\r\n\r\n // Record success\r\n this.onSuccess();\r\n\r\n return result;\r\n } catch (error) {\r\n // Record failure\r\n this.onFailure(error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Execute function with timeout\r\n */\r\n private async executeWithTimeout<T>(fn: () => Promise<T>): Promise<T> {\r\n return Promise.race([\r\n fn(),\r\n new Promise<T>((_, reject) => {\r\n setTimeout(() => {\r\n reject(new Error(`Circuit breaker timeout after ${this.timeout}ms`));\r\n }, this.timeout);\r\n }),\r\n ]);\r\n }\r\n\r\n /**\r\n * Handle successful execution\r\n */\r\n private onSuccess(): void {\r\n this.successes++;\r\n\r\n if (this.state === CircuitState.HALF_OPEN) {\r\n // Successful call in HALF_OPEN state closes the circuit\r\n this.state = CircuitState.CLOSED;\r\n this.failures = 0;\r\n this.openedAt = undefined;\r\n this.resetAt = undefined;\r\n this.lastError = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Handle failed execution\r\n */\r\n private onFailure(error: unknown): void {\r\n this.failures++;\r\n this.lastError = error instanceof Error ? error.message : String(error);\r\n\r\n if (this.state === CircuitState.HALF_OPEN) {\r\n // Failure in HALF_OPEN state immediately reopens circuit\r\n this.openCircuit();\r\n } else if (this.failures >= this.failureThreshold) {\r\n // Threshold reached, open circuit\r\n this.openCircuit();\r\n }\r\n }\r\n\r\n /**\r\n * Open the circuit\r\n */\r\n private openCircuit(): void {\r\n this.state = CircuitState.OPEN;\r\n this.openedAt = new Date();\r\n this.resetAt = new Date(Date.now() + this.cooldownMs);\r\n }\r\n\r\n /**\r\n * Check if circuit can attempt reset\r\n */\r\n private canAttemptReset(): boolean {\r\n if (!this.resetAt) {\r\n return false;\r\n }\r\n return Date.now() >= this.resetAt.getTime();\r\n }\r\n\r\n /**\r\n * Get current circuit breaker state\r\n */\r\n getState(): CircuitState {\r\n return this.state;\r\n }\r\n\r\n /**\r\n * Get circuit breaker statistics\r\n */\r\n getStats(): CircuitBreakerStats {\r\n return {\r\n state: this.state,\r\n failures: this.failures,\r\n successes: this.successes,\r\n totalCalls: this.totalCalls,\r\n openedAt: this.openedAt,\r\n resetAt: this.resetAt,\r\n lastError: this.lastError,\r\n };\r\n }\r\n\r\n /**\r\n * Manually reset circuit breaker\r\n */\r\n reset(): void {\r\n this.state = CircuitState.CLOSED;\r\n this.failures = 0;\r\n this.successes = 0;\r\n this.totalCalls = 0;\r\n this.openedAt = undefined;\r\n this.resetAt = undefined;\r\n this.lastError = undefined;\r\n }\r\n\r\n /**\r\n * Check if circuit is open\r\n */\r\n isOpen(): boolean {\r\n return this.state === CircuitState.OPEN;\r\n }\r\n\r\n /**\r\n * Check if circuit is closed\r\n */\r\n isClosed(): boolean {\r\n return this.state === CircuitState.CLOSED;\r\n }\r\n\r\n /**\r\n * Check if circuit is half-open\r\n */\r\n isHalfOpen(): boolean {\r\n return this.state === CircuitState.HALF_OPEN;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/circuit-breaker.ts"],"names":["CircuitState"],"mappings":"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","file":"circuit-breaker.js","sourcesContent":["/**\n * @fileoverview Circuit Breaker pattern implementation\n * Prevents cascade failures by tracking error rates and temporarily blocking requests\n */\n\n/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n /** Normal operation - requests are allowed */\n CLOSED = 'CLOSED',\n /** Failing - all requests are rejected immediately */\n OPEN = 'OPEN',\n /** Testing recovery - limited requests are allowed */\n HALF_OPEN = 'HALF_OPEN',\n}\n\n/**\n * Circuit breaker configuration\n */\nexport interface CircuitBreakerConfig {\n /** Number of failures before opening circuit */\n failureThreshold?: number;\n /** Time in ms before attempting to close circuit */\n cooldownMs?: number;\n /** Request timeout in ms */\n timeout?: number;\n /** Name for logging */\n name?: string;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n /** Current state */\n state: CircuitState;\n /** Total failures */\n failures: number;\n /** Total successes */\n successes: number;\n /** Total calls */\n totalCalls: number;\n /** Time circuit opened (if open) */\n openedAt?: Date;\n /** Time circuit will attempt to close */\n resetAt?: Date;\n /** Last error */\n lastError?: string;\n}\n\n/**\n * Circuit breaker error thrown when circuit is open\n */\nexport class CircuitBreakerOpenError extends Error {\n constructor(\n public readonly circuitName: string,\n public readonly resetAt: Date\n ) {\n super(`Circuit breaker \"${circuitName}\" is open. Will retry at ${resetAt.toISOString()}`);\n this.name = 'CircuitBreakerOpenError';\n }\n}\n\n/**\n * Circuit breaker implementation\n * Tracks failures and opens circuit to prevent cascade failures\n */\nexport class CircuitBreaker {\n private state: CircuitState = CircuitState.CLOSED;\n private failures = 0;\n private successes = 0;\n private totalCalls = 0;\n private openedAt?: Date;\n private resetAt?: Date;\n private lastError?: string;\n\n private readonly failureThreshold: number;\n private readonly cooldownMs: number;\n private readonly timeout: number;\n private readonly name: string;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.failureThreshold = config.failureThreshold ?? 5;\n this.cooldownMs = config.cooldownMs ?? 30000; // 30 seconds\n this.timeout = config.timeout ?? 10000; // 10 seconds\n this.name = config.name ?? 'CircuitBreaker';\n }\n\n /**\n * Execute a function with circuit breaker protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n this.totalCalls++;\n\n // Check if circuit should transition from OPEN to HALF_OPEN\n if (this.state === CircuitState.OPEN && this.canAttemptReset()) {\n this.state = CircuitState.HALF_OPEN;\n this.failures = 0; // Reset failure count for half-open state\n }\n\n // Reject immediately if circuit is open\n if (this.state === CircuitState.OPEN) {\n if (!this.resetAt) {\n throw new Error(`Circuit breaker \"${this.name}\" is open but has no reset time`);\n }\n throw new CircuitBreakerOpenError(this.name, this.resetAt);\n }\n\n try {\n // Execute with timeout\n const result = await this.executeWithTimeout(fn);\n\n // Record success\n this.onSuccess();\n\n return result;\n } catch (error) {\n // Record failure\n this.onFailure(error);\n throw error;\n }\n }\n\n /**\n * Execute function with timeout\n */\n private async executeWithTimeout<T>(fn: () => Promise<T>): Promise<T> {\n return Promise.race([\n fn(),\n new Promise<T>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Circuit breaker timeout after ${this.timeout}ms`));\n }, this.timeout);\n }),\n ]);\n }\n\n /**\n * Handle successful execution\n */\n private onSuccess(): void {\n this.successes++;\n\n if (this.state === CircuitState.HALF_OPEN) {\n // Successful call in HALF_OPEN state closes the circuit\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.openedAt = undefined;\n this.resetAt = undefined;\n this.lastError = undefined;\n }\n }\n\n /**\n * Handle failed execution\n */\n private onFailure(error: unknown): void {\n this.failures++;\n this.lastError = error instanceof Error ? error.message : String(error);\n\n if (this.state === CircuitState.HALF_OPEN) {\n // Failure in HALF_OPEN state immediately reopens circuit\n this.openCircuit();\n } else if (this.failures >= this.failureThreshold) {\n // Threshold reached, open circuit\n this.openCircuit();\n }\n }\n\n /**\n * Open the circuit\n */\n private openCircuit(): void {\n this.state = CircuitState.OPEN;\n this.openedAt = new Date();\n this.resetAt = new Date(Date.now() + this.cooldownMs);\n }\n\n /**\n * Check if circuit can attempt reset\n */\n private canAttemptReset(): boolean {\n if (!this.resetAt) {\n return false;\n }\n return Date.now() >= this.resetAt.getTime();\n }\n\n /**\n * Get current circuit breaker state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n totalCalls: this.totalCalls,\n openedAt: this.openedAt,\n resetAt: this.resetAt,\n lastError: this.lastError,\n };\n }\n\n /**\n * Manually reset circuit breaker\n */\n reset(): void {\n this.state = CircuitState.CLOSED;\n this.failures = 0;\n this.successes = 0;\n this.totalCalls = 0;\n this.openedAt = undefined;\n this.resetAt = undefined;\n this.lastError = undefined;\n }\n\n /**\n * Check if circuit is open\n */\n isOpen(): boolean {\n return this.state === CircuitState.OPEN;\n }\n\n /**\n * Check if circuit is closed\n */\n isClosed(): boolean {\n return this.state === CircuitState.CLOSED;\n }\n\n /**\n * Check if circuit is half-open\n */\n isHalfOpen(): boolean {\n return this.state === CircuitState.HALF_OPEN;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/circuit-breaker.ts"],"names":["CircuitState"],"mappings":"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","file":"circuit-breaker.js","sourcesContent":["/**\r\n * @fileoverview Circuit Breaker pattern implementation\r\n * Prevents cascade failures by tracking error rates and temporarily blocking requests\r\n */\r\n\r\n/**\r\n * Circuit breaker states\r\n */\r\nexport enum CircuitState {\r\n /** Normal operation - requests are allowed */\r\n CLOSED = 'CLOSED',\r\n /** Failing - all requests are rejected immediately */\r\n OPEN = 'OPEN',\r\n /** Testing recovery - limited requests are allowed */\r\n HALF_OPEN = 'HALF_OPEN',\r\n}\r\n\r\n/**\r\n * Circuit breaker configuration\r\n */\r\nexport interface CircuitBreakerConfig {\r\n /** Number of failures before opening circuit */\r\n failureThreshold?: number;\r\n /** Time in ms before attempting to close circuit */\r\n cooldownMs?: number;\r\n /** Request timeout in ms */\r\n timeout?: number;\r\n /** Name for logging */\r\n name?: string;\r\n}\r\n\r\n/**\r\n * Circuit breaker statistics\r\n */\r\nexport interface CircuitBreakerStats {\r\n /** Current state */\r\n state: CircuitState;\r\n /** Total failures */\r\n failures: number;\r\n /** Total successes */\r\n successes: number;\r\n /** Total calls */\r\n totalCalls: number;\r\n /** Time circuit opened (if open) */\r\n openedAt?: Date;\r\n /** Time circuit will attempt to close */\r\n resetAt?: Date;\r\n /** Last error */\r\n lastError?: string;\r\n}\r\n\r\n/**\r\n * Circuit breaker error thrown when circuit is open\r\n */\r\nexport class CircuitBreakerOpenError extends Error {\r\n constructor(\r\n public readonly circuitName: string,\r\n public readonly resetAt: Date\r\n ) {\r\n super(`Circuit breaker \"${circuitName}\" is open. Will retry at ${resetAt.toISOString()}`);\r\n this.name = 'CircuitBreakerOpenError';\r\n }\r\n}\r\n\r\n/**\r\n * Circuit breaker implementation\r\n * Tracks failures and opens circuit to prevent cascade failures\r\n */\r\nexport class CircuitBreaker {\r\n private state: CircuitState = CircuitState.CLOSED;\r\n private failures = 0;\r\n private successes = 0;\r\n private totalCalls = 0;\r\n private openedAt?: Date;\r\n private resetAt?: Date;\r\n private lastError?: string;\r\n\r\n private readonly failureThreshold: number;\r\n private readonly cooldownMs: number;\r\n private readonly timeout: number;\r\n private readonly name: string;\r\n\r\n constructor(config: CircuitBreakerConfig = {}) {\r\n this.failureThreshold = config.failureThreshold ?? 5;\r\n this.cooldownMs = config.cooldownMs ?? 30000; // 30 seconds\r\n this.timeout = config.timeout ?? 10000; // 10 seconds\r\n this.name = config.name ?? 'CircuitBreaker';\r\n }\r\n\r\n /**\r\n * Execute a function with circuit breaker protection\r\n */\r\n async execute<T>(fn: () => Promise<T>): Promise<T> {\r\n this.totalCalls++;\r\n\r\n // Check if circuit should transition from OPEN to HALF_OPEN\r\n if (this.state === CircuitState.OPEN && this.canAttemptReset()) {\r\n this.state = CircuitState.HALF_OPEN;\r\n this.failures = 0; // Reset failure count for half-open state\r\n }\r\n\r\n // Reject immediately if circuit is open\r\n if (this.state === CircuitState.OPEN) {\r\n if (!this.resetAt) {\r\n throw new Error(`Circuit breaker \"${this.name}\" is open but has no reset time`);\r\n }\r\n throw new CircuitBreakerOpenError(this.name, this.resetAt);\r\n }\r\n\r\n try {\r\n // Execute with timeout\r\n const result = await this.executeWithTimeout(fn);\r\n\r\n // Record success\r\n this.onSuccess();\r\n\r\n return result;\r\n } catch (error) {\r\n // Record failure\r\n this.onFailure(error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Execute function with timeout\r\n */\r\n private async executeWithTimeout<T>(fn: () => Promise<T>): Promise<T> {\r\n return Promise.race([\r\n fn(),\r\n new Promise<T>((_, reject) => {\r\n setTimeout(() => {\r\n reject(new Error(`Circuit breaker timeout after ${this.timeout}ms`));\r\n }, this.timeout);\r\n }),\r\n ]);\r\n }\r\n\r\n /**\r\n * Handle successful execution\r\n */\r\n private onSuccess(): void {\r\n this.successes++;\r\n\r\n if (this.state === CircuitState.HALF_OPEN) {\r\n // Successful call in HALF_OPEN state closes the circuit\r\n this.state = CircuitState.CLOSED;\r\n this.failures = 0;\r\n this.openedAt = undefined;\r\n this.resetAt = undefined;\r\n this.lastError = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Handle failed execution\r\n */\r\n private onFailure(error: unknown): void {\r\n this.failures++;\r\n this.lastError = error instanceof Error ? error.message : String(error);\r\n\r\n if (this.state === CircuitState.HALF_OPEN) {\r\n // Failure in HALF_OPEN state immediately reopens circuit\r\n this.openCircuit();\r\n } else if (this.failures >= this.failureThreshold) {\r\n // Threshold reached, open circuit\r\n this.openCircuit();\r\n }\r\n }\r\n\r\n /**\r\n * Open the circuit\r\n */\r\n private openCircuit(): void {\r\n this.state = CircuitState.OPEN;\r\n this.openedAt = new Date();\r\n this.resetAt = new Date(Date.now() + this.cooldownMs);\r\n }\r\n\r\n /**\r\n * Check if circuit can attempt reset\r\n */\r\n private canAttemptReset(): boolean {\r\n if (!this.resetAt) {\r\n return false;\r\n }\r\n return Date.now() >= this.resetAt.getTime();\r\n }\r\n\r\n /**\r\n * Get current circuit breaker state\r\n */\r\n getState(): CircuitState {\r\n return this.state;\r\n }\r\n\r\n /**\r\n * Get circuit breaker statistics\r\n */\r\n getStats(): CircuitBreakerStats {\r\n return {\r\n state: this.state,\r\n failures: this.failures,\r\n successes: this.successes,\r\n totalCalls: this.totalCalls,\r\n openedAt: this.openedAt,\r\n resetAt: this.resetAt,\r\n lastError: this.lastError,\r\n };\r\n }\r\n\r\n /**\r\n * Manually reset circuit breaker\r\n */\r\n reset(): void {\r\n this.state = CircuitState.CLOSED;\r\n this.failures = 0;\r\n this.successes = 0;\r\n this.totalCalls = 0;\r\n this.openedAt = undefined;\r\n this.resetAt = undefined;\r\n this.lastError = undefined;\r\n }\r\n\r\n /**\r\n * Check if circuit is open\r\n */\r\n isOpen(): boolean {\r\n return this.state === CircuitState.OPEN;\r\n }\r\n\r\n /**\r\n * Check if circuit is closed\r\n */\r\n isClosed(): boolean {\r\n return this.state === CircuitState.CLOSED;\r\n }\r\n\r\n /**\r\n * Check if circuit is half-open\r\n */\r\n isHalfOpen(): boolean {\r\n return this.state === CircuitState.HALF_OPEN;\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,102 +1,102 @@
1
- {
2
- "name": "@dsai-io/tools",
3
- "version": "1.0.7",
4
- "description": "Build tooling and CLI for DSAi Design System",
5
- "type": "module",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "bin": {
10
- "dsai": "./bin/dsai-tools.mjs",
11
- "dsai-tools": "./bin/dsai-tools.mjs"
12
- },
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js",
17
- "require": "./dist/index.cjs"
18
- },
19
- "./config": {
20
- "types": "./dist/config/index.d.ts",
21
- "import": "./dist/config/index.js",
22
- "require": "./dist/config/index.cjs"
23
- },
24
- "./tokens": {
25
- "types": "./dist/tokens/index.d.ts",
26
- "import": "./dist/tokens/index.js",
27
- "require": "./dist/tokens/index.cjs"
28
- },
29
- "./icons": {
30
- "types": "./dist/icons/index.d.ts",
31
- "import": "./dist/icons/index.js",
32
- "require": "./dist/icons/index.cjs"
33
- },
34
- "./cli": {
35
- "types": "./dist/cli/index.d.ts",
36
- "import": "./dist/cli/index.js",
37
- "require": "./dist/cli/index.cjs"
38
- },
39
- "./utils/circuit-breaker": {
40
- "types": "./dist/utils/circuit-breaker.d.ts",
41
- "import": "./dist/utils/circuit-breaker.js",
42
- "require": "./dist/utils/circuit-breaker.cjs"
43
- }
44
- },
45
- "files": [
46
- "dist",
47
- "bin",
48
- "templates"
49
- ],
50
- "scripts": {
51
- "build": "tsup",
52
- "build:watch": "tsup --watch",
53
- "dev": "tsup --watch",
54
- "test": "jest",
55
- "lint": "eslint src --ext .ts",
56
- "lint:fix": "eslint src --ext .ts --fix",
57
- "typecheck": "tsc --noEmit",
58
- "generate-schema": "node scripts/generate-schema.mjs"
59
- },
60
- "keywords": [
61
- "design-tokens",
62
- "design-system",
63
- "cli",
64
- "style-dictionary",
65
- "build-tools",
66
- "dsai"
67
- ],
68
- "license": "UNLICENSED",
69
- "engines": {
70
- "node": ">=22.0.0"
71
- },
72
- "dependencies": {
73
- "commander": "^14.0.2",
74
- "cosmiconfig": "^9.0.0",
75
- "deepmerge": "^4.3.1",
76
- "fast-glob": "^3.3.3",
77
- "ora": "^9.0.0",
78
- "picocolors": "^1.1.1",
79
- "svgo": "^4.0.0",
80
- "zod": "^4.3.5"
81
- },
82
- "devDependencies": {
83
- "@clack/prompts": "^0.11.0",
84
- "@types/node": "^22.15.30",
85
- "@types/prompts": "^2.4.9",
86
- "style-dictionary": "^5.1.4",
87
- "tsup": "^8.5.1",
88
- "typescript": "^5.9.3",
89
- "zod-to-json-schema": "^3.25.1"
90
- },
91
- "peerDependencies": {
92
- "style-dictionary": "^5.1.4"
93
- },
94
- "peerDependenciesMeta": {
95
- "style-dictionary": {
96
- "optional": true
97
- }
98
- },
99
- "publishConfig": {
100
- "access": "restricted"
101
- }
102
- }
1
+ {
2
+ "name": "@dsai-io/tools",
3
+ "version": "1.2.1",
4
+ "description": "Build tooling and CLI for DSAi Design System",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "dsai": "bin/dsai-tools.mjs",
11
+ "dsai-tools": "bin/dsai-tools.mjs"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ },
19
+ "./config": {
20
+ "types": "./dist/config/index.d.ts",
21
+ "import": "./dist/config/index.js",
22
+ "require": "./dist/config/index.cjs"
23
+ },
24
+ "./tokens": {
25
+ "types": "./dist/tokens/index.d.ts",
26
+ "import": "./dist/tokens/index.js",
27
+ "require": "./dist/tokens/index.cjs"
28
+ },
29
+ "./icons": {
30
+ "types": "./dist/icons/index.d.ts",
31
+ "import": "./dist/icons/index.js",
32
+ "require": "./dist/icons/index.cjs"
33
+ },
34
+ "./cli": {
35
+ "types": "./dist/cli/index.d.ts",
36
+ "import": "./dist/cli/index.js",
37
+ "require": "./dist/cli/index.cjs"
38
+ },
39
+ "./utils/circuit-breaker": {
40
+ "types": "./dist/utils/circuit-breaker.d.ts",
41
+ "import": "./dist/utils/circuit-breaker.js",
42
+ "require": "./dist/utils/circuit-breaker.cjs"
43
+ }
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "bin",
48
+ "templates"
49
+ ],
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "build:watch": "tsup --watch",
53
+ "dev": "tsup --watch",
54
+ "test": "jest",
55
+ "lint": "eslint src --ext .ts",
56
+ "lint:fix": "eslint src --ext .ts --fix",
57
+ "typecheck": "tsc --noEmit",
58
+ "generate-schema": "node scripts/generate-schema.mjs"
59
+ },
60
+ "keywords": [
61
+ "design-tokens",
62
+ "design-system",
63
+ "cli",
64
+ "style-dictionary",
65
+ "build-tools",
66
+ "dsai"
67
+ ],
68
+ "license": "MIT",
69
+ "engines": {
70
+ "node": ">=22.0.0"
71
+ },
72
+ "dependencies": {
73
+ "commander": "^14.0.2",
74
+ "cosmiconfig": "^9.0.0",
75
+ "deepmerge": "^4.3.1",
76
+ "fast-glob": "^3.3.3",
77
+ "ora": "^9.0.0",
78
+ "picocolors": "^1.1.1",
79
+ "svgo": "^4.0.0",
80
+ "zod": "^4.3.5"
81
+ },
82
+ "devDependencies": {
83
+ "@clack/prompts": "^0.11.0",
84
+ "@types/node": "^22.15.30",
85
+ "@types/prompts": "^2.4.9",
86
+ "style-dictionary": "^5.1.4",
87
+ "tsup": "^8.5.1",
88
+ "typescript": "^5.9.3",
89
+ "zod-to-json-schema": "^3.25.1"
90
+ },
91
+ "peerDependencies": {
92
+ "style-dictionary": "^5.1.4"
93
+ },
94
+ "peerDependenciesMeta": {
95
+ "style-dictionary": {
96
+ "optional": true
97
+ }
98
+ },
99
+ "publishConfig": {
100
+ "access": "public"
101
+ }
102
+ }
@@ -1,37 +1,37 @@
1
- {
2
- "$schema": "./dsai-config.schema.json",
3
- "tokens": {
4
- "source": "theme",
5
- "sourceDir": "figma-exports",
6
- "sourcePatterns": ["theme.json", "tokens.json", "*.tokens.json"],
7
- "outputDir": "dist",
8
- "formats": ["css", "scss", "js", "ts", "json"],
9
- "prefix": "--dsai-",
10
- "themes": {
11
- "autoDetect": true,
12
- "default": "Light",
13
- "selectorPattern": {
14
- "default": ":root",
15
- "others": "[data-dsai-theme=\"{mode}\"]"
16
- }
17
- },
18
- "outputReferences": true,
19
- "baseFontSize": 16,
20
- "separateThemeFiles": false,
21
- "watch": false
22
- },
23
- "icons": {
24
- "sourceDir": "icons",
25
- "outputDir": "src/components/icons",
26
- "framework": "react",
27
- "typescript": true,
28
- "optimize": true,
29
- "prefix": "Icon",
30
- "exportIndex": true,
31
- "generateSprite": false
32
- },
33
- "global": {
34
- "debug": false,
35
- "logLevel": "info"
36
- }
37
- }
1
+ {
2
+ "$schema": "./dsai-config.schema.json",
3
+ "tokens": {
4
+ "source": "theme",
5
+ "sourceDir": "figma-exports",
6
+ "sourcePatterns": ["theme.json", "tokens.json", "*.tokens.json"],
7
+ "outputDir": "dist",
8
+ "formats": ["css", "scss", "js", "ts", "json"],
9
+ "prefix": "--dsai-",
10
+ "themes": {
11
+ "autoDetect": true,
12
+ "default": "Light",
13
+ "selectorPattern": {
14
+ "default": ":root",
15
+ "others": "[data-dsai-theme=\"{mode}\"]"
16
+ }
17
+ },
18
+ "outputReferences": true,
19
+ "baseFontSize": 16,
20
+ "separateThemeFiles": false,
21
+ "watch": false
22
+ },
23
+ "icons": {
24
+ "sourceDir": "icons",
25
+ "outputDir": "src/components/icons",
26
+ "framework": "react",
27
+ "typescript": true,
28
+ "optimize": true,
29
+ "prefix": "Icon",
30
+ "exportIndex": true,
31
+ "generateSprite": false
32
+ },
33
+ "global": {
34
+ "debug": false,
35
+ "logLevel": "info"
36
+ }
37
+ }