@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.
- package/README.md +138 -369
- package/bin/dsai-tools.mjs +13 -13
- package/dist/cli/index.cjs +1942 -545
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +1944 -548
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.cjs +66 -2
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.cts +50 -3
- package/dist/config/index.d.ts +50 -3
- package/dist/config/index.js +63 -3
- package/dist/config/index.js.map +1 -1
- package/dist/icons/index.cjs.map +1 -1
- package/dist/icons/index.d.cts +1 -1
- package/dist/icons/index.d.ts +1 -1
- package/dist/icons/index.js.map +1 -1
- package/dist/index.cjs +1241 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +213 -4
- package/dist/index.d.ts +213 -4
- package/dist/index.js +1229 -19
- package/dist/index.js.map +1 -1
- package/dist/tokens/index.cjs +15 -15
- package/dist/tokens/index.cjs.map +1 -1
- package/dist/tokens/index.d.cts +1 -1
- package/dist/tokens/index.d.ts +1 -1
- package/dist/tokens/index.js +15 -15
- package/dist/tokens/index.js.map +1 -1
- package/dist/{types-DabOzcsj.d.cts → types-CtE9f0G0.d.cts} +58 -1
- package/dist/{types-DabOzcsj.d.ts → types-CtE9f0G0.d.ts} +58 -1
- package/dist/utils/circuit-breaker.cjs.map +1 -1
- package/dist/utils/circuit-breaker.js.map +1 -1
- package/package.json +102 -102
- package/templates/.dsairc.json +37 -37
- package/templates/dsai-config.schema.json +618 -554
- package/templates/dsai.config.mjs +281 -221
|
@@ -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,
|
|
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,
|
|
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.
|
|
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": "
|
|
11
|
-
"dsai-tools": "
|
|
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": "
|
|
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": "
|
|
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
|
+
}
|
package/templates/.dsairc.json
CHANGED
|
@@ -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
|
+
}
|