@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
package/dist/cli/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var crypto = require('crypto');
|
|
|
7
7
|
var fg = require('fast-glob');
|
|
8
8
|
var child_process = require('child_process');
|
|
9
9
|
var promises = require('fs/promises');
|
|
10
|
+
var url = require('url');
|
|
10
11
|
var commander = require('commander');
|
|
11
12
|
var cosmiconfig = require('cosmiconfig');
|
|
12
13
|
var e = require('picocolors');
|
|
@@ -16,6 +17,7 @@ var y2 = require('process');
|
|
|
16
17
|
var g = require('readline');
|
|
17
18
|
var stream = require('stream');
|
|
18
19
|
|
|
20
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
19
21
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
22
|
|
|
21
23
|
function _interopNamespace(e) {
|
|
@@ -4412,20 +4414,6 @@ var init_line_height = __esm({
|
|
|
4412
4414
|
}
|
|
4413
4415
|
});
|
|
4414
4416
|
|
|
4415
|
-
// src/tokens/style-dictionary/transforms/name.ts
|
|
4416
|
-
var nameKebab;
|
|
4417
|
-
var init_name = __esm({
|
|
4418
|
-
"src/tokens/style-dictionary/transforms/name.ts"() {
|
|
4419
|
-
nameKebab = {
|
|
4420
|
-
name: "name/kebab",
|
|
4421
|
-
type: "name",
|
|
4422
|
-
transform: (token) => {
|
|
4423
|
-
return token.path.join("-").replace(/_/g, "-").toLowerCase();
|
|
4424
|
-
}
|
|
4425
|
-
};
|
|
4426
|
-
}
|
|
4427
|
-
});
|
|
4428
|
-
|
|
4429
4417
|
// src/tokens/style-dictionary/transforms/name-js-identifier.ts
|
|
4430
4418
|
function toPascalCaseSegment3(segment) {
|
|
4431
4419
|
const needsNumericPrefix = /^\d/.test(segment);
|
|
@@ -4445,6 +4433,20 @@ var init_name_js_identifier = __esm({
|
|
|
4445
4433
|
}
|
|
4446
4434
|
});
|
|
4447
4435
|
|
|
4436
|
+
// src/tokens/style-dictionary/transforms/name.ts
|
|
4437
|
+
var nameKebab;
|
|
4438
|
+
var init_name = __esm({
|
|
4439
|
+
"src/tokens/style-dictionary/transforms/name.ts"() {
|
|
4440
|
+
nameKebab = {
|
|
4441
|
+
name: "name/kebab",
|
|
4442
|
+
type: "name",
|
|
4443
|
+
transform: (token) => {
|
|
4444
|
+
return token.path.join("-").replace(/_/g, "-").toLowerCase();
|
|
4445
|
+
}
|
|
4446
|
+
};
|
|
4447
|
+
}
|
|
4448
|
+
});
|
|
4449
|
+
|
|
4448
4450
|
// src/tokens/style-dictionary/transforms/index.ts
|
|
4449
4451
|
var transforms_exports = {};
|
|
4450
4452
|
__export(transforms_exports, {
|
|
@@ -4473,8 +4475,8 @@ var init_transforms = __esm({
|
|
|
4473
4475
|
init_dimension();
|
|
4474
4476
|
init_font_weight();
|
|
4475
4477
|
init_line_height();
|
|
4476
|
-
init_name();
|
|
4477
4478
|
init_name_js_identifier();
|
|
4479
|
+
init_name();
|
|
4478
4480
|
init_font_weight();
|
|
4479
4481
|
init_line_height();
|
|
4480
4482
|
init_dimension();
|
|
@@ -7904,494 +7906,225 @@ var require_src = __commonJS({
|
|
|
7904
7906
|
module.exports = { cursor, scroll, erase, beep };
|
|
7905
7907
|
}
|
|
7906
7908
|
});
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
var
|
|
7910
|
-
var
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7909
|
+
|
|
7910
|
+
// src/config/defaults.ts
|
|
7911
|
+
var DEFAULT_PREFIX = "--dsai-";
|
|
7912
|
+
var DEFAULT_LOG_LEVEL = "info";
|
|
7913
|
+
var DEFAULT_OUTPUT_DIR = "dist";
|
|
7914
|
+
var DEFAULT_SOURCE_DIR = "figma-exports";
|
|
7915
|
+
var DEFAULT_COLLECTIONS_DIR = "collections";
|
|
7916
|
+
var DEFAULT_ICONS_SOURCE_DIR = "icons";
|
|
7917
|
+
var DEFAULT_ICONS_OUTPUT_DIR = "dist/icons";
|
|
7918
|
+
var defaultSourcePatterns = ["theme.json", "tokens.json", "*.tokens.json"];
|
|
7919
|
+
var defaultFormats = ["css", "scss", "js", "ts", "json"];
|
|
7920
|
+
var defaultOutputFileNames = {
|
|
7921
|
+
css: "tokens.css",
|
|
7922
|
+
scss: "_tokens.scss",
|
|
7923
|
+
js: "tokens.js",
|
|
7924
|
+
ts: "tokens.ts",
|
|
7925
|
+
json: "tokens.json",
|
|
7926
|
+
android: "tokens.xml",
|
|
7927
|
+
ios: "tokens.h"
|
|
7928
|
+
};
|
|
7929
|
+
var defaultSelectorPattern = {
|
|
7930
|
+
default: ":root",
|
|
7931
|
+
others: '[data-dsai-theme="{mode}"]'
|
|
7932
|
+
};
|
|
7933
|
+
var defaultThemeDefinitions = {
|
|
7934
|
+
light: {
|
|
7935
|
+
isDefault: true,
|
|
7936
|
+
suffix: null,
|
|
7937
|
+
selector: ":root",
|
|
7938
|
+
outputFiles: {
|
|
7939
|
+
css: "tokens.css",
|
|
7940
|
+
scss: "_tokens.scss",
|
|
7941
|
+
js: "tokens.js",
|
|
7942
|
+
ts: "tokens.ts",
|
|
7943
|
+
json: "tokens.json",
|
|
7944
|
+
android: "tokens.xml",
|
|
7945
|
+
ios: "tokens.h"
|
|
7921
7946
|
}
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7947
|
+
},
|
|
7948
|
+
dark: {
|
|
7949
|
+
isDefault: false,
|
|
7950
|
+
suffix: "-dark",
|
|
7951
|
+
selector: '[data-dsai-theme="dark"]',
|
|
7952
|
+
mediaQuery: "(prefers-color-scheme: dark)",
|
|
7953
|
+
outputFiles: {
|
|
7954
|
+
css: "tokens-dark.css",
|
|
7955
|
+
scss: "_tokens-dark.scss",
|
|
7956
|
+
js: "tokens-dark.js",
|
|
7957
|
+
ts: "tokens-dark.ts",
|
|
7958
|
+
json: "tokens-dark.json",
|
|
7959
|
+
android: "tokens-dark.xml",
|
|
7960
|
+
ios: "tokens-dark.h"
|
|
7961
|
+
}
|
|
7962
|
+
}
|
|
7963
|
+
};
|
|
7964
|
+
var defaultThemesConfig = {
|
|
7965
|
+
enabled: true,
|
|
7966
|
+
autoDetect: true,
|
|
7967
|
+
default: "light",
|
|
7968
|
+
ignoreModes: [],
|
|
7969
|
+
selectorPattern: defaultSelectorPattern};
|
|
7970
|
+
var defaultIconFramework = "react";
|
|
7971
|
+
var defaultIconsConfig = {
|
|
7972
|
+
sourceDir: DEFAULT_ICONS_SOURCE_DIR,
|
|
7973
|
+
outputDir: DEFAULT_ICONS_OUTPUT_DIR,
|
|
7974
|
+
framework: defaultIconFramework,
|
|
7975
|
+
typescript: true,
|
|
7976
|
+
optimize: true,
|
|
7977
|
+
prefix: "Icon"
|
|
7978
|
+
};
|
|
7979
|
+
var defaultAliasesConfig = {
|
|
7980
|
+
importAlias: "@/",
|
|
7981
|
+
ui: "src/components/ui",
|
|
7982
|
+
hooks: "src/hooks",
|
|
7983
|
+
utils: "src/lib/utils",
|
|
7984
|
+
components: "src/components",
|
|
7985
|
+
lib: "src/lib"
|
|
7986
|
+
};
|
|
7987
|
+
var defaultComponentsConfig = {
|
|
7988
|
+
enabled: true,
|
|
7989
|
+
registryUrl: "https://registry.dsai.dev",
|
|
7990
|
+
tsx: true,
|
|
7991
|
+
overwrite: false
|
|
7992
|
+
};
|
|
7993
|
+
var defaultTokensConfig = {
|
|
7994
|
+
source: "theme",
|
|
7995
|
+
sourceDir: DEFAULT_SOURCE_DIR,
|
|
7996
|
+
collectionsDir: DEFAULT_COLLECTIONS_DIR,
|
|
7997
|
+
sourcePatterns: defaultSourcePatterns,
|
|
7998
|
+
outputDir: DEFAULT_OUTPUT_DIR,
|
|
7999
|
+
outputDirs: {},
|
|
8000
|
+
outputFileNames: defaultOutputFileNames,
|
|
8001
|
+
prefix: DEFAULT_PREFIX,
|
|
8002
|
+
formats: defaultFormats,
|
|
8003
|
+
mergeOrder: "after",
|
|
8004
|
+
createBundle: false,
|
|
8005
|
+
outputReferences: true,
|
|
8006
|
+
baseFontSize: 16,
|
|
8007
|
+
separateThemeFiles: false,
|
|
8008
|
+
watch: false};
|
|
8009
|
+
var defaultGlobalConfig = {
|
|
8010
|
+
cwd: process.cwd(),
|
|
8011
|
+
debug: false,
|
|
8012
|
+
logLevel: DEFAULT_LOG_LEVEL
|
|
8013
|
+
};
|
|
8014
|
+
({
|
|
8015
|
+
configDir: process.cwd()
|
|
8016
|
+
});
|
|
8017
|
+
|
|
8018
|
+
// src/config/resolver.ts
|
|
8019
|
+
function resolveGlobalConfig(config, options) {
|
|
8020
|
+
const base = defaultGlobalConfig;
|
|
8021
|
+
const cwd = options.cwd ?? process.cwd();
|
|
8022
|
+
return {
|
|
8023
|
+
cwd: config?.cwd ? path4__namespace.default.resolve(cwd, config.cwd) : cwd,
|
|
8024
|
+
debug: config?.debug ?? base.debug,
|
|
8025
|
+
logLevel: config?.logLevel ?? base.logLevel
|
|
8026
|
+
};
|
|
8027
|
+
}
|
|
8028
|
+
function resolveThemeDefinition(themeName, definition, selectorPattern, _outputFileNames, isDefaultTheme) {
|
|
8029
|
+
const generateOutputFiles = () => {
|
|
8030
|
+
const suffix = isDefaultTheme ? "" : `-${themeName}`;
|
|
8031
|
+
return {
|
|
8032
|
+
css: `tokens${suffix}.css`,
|
|
8033
|
+
scss: `_tokens${suffix}.scss`,
|
|
8034
|
+
js: `tokens${suffix}.js`,
|
|
8035
|
+
ts: `tokens${suffix}.ts`,
|
|
8036
|
+
json: `tokens${suffix}.json`,
|
|
8037
|
+
android: `tokens${suffix}.xml`,
|
|
8038
|
+
ios: `tokens${suffix}.h`
|
|
8039
|
+
};
|
|
8040
|
+
};
|
|
8041
|
+
const generateSelector = () => {
|
|
8042
|
+
if (isDefaultTheme) {
|
|
8043
|
+
return selectorPattern.default;
|
|
8044
|
+
}
|
|
8045
|
+
return selectorPattern.others.replace("{mode}", themeName);
|
|
8046
|
+
};
|
|
8047
|
+
const defaultOutputFiles = generateOutputFiles();
|
|
8048
|
+
return {
|
|
8049
|
+
isDefault: definition?.isDefault ?? isDefaultTheme,
|
|
8050
|
+
suffix: definition?.suffix ?? (isDefaultTheme ? null : `-${themeName}`),
|
|
8051
|
+
selector: definition?.selector ?? generateSelector(),
|
|
8052
|
+
mediaQuery: definition?.mediaQuery,
|
|
8053
|
+
dataAttribute: definition?.dataAttribute,
|
|
8054
|
+
outputFiles: {
|
|
8055
|
+
...defaultOutputFiles,
|
|
8056
|
+
...definition?.outputFiles
|
|
8057
|
+
}
|
|
8058
|
+
};
|
|
8059
|
+
}
|
|
8060
|
+
function resolveThemesConfig(config) {
|
|
8061
|
+
const base = defaultThemesConfig;
|
|
8062
|
+
const selectorPattern = {
|
|
8063
|
+
default: config?.selectorPattern?.default ?? base.selectorPattern.default,
|
|
8064
|
+
others: config?.selectorPattern?.others ?? base.selectorPattern.others
|
|
8065
|
+
};
|
|
8066
|
+
const defaultThemeName = config?.default?.toLowerCase() ?? base.default;
|
|
8067
|
+
let definitions;
|
|
8068
|
+
if (config?.definitions && Object.keys(config.definitions).length > 0) {
|
|
8069
|
+
definitions = {};
|
|
8070
|
+
for (const [themeName, definition] of Object.entries(config.definitions)) {
|
|
8071
|
+
const normalizedName = themeName.toLowerCase();
|
|
8072
|
+
const isDefaultTheme = definition.isDefault ?? normalizedName === defaultThemeName;
|
|
8073
|
+
const resolvedDef = resolveThemeDefinition(
|
|
8074
|
+
normalizedName,
|
|
8075
|
+
definition,
|
|
8076
|
+
selectorPattern,
|
|
8077
|
+
defaultOutputFileNames,
|
|
8078
|
+
isDefaultTheme
|
|
8079
|
+
);
|
|
8080
|
+
Object.defineProperty(definitions, normalizedName, {
|
|
8081
|
+
value: resolvedDef,
|
|
8082
|
+
writable: true,
|
|
8083
|
+
enumerable: true,
|
|
8084
|
+
configurable: true
|
|
8085
|
+
});
|
|
8086
|
+
}
|
|
8087
|
+
} else {
|
|
8088
|
+
definitions = { ...defaultThemeDefinitions };
|
|
8089
|
+
}
|
|
8090
|
+
return {
|
|
8091
|
+
enabled: config?.enabled ?? base.enabled,
|
|
8092
|
+
autoDetect: config?.autoDetect ?? base.autoDetect,
|
|
8093
|
+
default: defaultThemeName,
|
|
8094
|
+
ignoreModes: config?.ignoreModes ?? [...base.ignoreModes],
|
|
8095
|
+
selectorPattern,
|
|
8096
|
+
definitions
|
|
8097
|
+
};
|
|
8098
|
+
}
|
|
8099
|
+
function resolveIconsConfig(config, options) {
|
|
8100
|
+
const base = defaultIconsConfig;
|
|
8101
|
+
const configDir = options.configDir ?? options.cwd ?? process.cwd();
|
|
8102
|
+
return {
|
|
8103
|
+
sourceDir: config?.sourceDir ? path4__namespace.default.resolve(configDir, config.sourceDir) : base.sourceDir,
|
|
8104
|
+
outputDir: config?.outputDir ? path4__namespace.default.resolve(configDir, config.outputDir) : base.outputDir,
|
|
8105
|
+
framework: config?.framework ?? base.framework,
|
|
8106
|
+
typescript: config?.typescript ?? base.typescript,
|
|
8107
|
+
optimize: config?.optimize ?? base.optimize,
|
|
8108
|
+
prefix: config?.prefix ?? base.prefix
|
|
8109
|
+
};
|
|
8110
|
+
}
|
|
8111
|
+
function resolveTokensConfig(config, options) {
|
|
8112
|
+
const base = defaultTokensConfig;
|
|
8113
|
+
const configDir = options.configDir ?? options.cwd ?? process.cwd();
|
|
8114
|
+
const resolveDir = (dir) => path4__namespace.default.resolve(configDir, dir);
|
|
8115
|
+
const outputDirsMap = new Map(Object.entries(base.outputDirs));
|
|
8116
|
+
if (config?.outputDirs) {
|
|
8117
|
+
for (const [format, dir] of Object.entries(config.outputDirs)) {
|
|
8118
|
+
if (dir !== void 0) {
|
|
8119
|
+
outputDirsMap.set(format, resolveDir(dir));
|
|
7926
8120
|
}
|
|
7927
8121
|
}
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
);
|
|
7935
|
-
var customTransformSchema = zod.z.object({
|
|
7936
|
-
name: zod.z.string().min(1, "Transform name is required"),
|
|
7937
|
-
description: zod.z.string().optional(),
|
|
7938
|
-
type: zod.z.enum(["value", "attribute", "name"]).optional().default("value"),
|
|
7939
|
-
transform: zod.z.function().optional(),
|
|
7940
|
-
filter: zod.z.function().optional(),
|
|
7941
|
-
matcher: zod.z.function().optional()
|
|
7942
|
-
});
|
|
7943
|
-
var customFormatSchema = zod.z.object({
|
|
7944
|
-
name: zod.z.string().min(1, "Format name is required"),
|
|
7945
|
-
description: zod.z.string().optional(),
|
|
7946
|
-
formatter: zod.z.function().optional(),
|
|
7947
|
-
extension: zod.z.string().min(1).optional()
|
|
7948
|
-
});
|
|
7949
|
-
var outputFormatEnum = zod.z.enum(["css", "scss", "js", "ts", "json", "android", "ios"]);
|
|
7950
|
-
var themeDefinitionSchema = zod.z.object({
|
|
7951
|
-
isDefault: zod.z.boolean().optional().default(false),
|
|
7952
|
-
suffix: zod.z.string().nullable().optional(),
|
|
7953
|
-
selector: zod.z.string().min(1, "Theme selector is required"),
|
|
7954
|
-
mediaQuery: zod.z.string().optional(),
|
|
7955
|
-
dataAttribute: zod.z.string().optional(),
|
|
7956
|
-
outputFiles: zod.z.record(outputFormatEnum, zod.z.string()).optional()
|
|
7957
|
-
});
|
|
7958
|
-
var themeSelectorPatternSchema = zod.z.object({
|
|
7959
|
-
default: zod.z.string().optional().default(":root"),
|
|
7960
|
-
others: zod.z.string().optional().default('[data-dsai-theme="{mode}"]')
|
|
7961
|
-
});
|
|
7962
|
-
var themesConfigSchema = zod.z.object({
|
|
7963
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
7964
|
-
autoDetect: zod.z.boolean().optional().default(true),
|
|
7965
|
-
default: zod.z.string().optional().default("light"),
|
|
7966
|
-
ignoreModes: zod.z.array(zod.z.string()).optional().default([]),
|
|
7967
|
-
selectorPattern: themeSelectorPatternSchema.optional(),
|
|
7968
|
-
definitions: zod.z.record(zod.z.string(), themeDefinitionSchema).optional(),
|
|
7969
|
-
// Legacy fields (for backward compatibility)
|
|
7970
|
-
defaultMode: zod.z.enum(["light", "dark", "system"]).optional(),
|
|
7971
|
-
modes: zod.z.record(
|
|
7972
|
-
zod.z.string(),
|
|
7973
|
-
zod.z.object({
|
|
7974
|
-
selector: zod.z.string().min(1),
|
|
7975
|
-
mediaQuery: zod.z.string().optional(),
|
|
7976
|
-
dataAttribute: zod.z.string().optional(),
|
|
7977
|
-
cssVariables: zod.z.boolean().optional(),
|
|
7978
|
-
generateSeparateFiles: zod.z.boolean().optional(),
|
|
7979
|
-
prefix: zod.z.string().optional()
|
|
7980
|
-
})
|
|
7981
|
-
).optional(),
|
|
7982
|
-
outputFileName: zod.z.string().optional(),
|
|
7983
|
-
colorScheme: zod.z.object({
|
|
7984
|
-
light: zod.z.string().optional(),
|
|
7985
|
-
dark: zod.z.string().optional()
|
|
7986
|
-
}).optional()
|
|
7987
|
-
});
|
|
7988
|
-
var iconOptimizationSchema = zod.z.object({
|
|
7989
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
7990
|
-
removeComments: zod.z.boolean().optional().default(true),
|
|
7991
|
-
removeDimensions: zod.z.boolean().optional().default(false),
|
|
7992
|
-
removeViewBox: zod.z.boolean().optional().default(false),
|
|
7993
|
-
removeXMLNS: zod.z.boolean().optional().default(true),
|
|
7994
|
-
cleanupIds: zod.z.boolean().optional().default(true),
|
|
7995
|
-
minify: zod.z.boolean().optional().default(true)
|
|
7996
|
-
});
|
|
7997
|
-
var iconSpriteSchema = zod.z.object({
|
|
7998
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
7999
|
-
fileName: zod.z.string().optional().default("icons"),
|
|
8000
|
-
format: zod.z.enum(["symbol", "stack", "css"]).optional().default("symbol"),
|
|
8001
|
-
prefix: zod.z.string().optional().default("icon-")
|
|
8002
|
-
});
|
|
8003
|
-
var iconsConfigSchema = zod.z.object({
|
|
8004
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
8005
|
-
sourceDir: zod.z.string().optional().default("assets/icons"),
|
|
8006
|
-
outputDir: zod.z.string().optional().default("dist/icons"),
|
|
8007
|
-
formats: zod.z.array(zod.z.enum(["svg", "react", "vue", "sprite", "font"])).optional().default(["svg"]),
|
|
8008
|
-
optimization: iconOptimizationSchema.optional(),
|
|
8009
|
-
sprite: iconSpriteSchema.optional(),
|
|
8010
|
-
componentPrefix: zod.z.string().optional().default("Icon"),
|
|
8011
|
-
componentSuffix: zod.z.string().optional().default(""),
|
|
8012
|
-
generateIndex: zod.z.boolean().optional().default(true),
|
|
8013
|
-
generateTypes: zod.z.boolean().optional().default(true)
|
|
8014
|
-
});
|
|
8015
|
-
var tokenBuildConfigSchema = zod.z.object({
|
|
8016
|
-
format: outputFormatSchema,
|
|
8017
|
-
outputDir: zod.z.string().optional(),
|
|
8018
|
-
outputFileName: zod.z.string().optional(),
|
|
8019
|
-
fileExtension: zod.z.string().optional(),
|
|
8020
|
-
prefix: zod.z.string().optional(),
|
|
8021
|
-
useVariables: zod.z.boolean().optional(),
|
|
8022
|
-
selector: zod.z.string().optional(),
|
|
8023
|
-
transforms: zod.z.array(zod.z.string()).optional(),
|
|
8024
|
-
customTransforms: zod.z.array(customTransformSchema).optional(),
|
|
8025
|
-
filter: zod.z.function().optional(),
|
|
8026
|
-
header: zod.z.string().optional(),
|
|
8027
|
-
footer: zod.z.string().optional()
|
|
8028
|
-
});
|
|
8029
|
-
var postprocessConfigSchema = zod.z.object({
|
|
8030
|
-
enabled: zod.z.boolean().optional(),
|
|
8031
|
-
cssDir: zod.z.string().optional(),
|
|
8032
|
-
files: zod.z.array(zod.z.string()).optional(),
|
|
8033
|
-
replacements: zod.z.array(
|
|
8034
|
-
zod.z.object({
|
|
8035
|
-
description: zod.z.string().optional(),
|
|
8036
|
-
from: zod.z.union([zod.z.string(), zod.z.instanceof(RegExp)]),
|
|
8037
|
-
to: zod.z.string()
|
|
8038
|
-
})
|
|
8039
|
-
).optional()
|
|
8040
|
-
});
|
|
8041
|
-
var scssConfigSchema = zod.z.object({
|
|
8042
|
-
/** Output styles to generate: 'expanded' (readable) or 'compressed' (minified) */
|
|
8043
|
-
outputStyles: zod.z.array(zod.z.enum(["expanded", "compressed"])).optional(),
|
|
8044
|
-
/** Generate source maps for SCSS compilation */
|
|
8045
|
-
generateSourceMaps: zod.z.boolean().optional(),
|
|
8046
|
-
/** Suffix for minified files (e.g., '.min') */
|
|
8047
|
-
minifiedSuffix: zod.z.string().optional(),
|
|
8048
|
-
/** Theme entry point SCSS file */
|
|
8049
|
-
themeEntry: zod.z.string().optional(),
|
|
8050
|
-
/** Utilities entry point SCSS file */
|
|
8051
|
-
utilitiesEntry: zod.z.string().optional(),
|
|
8052
|
-
/** Output directory for compiled CSS files */
|
|
8053
|
-
cssOutputDir: zod.z.string().optional(),
|
|
8054
|
-
/** Additional Sass load paths */
|
|
8055
|
-
loadPaths: zod.z.array(zod.z.string()).optional(),
|
|
8056
|
-
/** Target CSS framework for variable name mapping */
|
|
8057
|
-
framework: zod.z.enum(["bootstrap", "tailwind", "material", "custom"]).optional(),
|
|
8058
|
-
/** Custom token to variable name mappings */
|
|
8059
|
-
nameMapping: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
8060
|
-
/** Output path for Bootstrap-compatible SCSS variables */
|
|
8061
|
-
variablesOutput: zod.z.string().optional()
|
|
8062
|
-
});
|
|
8063
|
-
var tokenCacheConfigSchema = zod.z.object({
|
|
8064
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
8065
|
-
directory: zod.z.string().optional().default(".cache"),
|
|
8066
|
-
hashType: hashTypeSchema.optional().default("content"),
|
|
8067
|
-
maxAge: zod.z.number().optional().default(864e5)
|
|
8068
|
-
});
|
|
8069
|
-
var tokenWatchConfigSchema = zod.z.object({
|
|
8070
|
-
enabled: zod.z.boolean().optional().default(false),
|
|
8071
|
-
debounce: zod.z.number().optional().default(300),
|
|
8072
|
-
clearScreen: zod.z.boolean().optional().default(true),
|
|
8073
|
-
ignorePatterns: zod.z.array(zod.z.string()).optional().default([])
|
|
8074
|
-
});
|
|
8075
|
-
var tokensHooksSchema = zod.z.object({
|
|
8076
|
-
onBuildStart: zod.z.function().optional(),
|
|
8077
|
-
onFormatComplete: zod.z.function().optional(),
|
|
8078
|
-
onAllFormatsComplete: zod.z.function().optional(),
|
|
8079
|
-
onBuildComplete: zod.z.function().optional(),
|
|
8080
|
-
onError: zod.z.function().optional()
|
|
8081
|
-
});
|
|
8082
|
-
var buildPipelineStepSchema = zod.z.enum([
|
|
8083
|
-
"validate",
|
|
8084
|
-
"snapshot",
|
|
8085
|
-
"preprocess",
|
|
8086
|
-
"transform",
|
|
8087
|
-
"style-dictionary",
|
|
8088
|
-
"sync",
|
|
8089
|
-
"sass-theme",
|
|
8090
|
-
"sass-theme-minified",
|
|
8091
|
-
"postprocess",
|
|
8092
|
-
"sass-utilities",
|
|
8093
|
-
"sass-utilities-minified",
|
|
8094
|
-
"bundle"
|
|
8095
|
-
]);
|
|
8096
|
-
var tokensBuildPipelineSchema = zod.z.object({
|
|
8097
|
-
/**
|
|
8098
|
-
* Steps to include in the build.
|
|
8099
|
-
* Order matters - steps run in sequence.
|
|
8100
|
-
* Default includes all steps for full @dsai-io/tokens build.
|
|
8101
|
-
* Simpler packages can use subset like ['validate', 'transform', 'style-dictionary']
|
|
8102
|
-
*/
|
|
8103
|
-
steps: zod.z.array(buildPipelineStepSchema).optional(),
|
|
8104
|
-
/**
|
|
8105
|
-
* Paths configuration for build steps
|
|
8106
|
-
*/
|
|
8107
|
-
paths: zod.z.object({
|
|
8108
|
-
/** Source file for sync step (Style Dictionary JS output) */
|
|
8109
|
-
syncSource: zod.z.string().optional(),
|
|
8110
|
-
/** Target file for sync step */
|
|
8111
|
-
syncTarget: zod.z.string().optional(),
|
|
8112
|
-
/** SCSS theme input file */
|
|
8113
|
-
sassThemeInput: zod.z.string().optional(),
|
|
8114
|
-
/** CSS theme output file */
|
|
8115
|
-
sassThemeOutput: zod.z.string().optional(),
|
|
8116
|
-
/** CSS theme minified output file */
|
|
8117
|
-
sassThemeMinifiedOutput: zod.z.string().optional(),
|
|
8118
|
-
/** SCSS utilities input file */
|
|
8119
|
-
sassUtilitiesInput: zod.z.string().optional(),
|
|
8120
|
-
/** CSS utilities output file */
|
|
8121
|
-
sassUtilitiesOutput: zod.z.string().optional(),
|
|
8122
|
-
/** CSS utilities minified output file */
|
|
8123
|
-
sassUtilitiesMinifiedOutput: zod.z.string().optional()
|
|
8124
|
-
}).optional(),
|
|
8125
|
-
/** Style Dictionary config file name */
|
|
8126
|
-
styleDictionaryConfig: zod.z.string().optional()
|
|
8127
|
-
});
|
|
8128
|
-
var tokensConfigSchema = zod.z.object({
|
|
8129
|
-
enabled: zod.z.boolean().optional().default(true),
|
|
8130
|
-
sourcePatterns: zod.z.array(zod.z.string()).optional().default(["src/tokens/**/*.json", "src/tokens/**/*.yaml"]),
|
|
8131
|
-
outputDirs: zod.z.object({
|
|
8132
|
-
css: zod.z.string().optional().default("dist/css"),
|
|
8133
|
-
scss: zod.z.string().optional().default("dist/scss"),
|
|
8134
|
-
less: zod.z.string().optional().default("dist/less"),
|
|
8135
|
-
js: zod.z.string().optional().default("dist/js"),
|
|
8136
|
-
ts: zod.z.string().optional().default("dist/ts"),
|
|
8137
|
-
json: zod.z.string().optional().default("dist/json")
|
|
8138
|
-
}).optional(),
|
|
8139
|
-
additionalScssDirectories: zod.z.array(zod.z.string()).optional().default([]),
|
|
8140
|
-
outputFileNames: zod.z.object({
|
|
8141
|
-
variables: zod.z.string().optional().default("variables"),
|
|
8142
|
-
utilities: zod.z.string().optional().default("utilities"),
|
|
8143
|
-
mixins: zod.z.string().optional().default("mixins"),
|
|
8144
|
-
tokens: zod.z.string().optional().default("tokens")
|
|
8145
|
-
}).optional(),
|
|
8146
|
-
prefix: zod.z.string().optional().default("dsai"),
|
|
8147
|
-
mergeOrder: zod.z.array(zod.z.string()).optional().default(["base", "semantic", "component"]),
|
|
8148
|
-
createBundle: zod.z.boolean().optional().default(true),
|
|
8149
|
-
bundleFileName: zod.z.string().optional().default("bundle"),
|
|
8150
|
-
formats: zod.z.array(outputFormatSchema).optional().default(["css", "scss", "json"]),
|
|
8151
|
-
platforms: zod.z.record(zod.z.string(), tokenBuildConfigSchema).optional(),
|
|
8152
|
-
transforms: zod.z.array(zod.z.string()).optional().default([]),
|
|
8153
|
-
customTransforms: zod.z.array(customTransformSchema).optional().default([]),
|
|
8154
|
-
customFormats: zod.z.array(customFormatSchema).optional().default([]),
|
|
8155
|
-
hooks: tokensHooksSchema.optional(),
|
|
8156
|
-
cache: tokenCacheConfigSchema.optional(),
|
|
8157
|
-
watch: tokenWatchConfigSchema.optional(),
|
|
8158
|
-
verbose: zod.z.boolean().optional().default(false),
|
|
8159
|
-
/** SCSS/CSS output configuration */
|
|
8160
|
-
scss: scssConfigSchema.optional(),
|
|
8161
|
-
/** Build pipeline configuration */
|
|
8162
|
-
pipeline: tokensBuildPipelineSchema.optional(),
|
|
8163
|
-
/** Postprocess configuration */
|
|
8164
|
-
postprocess: postprocessConfigSchema.optional()
|
|
8165
|
-
});
|
|
8166
|
-
var buildConfigSchema = zod.z.object({
|
|
8167
|
-
outDir: zod.z.string().optional().default("dist"),
|
|
8168
|
-
clean: zod.z.boolean().optional().default(true),
|
|
8169
|
-
sourcemap: zod.z.boolean().optional().default(false),
|
|
8170
|
-
minify: zod.z.boolean().optional().default(true),
|
|
8171
|
-
parallel: zod.z.boolean().optional().default(true),
|
|
8172
|
-
maxConcurrency: zod.z.number().optional().default(4)
|
|
8173
|
-
});
|
|
8174
|
-
var globalConfigSchema = zod.z.object({
|
|
8175
|
-
logLevel: logLevelSchema.optional().default("info"),
|
|
8176
|
-
colors: zod.z.boolean().optional().default(true),
|
|
8177
|
-
ci: zod.z.boolean().optional().default(false),
|
|
8178
|
-
dryRun: zod.z.boolean().optional().default(false),
|
|
8179
|
-
cwd: zod.z.string().optional(),
|
|
8180
|
-
configPath: zod.z.string().optional(),
|
|
8181
|
-
framework: frameworkSchema.optional(),
|
|
8182
|
-
build: buildConfigSchema.optional()
|
|
8183
|
-
});
|
|
8184
|
-
zod.z.object({
|
|
8185
|
-
$schema: zod.z.string().optional(),
|
|
8186
|
-
extends: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional(),
|
|
8187
|
-
global: globalConfigSchema.optional(),
|
|
8188
|
-
tokens: tokensConfigSchema.optional(),
|
|
8189
|
-
themes: themesConfigSchema.optional(),
|
|
8190
|
-
icons: iconsConfigSchema.optional()
|
|
8191
|
-
});
|
|
8192
|
-
|
|
8193
|
-
// src/config/defaults.ts
|
|
8194
|
-
var DEFAULT_PREFIX = "--dsai-";
|
|
8195
|
-
var DEFAULT_LOG_LEVEL = "info";
|
|
8196
|
-
var DEFAULT_OUTPUT_DIR = "dist";
|
|
8197
|
-
var DEFAULT_SOURCE_DIR = "figma-exports";
|
|
8198
|
-
var DEFAULT_COLLECTIONS_DIR = "collections";
|
|
8199
|
-
var DEFAULT_ICONS_SOURCE_DIR = "icons";
|
|
8200
|
-
var DEFAULT_ICONS_OUTPUT_DIR = "dist/icons";
|
|
8201
|
-
var defaultSourcePatterns = ["theme.json", "tokens.json", "*.tokens.json"];
|
|
8202
|
-
var defaultFormats = ["css", "scss", "js", "ts", "json"];
|
|
8203
|
-
var defaultOutputFileNames = {
|
|
8204
|
-
css: "tokens.css",
|
|
8205
|
-
scss: "_tokens.scss",
|
|
8206
|
-
js: "tokens.js",
|
|
8207
|
-
ts: "tokens.ts",
|
|
8208
|
-
json: "tokens.json",
|
|
8209
|
-
android: "tokens.xml",
|
|
8210
|
-
ios: "tokens.h"
|
|
8211
|
-
};
|
|
8212
|
-
var defaultSelectorPattern = {
|
|
8213
|
-
default: ":root",
|
|
8214
|
-
others: '[data-dsai-theme="{mode}"]'
|
|
8215
|
-
};
|
|
8216
|
-
var defaultThemeDefinitions = {
|
|
8217
|
-
light: {
|
|
8218
|
-
isDefault: true,
|
|
8219
|
-
suffix: null,
|
|
8220
|
-
selector: ":root",
|
|
8221
|
-
outputFiles: {
|
|
8222
|
-
css: "tokens.css",
|
|
8223
|
-
scss: "_tokens.scss",
|
|
8224
|
-
js: "tokens.js",
|
|
8225
|
-
ts: "tokens.ts",
|
|
8226
|
-
json: "tokens.json",
|
|
8227
|
-
android: "tokens.xml",
|
|
8228
|
-
ios: "tokens.h"
|
|
8229
|
-
}
|
|
8230
|
-
},
|
|
8231
|
-
dark: {
|
|
8232
|
-
isDefault: false,
|
|
8233
|
-
suffix: "-dark",
|
|
8234
|
-
selector: '[data-dsai-theme="dark"]',
|
|
8235
|
-
mediaQuery: "(prefers-color-scheme: dark)",
|
|
8236
|
-
outputFiles: {
|
|
8237
|
-
css: "tokens-dark.css",
|
|
8238
|
-
scss: "_tokens-dark.scss",
|
|
8239
|
-
js: "tokens-dark.js",
|
|
8240
|
-
ts: "tokens-dark.ts",
|
|
8241
|
-
json: "tokens-dark.json",
|
|
8242
|
-
android: "tokens-dark.xml",
|
|
8243
|
-
ios: "tokens-dark.h"
|
|
8244
|
-
}
|
|
8245
|
-
}
|
|
8246
|
-
};
|
|
8247
|
-
var defaultThemesConfig = {
|
|
8248
|
-
enabled: true,
|
|
8249
|
-
autoDetect: true,
|
|
8250
|
-
default: "light",
|
|
8251
|
-
ignoreModes: [],
|
|
8252
|
-
selectorPattern: defaultSelectorPattern};
|
|
8253
|
-
var defaultIconFramework = "react";
|
|
8254
|
-
var defaultIconsConfig = {
|
|
8255
|
-
sourceDir: DEFAULT_ICONS_SOURCE_DIR,
|
|
8256
|
-
outputDir: DEFAULT_ICONS_OUTPUT_DIR,
|
|
8257
|
-
framework: defaultIconFramework,
|
|
8258
|
-
typescript: true,
|
|
8259
|
-
optimize: true,
|
|
8260
|
-
prefix: "Icon"
|
|
8261
|
-
};
|
|
8262
|
-
var defaultTokensConfig = {
|
|
8263
|
-
source: "theme",
|
|
8264
|
-
sourceDir: DEFAULT_SOURCE_DIR,
|
|
8265
|
-
collectionsDir: DEFAULT_COLLECTIONS_DIR,
|
|
8266
|
-
sourcePatterns: defaultSourcePatterns,
|
|
8267
|
-
outputDir: DEFAULT_OUTPUT_DIR,
|
|
8268
|
-
outputDirs: {},
|
|
8269
|
-
outputFileNames: defaultOutputFileNames,
|
|
8270
|
-
prefix: DEFAULT_PREFIX,
|
|
8271
|
-
formats: defaultFormats,
|
|
8272
|
-
mergeOrder: "after",
|
|
8273
|
-
createBundle: false,
|
|
8274
|
-
outputReferences: true,
|
|
8275
|
-
baseFontSize: 16,
|
|
8276
|
-
separateThemeFiles: false,
|
|
8277
|
-
watch: false};
|
|
8278
|
-
var defaultGlobalConfig = {
|
|
8279
|
-
cwd: process.cwd(),
|
|
8280
|
-
debug: false,
|
|
8281
|
-
logLevel: DEFAULT_LOG_LEVEL
|
|
8282
|
-
};
|
|
8283
|
-
({
|
|
8284
|
-
configDir: process.cwd()
|
|
8285
|
-
});
|
|
8286
|
-
function resolveGlobalConfig(config, options) {
|
|
8287
|
-
const base = defaultGlobalConfig;
|
|
8288
|
-
const cwd = options.cwd ?? process.cwd();
|
|
8289
|
-
return {
|
|
8290
|
-
cwd: config?.cwd ? path4__namespace.default.resolve(cwd, config.cwd) : cwd,
|
|
8291
|
-
debug: config?.debug ?? base.debug,
|
|
8292
|
-
logLevel: config?.logLevel ?? base.logLevel
|
|
8293
|
-
};
|
|
8294
|
-
}
|
|
8295
|
-
function resolveThemeDefinition(themeName, definition, selectorPattern, _outputFileNames, isDefaultTheme) {
|
|
8296
|
-
const generateOutputFiles = () => {
|
|
8297
|
-
const suffix = isDefaultTheme ? "" : `-${themeName}`;
|
|
8298
|
-
return {
|
|
8299
|
-
css: `tokens${suffix}.css`,
|
|
8300
|
-
scss: `_tokens${suffix}.scss`,
|
|
8301
|
-
js: `tokens${suffix}.js`,
|
|
8302
|
-
ts: `tokens${suffix}.ts`,
|
|
8303
|
-
json: `tokens${suffix}.json`,
|
|
8304
|
-
android: `tokens${suffix}.xml`,
|
|
8305
|
-
ios: `tokens${suffix}.h`
|
|
8306
|
-
};
|
|
8307
|
-
};
|
|
8308
|
-
const generateSelector = () => {
|
|
8309
|
-
if (isDefaultTheme) {
|
|
8310
|
-
return selectorPattern.default;
|
|
8311
|
-
}
|
|
8312
|
-
return selectorPattern.others.replace("{mode}", themeName);
|
|
8313
|
-
};
|
|
8314
|
-
const defaultOutputFiles = generateOutputFiles();
|
|
8315
|
-
return {
|
|
8316
|
-
isDefault: definition?.isDefault ?? isDefaultTheme,
|
|
8317
|
-
suffix: definition?.suffix ?? (isDefaultTheme ? null : `-${themeName}`),
|
|
8318
|
-
selector: definition?.selector ?? generateSelector(),
|
|
8319
|
-
mediaQuery: definition?.mediaQuery,
|
|
8320
|
-
dataAttribute: definition?.dataAttribute,
|
|
8321
|
-
outputFiles: {
|
|
8322
|
-
...defaultOutputFiles,
|
|
8323
|
-
...definition?.outputFiles
|
|
8324
|
-
}
|
|
8325
|
-
};
|
|
8326
|
-
}
|
|
8327
|
-
function resolveThemesConfig(config) {
|
|
8328
|
-
const base = defaultThemesConfig;
|
|
8329
|
-
const selectorPattern = {
|
|
8330
|
-
default: config?.selectorPattern?.default ?? base.selectorPattern.default,
|
|
8331
|
-
others: config?.selectorPattern?.others ?? base.selectorPattern.others
|
|
8332
|
-
};
|
|
8333
|
-
const defaultThemeName = config?.default?.toLowerCase() ?? base.default;
|
|
8334
|
-
let definitions;
|
|
8335
|
-
if (config?.definitions && Object.keys(config.definitions).length > 0) {
|
|
8336
|
-
definitions = {};
|
|
8337
|
-
for (const [themeName, definition] of Object.entries(config.definitions)) {
|
|
8338
|
-
const normalizedName = themeName.toLowerCase();
|
|
8339
|
-
const isDefaultTheme = definition.isDefault ?? normalizedName === defaultThemeName;
|
|
8340
|
-
const resolvedDef = resolveThemeDefinition(
|
|
8341
|
-
normalizedName,
|
|
8342
|
-
definition,
|
|
8343
|
-
selectorPattern,
|
|
8344
|
-
defaultOutputFileNames,
|
|
8345
|
-
isDefaultTheme
|
|
8346
|
-
);
|
|
8347
|
-
Object.defineProperty(definitions, normalizedName, {
|
|
8348
|
-
value: resolvedDef,
|
|
8349
|
-
writable: true,
|
|
8350
|
-
enumerable: true,
|
|
8351
|
-
configurable: true
|
|
8352
|
-
});
|
|
8353
|
-
}
|
|
8354
|
-
} else {
|
|
8355
|
-
definitions = { ...defaultThemeDefinitions };
|
|
8356
|
-
}
|
|
8357
|
-
return {
|
|
8358
|
-
enabled: config?.enabled ?? base.enabled,
|
|
8359
|
-
autoDetect: config?.autoDetect ?? base.autoDetect,
|
|
8360
|
-
default: defaultThemeName,
|
|
8361
|
-
ignoreModes: config?.ignoreModes ?? [...base.ignoreModes],
|
|
8362
|
-
selectorPattern,
|
|
8363
|
-
definitions
|
|
8364
|
-
};
|
|
8365
|
-
}
|
|
8366
|
-
function resolveIconsConfig(config, options) {
|
|
8367
|
-
const base = defaultIconsConfig;
|
|
8368
|
-
const configDir = options.configDir ?? options.cwd ?? process.cwd();
|
|
8369
|
-
return {
|
|
8370
|
-
sourceDir: config?.sourceDir ? path4__namespace.default.resolve(configDir, config.sourceDir) : base.sourceDir,
|
|
8371
|
-
outputDir: config?.outputDir ? path4__namespace.default.resolve(configDir, config.outputDir) : base.outputDir,
|
|
8372
|
-
framework: config?.framework ?? base.framework,
|
|
8373
|
-
typescript: config?.typescript ?? base.typescript,
|
|
8374
|
-
optimize: config?.optimize ?? base.optimize,
|
|
8375
|
-
prefix: config?.prefix ?? base.prefix
|
|
8376
|
-
};
|
|
8377
|
-
}
|
|
8378
|
-
function resolveTokensConfig(config, options) {
|
|
8379
|
-
const base = defaultTokensConfig;
|
|
8380
|
-
const configDir = options.configDir ?? options.cwd ?? process.cwd();
|
|
8381
|
-
const resolveDir = (dir) => path4__namespace.default.resolve(configDir, dir);
|
|
8382
|
-
const outputDirsMap = new Map(Object.entries(base.outputDirs));
|
|
8383
|
-
if (config?.outputDirs) {
|
|
8384
|
-
for (const [format, dir] of Object.entries(config.outputDirs)) {
|
|
8385
|
-
if (dir !== void 0) {
|
|
8386
|
-
outputDirsMap.set(format, resolveDir(dir));
|
|
8387
|
-
}
|
|
8388
|
-
}
|
|
8389
|
-
}
|
|
8390
|
-
const outputDirs = Object.fromEntries(outputDirsMap);
|
|
8391
|
-
const collectionMappingMap = /* @__PURE__ */ new Map();
|
|
8392
|
-
if (config?.collectionMapping) {
|
|
8393
|
-
for (const [name, filePath] of Object.entries(config.collectionMapping)) {
|
|
8394
|
-
collectionMappingMap.set(name, resolveDir(filePath));
|
|
8122
|
+
}
|
|
8123
|
+
const outputDirs = Object.fromEntries(outputDirsMap);
|
|
8124
|
+
const collectionMappingMap = /* @__PURE__ */ new Map();
|
|
8125
|
+
if (config?.collectionMapping) {
|
|
8126
|
+
for (const [name, filePath] of Object.entries(config.collectionMapping)) {
|
|
8127
|
+
collectionMappingMap.set(name, resolveDir(filePath));
|
|
8395
8128
|
}
|
|
8396
8129
|
}
|
|
8397
8130
|
const collectionMapping = Object.fromEntries(collectionMappingMap);
|
|
@@ -8433,10 +8166,32 @@ function resolveTokensConfig(config, options) {
|
|
|
8433
8166
|
postprocess: config?.postprocess
|
|
8434
8167
|
};
|
|
8435
8168
|
}
|
|
8169
|
+
function resolveAliasesConfig(config) {
|
|
8170
|
+
const base = defaultAliasesConfig;
|
|
8171
|
+
return {
|
|
8172
|
+
importAlias: config?.importAlias ?? base.importAlias,
|
|
8173
|
+
ui: config?.ui ?? base.ui,
|
|
8174
|
+
hooks: config?.hooks ?? base.hooks,
|
|
8175
|
+
utils: config?.utils ?? base.utils,
|
|
8176
|
+
components: config?.components ?? base.components,
|
|
8177
|
+
lib: config?.lib ?? base.lib
|
|
8178
|
+
};
|
|
8179
|
+
}
|
|
8180
|
+
function resolveComponentsConfig(config) {
|
|
8181
|
+
const base = defaultComponentsConfig;
|
|
8182
|
+
return {
|
|
8183
|
+
enabled: config?.enabled ?? base.enabled,
|
|
8184
|
+
registryUrl: config?.registryUrl ?? base.registryUrl,
|
|
8185
|
+
tsx: config?.tsx ?? base.tsx,
|
|
8186
|
+
overwrite: config?.overwrite ?? base.overwrite
|
|
8187
|
+
};
|
|
8188
|
+
}
|
|
8436
8189
|
function applyOverrides(config, overrides) {
|
|
8437
8190
|
return {
|
|
8438
8191
|
tokens: overrides.tokens ? { ...config.tokens, ...overrides.tokens } : config.tokens,
|
|
8439
8192
|
icons: overrides.icons ? { ...config.icons, ...overrides.icons } : config.icons,
|
|
8193
|
+
aliases: overrides.aliases ? { ...config.aliases, ...overrides.aliases } : config.aliases,
|
|
8194
|
+
components: overrides.components ? { ...config.components, ...overrides.components } : config.components,
|
|
8440
8195
|
global: overrides.global ? { ...config.global, ...overrides.global } : config.global
|
|
8441
8196
|
};
|
|
8442
8197
|
}
|
|
@@ -8447,6 +8202,8 @@ function resolveConfig(config = {}, options = {}) {
|
|
|
8447
8202
|
global: resolveGlobalConfig(mergedConfig.global, options),
|
|
8448
8203
|
tokens: resolveTokensConfig(mergedConfig.tokens, options),
|
|
8449
8204
|
icons: resolveIconsConfig(mergedConfig.icons, options),
|
|
8205
|
+
aliases: resolveAliasesConfig(mergedConfig.aliases),
|
|
8206
|
+
components: resolveComponentsConfig(mergedConfig.components),
|
|
8450
8207
|
configDir
|
|
8451
8208
|
};
|
|
8452
8209
|
}
|
|
@@ -8511,10 +8268,215 @@ async function loadConfig(options = {}) {
|
|
|
8511
8268
|
warnings
|
|
8512
8269
|
};
|
|
8513
8270
|
}
|
|
8271
|
+
function loadItem(name, registryDir) {
|
|
8272
|
+
const subdirs = ["components", "hooks", "utils", "lib", "styles", "types"];
|
|
8273
|
+
for (const sub of subdirs) {
|
|
8274
|
+
const filePath = path4.join(registryDir, sub, `${name}.json`);
|
|
8275
|
+
if (fs3.existsSync(filePath)) {
|
|
8276
|
+
return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
8277
|
+
}
|
|
8278
|
+
}
|
|
8279
|
+
return null;
|
|
8280
|
+
}
|
|
8281
|
+
function resolveTree(names, registryDir) {
|
|
8282
|
+
const visited = /* @__PURE__ */ new Map();
|
|
8283
|
+
const queue = [...names];
|
|
8284
|
+
while (queue.length > 0) {
|
|
8285
|
+
const name = queue.shift();
|
|
8286
|
+
if (visited.has(name)) continue;
|
|
8287
|
+
const item = loadItem(name, registryDir);
|
|
8288
|
+
if (!item) {
|
|
8289
|
+
throw new Error(`Registry item "${name}" not found. Run \`dsai registry build\` or check the name.`);
|
|
8290
|
+
}
|
|
8291
|
+
visited.set(name, item);
|
|
8292
|
+
for (const dep of item.registryDependencies) {
|
|
8293
|
+
if (!visited.has(dep)) queue.push(dep);
|
|
8294
|
+
}
|
|
8295
|
+
}
|
|
8296
|
+
const inDeg = /* @__PURE__ */ new Map();
|
|
8297
|
+
for (const [name, item] of visited) {
|
|
8298
|
+
inDeg.set(name, item.registryDependencies.filter((d3) => visited.has(d3)).length);
|
|
8299
|
+
}
|
|
8300
|
+
const sorted = [];
|
|
8301
|
+
const ready = [];
|
|
8302
|
+
for (const [name, deg] of inDeg) {
|
|
8303
|
+
if (deg === 0) ready.push(name);
|
|
8304
|
+
}
|
|
8305
|
+
while (ready.length > 0) {
|
|
8306
|
+
const name = ready.shift();
|
|
8307
|
+
sorted.push(visited.get(name));
|
|
8308
|
+
for (const [otherName, otherItem] of visited) {
|
|
8309
|
+
if (otherItem.registryDependencies.includes(name)) {
|
|
8310
|
+
const newDeg = (inDeg.get(otherName) ?? 1) - 1;
|
|
8311
|
+
inDeg.set(otherName, newDeg);
|
|
8312
|
+
if (newDeg === 0) ready.push(otherName);
|
|
8313
|
+
}
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8316
|
+
if (sorted.length !== visited.size) {
|
|
8317
|
+
const missing = [...visited.keys()].filter((n) => !sorted.some((s) => s.name === n));
|
|
8318
|
+
throw new Error(`Circular dependency detected involving: ${missing.join(", ")}`);
|
|
8319
|
+
}
|
|
8320
|
+
const allDeps = /* @__PURE__ */ new Set();
|
|
8321
|
+
const allDevDeps = /* @__PURE__ */ new Set();
|
|
8322
|
+
const lightVars = {};
|
|
8323
|
+
const darkVars = {};
|
|
8324
|
+
for (const item of sorted) {
|
|
8325
|
+
for (const dep of item.dependencies) allDeps.add(dep);
|
|
8326
|
+
for (const dep of item.devDependencies) allDevDeps.add(dep);
|
|
8327
|
+
if (item.cssVars?.light) Object.assign(lightVars, item.cssVars.light);
|
|
8328
|
+
if (item.cssVars?.dark) Object.assign(darkVars, item.cssVars.dark);
|
|
8329
|
+
}
|
|
8330
|
+
return {
|
|
8331
|
+
items: sorted,
|
|
8332
|
+
dependencies: [...allDeps],
|
|
8333
|
+
devDependencies: [...allDevDeps],
|
|
8334
|
+
cssVars: { light: lightVars, dark: darkVars }
|
|
8335
|
+
};
|
|
8336
|
+
}
|
|
8514
8337
|
|
|
8515
|
-
// src/
|
|
8516
|
-
|
|
8517
|
-
|
|
8338
|
+
// src/registry/transformer.ts
|
|
8339
|
+
function transformImports(content, options) {
|
|
8340
|
+
const { aliases } = options;
|
|
8341
|
+
let result = content;
|
|
8342
|
+
result = result.replace(
|
|
8343
|
+
/(from\s+['"])(?:\.\.\/)+types(?:\/([^'"]+))?(['"])/g,
|
|
8344
|
+
(_match, prefix, subpath, suffix) => {
|
|
8345
|
+
if (subpath) {
|
|
8346
|
+
return `${prefix}${aliases.importAlias}${aliases.components}/types/${subpath}${suffix}`;
|
|
8347
|
+
}
|
|
8348
|
+
return `${prefix}${aliases.importAlias}${aliases.components}/types${suffix}`;
|
|
8349
|
+
}
|
|
8350
|
+
);
|
|
8351
|
+
result = result.replace(
|
|
8352
|
+
/(from\s+['"])\.\.\/(([A-Z]\w+)(\/[^'"]+)?)(['"])/g,
|
|
8353
|
+
(_match, prefix, _fullPath, dirName, subPath, suffix) => {
|
|
8354
|
+
const kebab = dirName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
8355
|
+
if (subPath) {
|
|
8356
|
+
return `${prefix}${aliases.importAlias}${aliases.ui}/${kebab}${subPath}${suffix}`;
|
|
8357
|
+
}
|
|
8358
|
+
return `${prefix}${aliases.importAlias}${aliases.ui}/${kebab}${suffix}`;
|
|
8359
|
+
}
|
|
8360
|
+
);
|
|
8361
|
+
result = result.replace(
|
|
8362
|
+
/(from\s+['"])(?:\.\.\/)+hooks\/(\w+)(['"])/g,
|
|
8363
|
+
`$1${aliases.importAlias}${aliases.hooks}/$2$3`
|
|
8364
|
+
);
|
|
8365
|
+
result = result.replace(
|
|
8366
|
+
/(from\s+['"])(?:\.\.\/)+utils\/(\w+(?:\/\w+)?)(['"])/g,
|
|
8367
|
+
`$1${aliases.importAlias}${aliases.utils}/$2$3`
|
|
8368
|
+
);
|
|
8369
|
+
result = result.replace(
|
|
8370
|
+
/(from\s+['"])(?:\.\.\/)+utils(['"])/g,
|
|
8371
|
+
`$1${aliases.importAlias}${aliases.utils}$2`
|
|
8372
|
+
);
|
|
8373
|
+
return result;
|
|
8374
|
+
}
|
|
8375
|
+
function normalizeExtensions(content, tsx) {
|
|
8376
|
+
if (!tsx) {
|
|
8377
|
+
return content.replace(/(from\s+['"][^'"]+)\.tsx(['"])/g, "$1.jsx$2").replace(/(from\s+['"][^'"]+)\.ts(['"])/g, "$1.js$2");
|
|
8378
|
+
}
|
|
8379
|
+
return content;
|
|
8380
|
+
}
|
|
8381
|
+
|
|
8382
|
+
// src/registry/writer.ts
|
|
8383
|
+
function getTargetDir(type, aliases) {
|
|
8384
|
+
switch (type) {
|
|
8385
|
+
case "registry:ui":
|
|
8386
|
+
return aliases.ui;
|
|
8387
|
+
case "registry:hook":
|
|
8388
|
+
return aliases.hooks;
|
|
8389
|
+
case "registry:util":
|
|
8390
|
+
return aliases.utils;
|
|
8391
|
+
case "registry:lib":
|
|
8392
|
+
return aliases.lib;
|
|
8393
|
+
case "registry:component":
|
|
8394
|
+
return aliases.components;
|
|
8395
|
+
case "registry:type":
|
|
8396
|
+
return aliases.components;
|
|
8397
|
+
case "registry:style":
|
|
8398
|
+
return aliases.ui;
|
|
8399
|
+
default:
|
|
8400
|
+
return aliases.lib;
|
|
8401
|
+
}
|
|
8402
|
+
}
|
|
8403
|
+
function detectPackageManager(projectDir) {
|
|
8404
|
+
if (fs3.existsSync(path4.join(projectDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
8405
|
+
if (fs3.existsSync(path4.join(projectDir, "bun.lockb")) || fs3.existsSync(path4.join(projectDir, "bun.lock"))) return "bun";
|
|
8406
|
+
if (fs3.existsSync(path4.join(projectDir, "yarn.lock"))) return "yarn";
|
|
8407
|
+
return "npm";
|
|
8408
|
+
}
|
|
8409
|
+
function getInstallArgs(pm, packages, dev) {
|
|
8410
|
+
switch (pm) {
|
|
8411
|
+
case "pnpm":
|
|
8412
|
+
return ["pnpm", ["add", ...[], ...packages]];
|
|
8413
|
+
case "yarn":
|
|
8414
|
+
return ["yarn", ["add", ...[], ...packages]];
|
|
8415
|
+
case "bun":
|
|
8416
|
+
return ["bun", ["add", ...[], ...packages]];
|
|
8417
|
+
default:
|
|
8418
|
+
return ["npm", ["install", ...[], ...packages]];
|
|
8419
|
+
}
|
|
8420
|
+
}
|
|
8421
|
+
function writeRegistryItems(tree, options) {
|
|
8422
|
+
const { projectDir, aliases, components, overwrite, dryRun, log } = options;
|
|
8423
|
+
const result = { written: [], skipped: [], installedDeps: [] };
|
|
8424
|
+
const shouldOverwrite = overwrite ?? components.overwrite;
|
|
8425
|
+
for (const item of tree.items) {
|
|
8426
|
+
const targetBaseDir = getTargetDir(item.type, aliases);
|
|
8427
|
+
for (const file of item.files) {
|
|
8428
|
+
const fileName = path4.basename(file.path);
|
|
8429
|
+
let targetPath;
|
|
8430
|
+
if (file.target) {
|
|
8431
|
+
targetPath = path4.join(projectDir, file.target);
|
|
8432
|
+
} else if (item.type === "registry:ui" || item.type === "registry:component") {
|
|
8433
|
+
targetPath = path4.join(projectDir, targetBaseDir, item.name, fileName);
|
|
8434
|
+
} else if (item.type === "registry:type") {
|
|
8435
|
+
targetPath = path4.join(projectDir, targetBaseDir, file.path);
|
|
8436
|
+
} else {
|
|
8437
|
+
targetPath = path4.join(projectDir, targetBaseDir, fileName);
|
|
8438
|
+
}
|
|
8439
|
+
if (fs3.existsSync(targetPath) && !shouldOverwrite) {
|
|
8440
|
+
if (log) log(` Skipped (exists): ${targetPath}`);
|
|
8441
|
+
result.skipped.push(targetPath);
|
|
8442
|
+
continue;
|
|
8443
|
+
}
|
|
8444
|
+
let content = file.content;
|
|
8445
|
+
content = transformImports(content, { aliases, tsx: components.tsx });
|
|
8446
|
+
content = normalizeExtensions(content, components.tsx);
|
|
8447
|
+
if (dryRun) {
|
|
8448
|
+
if (log) log(` Would write: ${targetPath}`);
|
|
8449
|
+
result.written.push(targetPath);
|
|
8450
|
+
continue;
|
|
8451
|
+
}
|
|
8452
|
+
const dir = path4.dirname(targetPath);
|
|
8453
|
+
if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
|
|
8454
|
+
fs3.writeFileSync(targetPath, content, "utf-8");
|
|
8455
|
+
if (log) log(` Written: ${targetPath}`);
|
|
8456
|
+
result.written.push(targetPath);
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
const depsToInstall = tree.dependencies.filter((dep) => {
|
|
8460
|
+
const pkgJsonPath = path4.join(projectDir, "package.json");
|
|
8461
|
+
if (fs3.existsSync(pkgJsonPath)) {
|
|
8462
|
+
const pkgJson = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
|
|
8463
|
+
const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };
|
|
8464
|
+
return !Reflect.get(allDeps, dep);
|
|
8465
|
+
}
|
|
8466
|
+
return true;
|
|
8467
|
+
});
|
|
8468
|
+
if (depsToInstall.length > 0 && !dryRun) {
|
|
8469
|
+
const pm = detectPackageManager(projectDir);
|
|
8470
|
+
const [cmd, args] = getInstallArgs(pm, depsToInstall);
|
|
8471
|
+
if (log) log(` Installing: ${cmd} ${args.join(" ")}`);
|
|
8472
|
+
child_process.execFileSync(cmd, args, { cwd: projectDir, stdio: "inherit" });
|
|
8473
|
+
result.installedDeps = depsToInstall;
|
|
8474
|
+
} else if (depsToInstall.length > 0 && dryRun) {
|
|
8475
|
+
if (log) log(` Would install: ${depsToInstall.join(", ")}`);
|
|
8476
|
+
result.installedDeps = depsToInstall;
|
|
8477
|
+
}
|
|
8478
|
+
return result;
|
|
8479
|
+
}
|
|
8518
8480
|
|
|
8519
8481
|
// src/cli/types.ts
|
|
8520
8482
|
var ExitCode = {
|
|
@@ -8732,48 +8694,531 @@ function createLogger(options = {}) {
|
|
|
8732
8694
|
console.log(`${prefixStr}${colors_default.muted("DEBUG")} ${colors_default.dim(message)}`);
|
|
8733
8695
|
}
|
|
8734
8696
|
}
|
|
8735
|
-
};
|
|
8736
|
-
}
|
|
8737
|
-
function formatDuration(ms) {
|
|
8738
|
-
if (ms < 1e3) {
|
|
8739
|
-
return `${ms}ms`;
|
|
8740
|
-
}
|
|
8741
|
-
if (ms < 6e4) {
|
|
8742
|
-
return `${(ms / 1e3).toFixed(2)}s`;
|
|
8743
|
-
}
|
|
8744
|
-
const minutes = Math.floor(ms / 6e4);
|
|
8745
|
-
const seconds = (ms % 6e4 / 1e3).toFixed(0);
|
|
8746
|
-
return `${minutes}m ${seconds}s`;
|
|
8747
|
-
}
|
|
8748
|
-
function formatBytes(bytes) {
|
|
8749
|
-
if (bytes === 0) {
|
|
8750
|
-
return "0 B";
|
|
8751
|
-
}
|
|
8752
|
-
const k3 = 1024;
|
|
8753
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k3));
|
|
8754
|
-
const sizeIndex = Math.min(i, 3);
|
|
8755
|
-
let sizeLabel;
|
|
8756
|
-
switch (sizeIndex) {
|
|
8757
|
-
case 0:
|
|
8758
|
-
sizeLabel = "B";
|
|
8759
|
-
break;
|
|
8760
|
-
case 1:
|
|
8761
|
-
sizeLabel = "KB";
|
|
8762
|
-
break;
|
|
8763
|
-
case 2:
|
|
8764
|
-
sizeLabel = "MB";
|
|
8765
|
-
break;
|
|
8766
|
-
default:
|
|
8767
|
-
sizeLabel = "GB";
|
|
8768
|
-
}
|
|
8769
|
-
return `${Number.parseFloat((bytes / k3 ** sizeIndex).toFixed(2))} ${sizeLabel}`;
|
|
8770
|
-
}
|
|
8771
|
-
function formatCount(count, singular, plural) {
|
|
8772
|
-
const label = count === 1 ? singular : plural ?? `${singular}s`;
|
|
8773
|
-
return `${count} ${label}`;
|
|
8697
|
+
};
|
|
8698
|
+
}
|
|
8699
|
+
function formatDuration(ms) {
|
|
8700
|
+
if (ms < 1e3) {
|
|
8701
|
+
return `${ms}ms`;
|
|
8702
|
+
}
|
|
8703
|
+
if (ms < 6e4) {
|
|
8704
|
+
return `${(ms / 1e3).toFixed(2)}s`;
|
|
8705
|
+
}
|
|
8706
|
+
const minutes = Math.floor(ms / 6e4);
|
|
8707
|
+
const seconds = (ms % 6e4 / 1e3).toFixed(0);
|
|
8708
|
+
return `${minutes}m ${seconds}s`;
|
|
8709
|
+
}
|
|
8710
|
+
function formatBytes(bytes) {
|
|
8711
|
+
if (bytes === 0) {
|
|
8712
|
+
return "0 B";
|
|
8713
|
+
}
|
|
8714
|
+
const k3 = 1024;
|
|
8715
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k3));
|
|
8716
|
+
const sizeIndex = Math.min(i, 3);
|
|
8717
|
+
let sizeLabel;
|
|
8718
|
+
switch (sizeIndex) {
|
|
8719
|
+
case 0:
|
|
8720
|
+
sizeLabel = "B";
|
|
8721
|
+
break;
|
|
8722
|
+
case 1:
|
|
8723
|
+
sizeLabel = "KB";
|
|
8724
|
+
break;
|
|
8725
|
+
case 2:
|
|
8726
|
+
sizeLabel = "MB";
|
|
8727
|
+
break;
|
|
8728
|
+
default:
|
|
8729
|
+
sizeLabel = "GB";
|
|
8730
|
+
}
|
|
8731
|
+
return `${Number.parseFloat((bytes / k3 ** sizeIndex).toFixed(2))} ${sizeLabel}`;
|
|
8732
|
+
}
|
|
8733
|
+
function formatCount(count, singular, plural) {
|
|
8734
|
+
const label = count === 1 ? singular : plural ?? `${singular}s`;
|
|
8735
|
+
return `${count} ${label}`;
|
|
8736
|
+
}
|
|
8737
|
+
|
|
8738
|
+
// src/cli/commands/add.ts
|
|
8739
|
+
var VALID_TYPES = ["ui", "hook", "util", "lib", "type", "style"];
|
|
8740
|
+
function createAddCommand() {
|
|
8741
|
+
const cmd = new commander.Command("add").description("Add DSAi items (components, hooks, utils) to your project").argument("[items...]", "Item names to add (e.g., button use-focus-trap cn)").option("--all", "Add all items of the specified type (default: ui)", false).option("--type <type>", "Filter by type: ui, hook, util, lib, type").option("--overwrite", "Overwrite existing files", false).option("--dry-run", "Preview changes without writing files", false).option("--registry <path>", "Path to local registry directory").option("--list", "List all available items", false).action(async (items, opts, cmdObj) => {
|
|
8742
|
+
const parentOpts = cmdObj.parent?.opts() ?? {};
|
|
8743
|
+
const allOpts = {
|
|
8744
|
+
...parentOpts,
|
|
8745
|
+
...opts,
|
|
8746
|
+
dryRun: opts.dryRun || parentOpts.dryRun,
|
|
8747
|
+
overwrite: opts.overwrite || parentOpts.overwrite
|
|
8748
|
+
};
|
|
8749
|
+
const logger = createLogger(allOpts);
|
|
8750
|
+
try {
|
|
8751
|
+
const { config } = await loadConfig({
|
|
8752
|
+
cwd: allOpts.cwd ?? process.cwd(),
|
|
8753
|
+
configPath: allOpts.config
|
|
8754
|
+
});
|
|
8755
|
+
const registryDir = allOpts.registry ? path4.resolve(allOpts.registry) : path4.join(config.configDir, "node_modules", "@dsai-io", "tools", "registry");
|
|
8756
|
+
if (!fs3.existsSync(registryDir)) {
|
|
8757
|
+
logger.error(
|
|
8758
|
+
`Registry not found at: ${registryDir}
|
|
8759
|
+
Run \`dsai registry build\` or use --registry <path>.`
|
|
8760
|
+
);
|
|
8761
|
+
process.exit(ExitCode.GeneralError);
|
|
8762
|
+
}
|
|
8763
|
+
const typeFilter = allOpts.type;
|
|
8764
|
+
if (typeFilter && !VALID_TYPES.includes(typeFilter)) {
|
|
8765
|
+
logger.error(
|
|
8766
|
+
`Invalid type "${typeFilter}". Valid types: ${VALID_TYPES.join(", ")}`
|
|
8767
|
+
);
|
|
8768
|
+
process.exit(ExitCode.GeneralError);
|
|
8769
|
+
}
|
|
8770
|
+
const filterByType = (entries) => {
|
|
8771
|
+
if (!typeFilter) return entries;
|
|
8772
|
+
return entries.filter((i) => i.type === `registry:${typeFilter}`);
|
|
8773
|
+
};
|
|
8774
|
+
if (allOpts.list) {
|
|
8775
|
+
const indexPath = path4.join(registryDir, "index.json");
|
|
8776
|
+
if (!fs3.existsSync(indexPath)) {
|
|
8777
|
+
logger.error("Registry index not found.");
|
|
8778
|
+
process.exit(ExitCode.GeneralError);
|
|
8779
|
+
}
|
|
8780
|
+
const index = JSON.parse(fs3.readFileSync(indexPath, "utf-8"));
|
|
8781
|
+
const filtered = filterByType(index.items);
|
|
8782
|
+
console.log(`
|
|
8783
|
+
${colors.bold("Available items:")}
|
|
8784
|
+
`);
|
|
8785
|
+
const grouped = {};
|
|
8786
|
+
for (const item of filtered) {
|
|
8787
|
+
const type = item.type.replace("registry:", "");
|
|
8788
|
+
if (!grouped[type]) grouped[type] = [];
|
|
8789
|
+
grouped[type].push(item);
|
|
8790
|
+
}
|
|
8791
|
+
const displayOrder = ["ui", "hook", "util", "lib", "type", "style"];
|
|
8792
|
+
for (const type of displayOrder) {
|
|
8793
|
+
const typeItems = grouped[type];
|
|
8794
|
+
if (!typeItems || typeItems.length === 0) continue;
|
|
8795
|
+
console.log(` ${colors.cyan(type)} (${typeItems.length}):`);
|
|
8796
|
+
for (const item of typeItems.sort((a, b3) => a.name.localeCompare(b3.name))) {
|
|
8797
|
+
console.log(
|
|
8798
|
+
` ${colors.bold(item.name.padEnd(28))} ${colors.muted(item.description)}`
|
|
8799
|
+
);
|
|
8800
|
+
}
|
|
8801
|
+
console.log();
|
|
8802
|
+
}
|
|
8803
|
+
console.log(` ${colors.muted(`${filtered.length} items available`)}
|
|
8804
|
+
`);
|
|
8805
|
+
console.log(`${colors.muted("Usage:")}`);
|
|
8806
|
+
console.log(` ${colors.command("dsai add button modal")} ${colors.muted("Add specific items")}`);
|
|
8807
|
+
console.log(` ${colors.command("dsai add use-focus-trap cn")} ${colors.muted("Add hooks and utils")}`);
|
|
8808
|
+
console.log(` ${colors.command("dsai add --all")} ${colors.muted("Add all UI components")}`);
|
|
8809
|
+
console.log(` ${colors.command("dsai add --all --type hook")} ${colors.muted("Add all hooks")}`);
|
|
8810
|
+
console.log(` ${colors.command("dsai add --list --type util")} ${colors.muted("List only utilities")}
|
|
8811
|
+
`);
|
|
8812
|
+
return;
|
|
8813
|
+
}
|
|
8814
|
+
if (!allOpts.all && items.length === 0) {
|
|
8815
|
+
logger.error(
|
|
8816
|
+
`No items specified.
|
|
8817
|
+
Usage: ${colors.command("dsai add <item...>")}
|
|
8818
|
+
${colors.command("dsai add --all [--type hook|util]")}
|
|
8819
|
+
${colors.command("dsai add --list")}`
|
|
8820
|
+
);
|
|
8821
|
+
process.exit(ExitCode.GeneralError);
|
|
8822
|
+
}
|
|
8823
|
+
let itemNames = items;
|
|
8824
|
+
if (allOpts.all) {
|
|
8825
|
+
const indexPath = path4.join(registryDir, "index.json");
|
|
8826
|
+
const index = JSON.parse(fs3.readFileSync(indexPath, "utf-8"));
|
|
8827
|
+
const effectiveType = typeFilter ?? "ui";
|
|
8828
|
+
itemNames = index.items.filter((i) => i.type === `registry:${effectiveType}`).map((i) => i.name);
|
|
8829
|
+
if (itemNames.length === 0) {
|
|
8830
|
+
logger.error(`No items found for type "${effectiveType}".`);
|
|
8831
|
+
process.exit(ExitCode.GeneralError);
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8834
|
+
const spinner = createSpinner();
|
|
8835
|
+
spinner.start("Resolving dependencies...");
|
|
8836
|
+
let tree;
|
|
8837
|
+
try {
|
|
8838
|
+
tree = resolveTree(itemNames, registryDir);
|
|
8839
|
+
} catch (err) {
|
|
8840
|
+
spinner.fail("Failed to resolve dependencies");
|
|
8841
|
+
logger.error(err.message);
|
|
8842
|
+
process.exit(ExitCode.GeneralError);
|
|
8843
|
+
}
|
|
8844
|
+
spinner.succeed(
|
|
8845
|
+
`Resolved ${tree.items.length} items (${itemNames.length} requested + ${tree.items.length - itemNames.length} dependencies)`
|
|
8846
|
+
);
|
|
8847
|
+
console.log(`
|
|
8848
|
+
${colors.bold("Items to install:")}`);
|
|
8849
|
+
for (const item of tree.items) {
|
|
8850
|
+
const type = item.type.replace("registry:", "");
|
|
8851
|
+
console.log(` ${colors.cyan(type.padEnd(10))} ${item.name}`);
|
|
8852
|
+
}
|
|
8853
|
+
if (tree.dependencies.length > 0) {
|
|
8854
|
+
console.log(
|
|
8855
|
+
`
|
|
8856
|
+
${colors.bold("npm dependencies:")} ${tree.dependencies.join(", ")}`
|
|
8857
|
+
);
|
|
8858
|
+
}
|
|
8859
|
+
console.log();
|
|
8860
|
+
const writeLabel = allOpts.dryRun ? "Previewing changes..." : "Installing items...";
|
|
8861
|
+
const writeSpinner = createSpinner();
|
|
8862
|
+
writeSpinner.start(writeLabel);
|
|
8863
|
+
const result = writeRegistryItems(tree, {
|
|
8864
|
+
projectDir: config.global.cwd,
|
|
8865
|
+
aliases: config.aliases,
|
|
8866
|
+
components: config.components,
|
|
8867
|
+
overwrite: allOpts.overwrite,
|
|
8868
|
+
dryRun: allOpts.dryRun,
|
|
8869
|
+
log: (msg) => {
|
|
8870
|
+
writeSpinner.stop();
|
|
8871
|
+
console.log(msg);
|
|
8872
|
+
writeSpinner.start(writeLabel);
|
|
8873
|
+
}
|
|
8874
|
+
});
|
|
8875
|
+
writeSpinner.succeed(
|
|
8876
|
+
allOpts.dryRun ? "Dry run complete" : `Installed ${result.written.length} files`
|
|
8877
|
+
);
|
|
8878
|
+
if (result.skipped.length > 0) {
|
|
8879
|
+
console.log(
|
|
8880
|
+
`
|
|
8881
|
+
${colors.warning(`${result.skipped.length} files skipped (already exist). Use --overwrite to replace.`)}`
|
|
8882
|
+
);
|
|
8883
|
+
}
|
|
8884
|
+
if (!allOpts.dryRun) {
|
|
8885
|
+
console.log(`
|
|
8886
|
+
${colors.success("Done!")} Items are ready to use.
|
|
8887
|
+
`);
|
|
8888
|
+
const firstItem = tree.items.find((i) => itemNames.includes(i.name)) ?? tree.items[0];
|
|
8889
|
+
if (firstItem) {
|
|
8890
|
+
const type = firstItem.type.replace("registry:", "");
|
|
8891
|
+
const name = firstItem.name;
|
|
8892
|
+
const titleCase = name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
8893
|
+
console.log(`${colors.muted("Import example:")}`);
|
|
8894
|
+
if (type === "ui" || type === "component") {
|
|
8895
|
+
console.log(
|
|
8896
|
+
` ${colors.cyan(`import { ${titleCase} } from '${config.aliases.importAlias}${config.aliases.ui}/${name}';`)}`
|
|
8897
|
+
);
|
|
8898
|
+
} else if (type === "hook") {
|
|
8899
|
+
console.log(
|
|
8900
|
+
` ${colors.cyan(`import { ${titleCase.replace("Use", "use")} } from '${config.aliases.importAlias}${config.aliases.hooks}/${titleCase.replace("Use", "use")}';`)}`
|
|
8901
|
+
);
|
|
8902
|
+
} else if (type === "util") {
|
|
8903
|
+
console.log(
|
|
8904
|
+
` ${colors.cyan(`import { ${name} } from '${config.aliases.importAlias}${config.aliases.utils}/${name}';`)}`
|
|
8905
|
+
);
|
|
8906
|
+
}
|
|
8907
|
+
console.log();
|
|
8908
|
+
}
|
|
8909
|
+
}
|
|
8910
|
+
} catch (err) {
|
|
8911
|
+
logger.error(`Unexpected error: ${err.message}`);
|
|
8912
|
+
process.exit(ExitCode.GeneralError);
|
|
8913
|
+
}
|
|
8914
|
+
});
|
|
8915
|
+
return cmd;
|
|
8774
8916
|
}
|
|
8917
|
+
var logLevelSchema = zod.z.enum(["silent", "error", "warn", "info", "debug", "verbose"]);
|
|
8918
|
+
var outputFormatSchema = zod.z.enum(["css", "scss", "less", "json", "js", "ts", "esm", "cjs"]);
|
|
8919
|
+
var frameworkSchema = zod.z.enum(["react", "vue", "angular", "svelte", "vanilla"]);
|
|
8920
|
+
var hashTypeSchema = zod.z.enum(["content", "timestamp", "version", "none"]);
|
|
8921
|
+
zod.z.string().min(1, "Glob pattern cannot be empty");
|
|
8922
|
+
zod.z.string().min(1, "File path cannot be empty");
|
|
8923
|
+
zod.z.string().refine(
|
|
8924
|
+
(val) => {
|
|
8925
|
+
const parts = val.split("-");
|
|
8926
|
+
const version2 = parts[0] ?? "";
|
|
8927
|
+
const preRelease = parts[1];
|
|
8928
|
+
const versionParts = version2.split(".");
|
|
8929
|
+
if (versionParts.length !== 3) {
|
|
8930
|
+
return false;
|
|
8931
|
+
}
|
|
8932
|
+
for (const part of versionParts) {
|
|
8933
|
+
const num = Number(part);
|
|
8934
|
+
if (!Number.isInteger(num) || num < 0) {
|
|
8935
|
+
return false;
|
|
8936
|
+
}
|
|
8937
|
+
}
|
|
8938
|
+
if (preRelease !== void 0 && preRelease.length === 0) {
|
|
8939
|
+
return false;
|
|
8940
|
+
}
|
|
8941
|
+
return true;
|
|
8942
|
+
},
|
|
8943
|
+
{ message: "Invalid semantic version format" }
|
|
8944
|
+
);
|
|
8945
|
+
var customTransformSchema = zod.z.object({
|
|
8946
|
+
name: zod.z.string().min(1, "Transform name is required"),
|
|
8947
|
+
description: zod.z.string().optional(),
|
|
8948
|
+
type: zod.z.enum(["value", "attribute", "name"]).optional().default("value"),
|
|
8949
|
+
transform: zod.z.function().optional(),
|
|
8950
|
+
filter: zod.z.function().optional(),
|
|
8951
|
+
matcher: zod.z.function().optional()
|
|
8952
|
+
});
|
|
8953
|
+
var customFormatSchema = zod.z.object({
|
|
8954
|
+
name: zod.z.string().min(1, "Format name is required"),
|
|
8955
|
+
description: zod.z.string().optional(),
|
|
8956
|
+
formatter: zod.z.function().optional(),
|
|
8957
|
+
extension: zod.z.string().min(1).optional()
|
|
8958
|
+
});
|
|
8959
|
+
var outputFormatEnum = zod.z.enum(["css", "scss", "js", "ts", "json", "android", "ios"]);
|
|
8960
|
+
var themeDefinitionSchema = zod.z.object({
|
|
8961
|
+
isDefault: zod.z.boolean().optional().default(false),
|
|
8962
|
+
suffix: zod.z.string().nullable().optional(),
|
|
8963
|
+
selector: zod.z.string().min(1, "Theme selector is required"),
|
|
8964
|
+
mediaQuery: zod.z.string().optional(),
|
|
8965
|
+
dataAttribute: zod.z.string().optional(),
|
|
8966
|
+
outputFiles: zod.z.record(outputFormatEnum, zod.z.string()).optional()
|
|
8967
|
+
});
|
|
8968
|
+
var themeSelectorPatternSchema = zod.z.object({
|
|
8969
|
+
default: zod.z.string().optional().default(":root"),
|
|
8970
|
+
others: zod.z.string().optional().default('[data-dsai-theme="{mode}"]')
|
|
8971
|
+
});
|
|
8972
|
+
var themesConfigSchema = zod.z.object({
|
|
8973
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
8974
|
+
autoDetect: zod.z.boolean().optional().default(true),
|
|
8975
|
+
default: zod.z.string().optional().default("light"),
|
|
8976
|
+
ignoreModes: zod.z.array(zod.z.string()).optional().default([]),
|
|
8977
|
+
selectorPattern: themeSelectorPatternSchema.optional(),
|
|
8978
|
+
definitions: zod.z.record(zod.z.string(), themeDefinitionSchema).optional(),
|
|
8979
|
+
// Legacy fields (for backward compatibility)
|
|
8980
|
+
defaultMode: zod.z.enum(["light", "dark", "system"]).optional(),
|
|
8981
|
+
modes: zod.z.record(
|
|
8982
|
+
zod.z.string(),
|
|
8983
|
+
zod.z.object({
|
|
8984
|
+
selector: zod.z.string().min(1),
|
|
8985
|
+
mediaQuery: zod.z.string().optional(),
|
|
8986
|
+
dataAttribute: zod.z.string().optional(),
|
|
8987
|
+
cssVariables: zod.z.boolean().optional(),
|
|
8988
|
+
generateSeparateFiles: zod.z.boolean().optional(),
|
|
8989
|
+
prefix: zod.z.string().optional()
|
|
8990
|
+
})
|
|
8991
|
+
).optional(),
|
|
8992
|
+
outputFileName: zod.z.string().optional(),
|
|
8993
|
+
colorScheme: zod.z.object({
|
|
8994
|
+
light: zod.z.string().optional(),
|
|
8995
|
+
dark: zod.z.string().optional()
|
|
8996
|
+
}).optional()
|
|
8997
|
+
});
|
|
8998
|
+
var iconOptimizationSchema = zod.z.object({
|
|
8999
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9000
|
+
removeComments: zod.z.boolean().optional().default(true),
|
|
9001
|
+
removeDimensions: zod.z.boolean().optional().default(false),
|
|
9002
|
+
removeViewBox: zod.z.boolean().optional().default(false),
|
|
9003
|
+
removeXMLNS: zod.z.boolean().optional().default(true),
|
|
9004
|
+
cleanupIds: zod.z.boolean().optional().default(true),
|
|
9005
|
+
minify: zod.z.boolean().optional().default(true)
|
|
9006
|
+
});
|
|
9007
|
+
var iconSpriteSchema = zod.z.object({
|
|
9008
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9009
|
+
fileName: zod.z.string().optional().default("icons"),
|
|
9010
|
+
format: zod.z.enum(["symbol", "stack", "css"]).optional().default("symbol"),
|
|
9011
|
+
prefix: zod.z.string().optional().default("icon-")
|
|
9012
|
+
});
|
|
9013
|
+
var iconsConfigSchema = zod.z.object({
|
|
9014
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9015
|
+
sourceDir: zod.z.string().optional().default("assets/icons"),
|
|
9016
|
+
outputDir: zod.z.string().optional().default("dist/icons"),
|
|
9017
|
+
formats: zod.z.array(zod.z.enum(["svg", "react", "vue", "sprite", "font"])).optional().default(["svg"]),
|
|
9018
|
+
optimization: iconOptimizationSchema.optional(),
|
|
9019
|
+
sprite: iconSpriteSchema.optional(),
|
|
9020
|
+
componentPrefix: zod.z.string().optional().default("Icon"),
|
|
9021
|
+
componentSuffix: zod.z.string().optional().default(""),
|
|
9022
|
+
generateIndex: zod.z.boolean().optional().default(true),
|
|
9023
|
+
generateTypes: zod.z.boolean().optional().default(true)
|
|
9024
|
+
});
|
|
9025
|
+
var tokenBuildConfigSchema = zod.z.object({
|
|
9026
|
+
format: outputFormatSchema,
|
|
9027
|
+
outputDir: zod.z.string().optional(),
|
|
9028
|
+
outputFileName: zod.z.string().optional(),
|
|
9029
|
+
fileExtension: zod.z.string().optional(),
|
|
9030
|
+
prefix: zod.z.string().optional(),
|
|
9031
|
+
useVariables: zod.z.boolean().optional(),
|
|
9032
|
+
selector: zod.z.string().optional(),
|
|
9033
|
+
transforms: zod.z.array(zod.z.string()).optional(),
|
|
9034
|
+
customTransforms: zod.z.array(customTransformSchema).optional(),
|
|
9035
|
+
filter: zod.z.function().optional(),
|
|
9036
|
+
header: zod.z.string().optional(),
|
|
9037
|
+
footer: zod.z.string().optional()
|
|
9038
|
+
});
|
|
9039
|
+
var postprocessConfigSchema = zod.z.object({
|
|
9040
|
+
enabled: zod.z.boolean().optional(),
|
|
9041
|
+
cssDir: zod.z.string().optional(),
|
|
9042
|
+
files: zod.z.array(zod.z.string()).optional(),
|
|
9043
|
+
replacements: zod.z.array(
|
|
9044
|
+
zod.z.object({
|
|
9045
|
+
description: zod.z.string().optional(),
|
|
9046
|
+
from: zod.z.union([zod.z.string(), zod.z.instanceof(RegExp)]),
|
|
9047
|
+
to: zod.z.string()
|
|
9048
|
+
})
|
|
9049
|
+
).optional()
|
|
9050
|
+
});
|
|
9051
|
+
var scssConfigSchema = zod.z.object({
|
|
9052
|
+
/** Output styles to generate: 'expanded' (readable) or 'compressed' (minified) */
|
|
9053
|
+
outputStyles: zod.z.array(zod.z.enum(["expanded", "compressed"])).optional(),
|
|
9054
|
+
/** Generate source maps for SCSS compilation */
|
|
9055
|
+
generateSourceMaps: zod.z.boolean().optional(),
|
|
9056
|
+
/** Suffix for minified files (e.g., '.min') */
|
|
9057
|
+
minifiedSuffix: zod.z.string().optional(),
|
|
9058
|
+
/** Theme entry point SCSS file */
|
|
9059
|
+
themeEntry: zod.z.string().optional(),
|
|
9060
|
+
/** Utilities entry point SCSS file */
|
|
9061
|
+
utilitiesEntry: zod.z.string().optional(),
|
|
9062
|
+
/** Output directory for compiled CSS files */
|
|
9063
|
+
cssOutputDir: zod.z.string().optional(),
|
|
9064
|
+
/** Additional Sass load paths */
|
|
9065
|
+
loadPaths: zod.z.array(zod.z.string()).optional(),
|
|
9066
|
+
/** Target CSS framework for variable name mapping */
|
|
9067
|
+
framework: zod.z.enum(["bootstrap", "tailwind", "material", "custom"]).optional(),
|
|
9068
|
+
/** Custom token to variable name mappings */
|
|
9069
|
+
nameMapping: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
9070
|
+
/** Output path for Bootstrap-compatible SCSS variables */
|
|
9071
|
+
variablesOutput: zod.z.string().optional()
|
|
9072
|
+
});
|
|
9073
|
+
var tokenCacheConfigSchema = zod.z.object({
|
|
9074
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9075
|
+
directory: zod.z.string().optional().default(".cache"),
|
|
9076
|
+
hashType: hashTypeSchema.optional().default("content"),
|
|
9077
|
+
maxAge: zod.z.number().optional().default(864e5)
|
|
9078
|
+
});
|
|
9079
|
+
var tokenWatchConfigSchema = zod.z.object({
|
|
9080
|
+
enabled: zod.z.boolean().optional().default(false),
|
|
9081
|
+
debounce: zod.z.number().optional().default(300),
|
|
9082
|
+
clearScreen: zod.z.boolean().optional().default(true),
|
|
9083
|
+
ignorePatterns: zod.z.array(zod.z.string()).optional().default([])
|
|
9084
|
+
});
|
|
9085
|
+
var tokensHooksSchema = zod.z.object({
|
|
9086
|
+
onBuildStart: zod.z.function().optional(),
|
|
9087
|
+
onFormatComplete: zod.z.function().optional(),
|
|
9088
|
+
onAllFormatsComplete: zod.z.function().optional(),
|
|
9089
|
+
onBuildComplete: zod.z.function().optional(),
|
|
9090
|
+
onError: zod.z.function().optional()
|
|
9091
|
+
});
|
|
9092
|
+
var buildPipelineStepSchema = zod.z.enum([
|
|
9093
|
+
"validate",
|
|
9094
|
+
"snapshot",
|
|
9095
|
+
"preprocess",
|
|
9096
|
+
"transform",
|
|
9097
|
+
"style-dictionary",
|
|
9098
|
+
"sync",
|
|
9099
|
+
"sass-theme",
|
|
9100
|
+
"sass-theme-minified",
|
|
9101
|
+
"postprocess",
|
|
9102
|
+
"sass-utilities",
|
|
9103
|
+
"sass-utilities-minified",
|
|
9104
|
+
"bundle"
|
|
9105
|
+
]);
|
|
9106
|
+
var tokensBuildPipelineSchema = zod.z.object({
|
|
9107
|
+
/**
|
|
9108
|
+
* Steps to include in the build.
|
|
9109
|
+
* Order matters - steps run in sequence.
|
|
9110
|
+
* Default includes all steps for full @dsai-io/tokens build.
|
|
9111
|
+
* Simpler packages can use subset like ['validate', 'transform', 'style-dictionary']
|
|
9112
|
+
*/
|
|
9113
|
+
steps: zod.z.array(buildPipelineStepSchema).optional(),
|
|
9114
|
+
/**
|
|
9115
|
+
* Paths configuration for build steps
|
|
9116
|
+
*/
|
|
9117
|
+
paths: zod.z.object({
|
|
9118
|
+
/** Source file for sync step (Style Dictionary JS output) */
|
|
9119
|
+
syncSource: zod.z.string().optional(),
|
|
9120
|
+
/** Target file for sync step */
|
|
9121
|
+
syncTarget: zod.z.string().optional(),
|
|
9122
|
+
/** SCSS theme input file */
|
|
9123
|
+
sassThemeInput: zod.z.string().optional(),
|
|
9124
|
+
/** CSS theme output file */
|
|
9125
|
+
sassThemeOutput: zod.z.string().optional(),
|
|
9126
|
+
/** CSS theme minified output file */
|
|
9127
|
+
sassThemeMinifiedOutput: zod.z.string().optional(),
|
|
9128
|
+
/** SCSS utilities input file */
|
|
9129
|
+
sassUtilitiesInput: zod.z.string().optional(),
|
|
9130
|
+
/** CSS utilities output file */
|
|
9131
|
+
sassUtilitiesOutput: zod.z.string().optional(),
|
|
9132
|
+
/** CSS utilities minified output file */
|
|
9133
|
+
sassUtilitiesMinifiedOutput: zod.z.string().optional()
|
|
9134
|
+
}).optional(),
|
|
9135
|
+
/** Style Dictionary config file name */
|
|
9136
|
+
styleDictionaryConfig: zod.z.string().optional()
|
|
9137
|
+
});
|
|
9138
|
+
var tokensConfigSchema = zod.z.object({
|
|
9139
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9140
|
+
sourcePatterns: zod.z.array(zod.z.string()).optional().default(["src/tokens/**/*.json", "src/tokens/**/*.yaml"]),
|
|
9141
|
+
outputDirs: zod.z.object({
|
|
9142
|
+
css: zod.z.string().optional().default("dist/css"),
|
|
9143
|
+
scss: zod.z.string().optional().default("dist/scss"),
|
|
9144
|
+
less: zod.z.string().optional().default("dist/less"),
|
|
9145
|
+
js: zod.z.string().optional().default("dist/js"),
|
|
9146
|
+
ts: zod.z.string().optional().default("dist/ts"),
|
|
9147
|
+
json: zod.z.string().optional().default("dist/json")
|
|
9148
|
+
}).optional(),
|
|
9149
|
+
additionalScssDirectories: zod.z.array(zod.z.string()).optional().default([]),
|
|
9150
|
+
outputFileNames: zod.z.object({
|
|
9151
|
+
variables: zod.z.string().optional().default("variables"),
|
|
9152
|
+
utilities: zod.z.string().optional().default("utilities"),
|
|
9153
|
+
mixins: zod.z.string().optional().default("mixins"),
|
|
9154
|
+
tokens: zod.z.string().optional().default("tokens")
|
|
9155
|
+
}).optional(),
|
|
9156
|
+
prefix: zod.z.string().optional().default("dsai"),
|
|
9157
|
+
mergeOrder: zod.z.array(zod.z.string()).optional().default(["base", "semantic", "component"]),
|
|
9158
|
+
createBundle: zod.z.boolean().optional().default(true),
|
|
9159
|
+
bundleFileName: zod.z.string().optional().default("bundle"),
|
|
9160
|
+
formats: zod.z.array(outputFormatSchema).optional().default(["css", "scss", "json"]),
|
|
9161
|
+
platforms: zod.z.record(zod.z.string(), tokenBuildConfigSchema).optional(),
|
|
9162
|
+
transforms: zod.z.array(zod.z.string()).optional().default([]),
|
|
9163
|
+
customTransforms: zod.z.array(customTransformSchema).optional().default([]),
|
|
9164
|
+
customFormats: zod.z.array(customFormatSchema).optional().default([]),
|
|
9165
|
+
hooks: tokensHooksSchema.optional(),
|
|
9166
|
+
cache: tokenCacheConfigSchema.optional(),
|
|
9167
|
+
watch: tokenWatchConfigSchema.optional(),
|
|
9168
|
+
verbose: zod.z.boolean().optional().default(false),
|
|
9169
|
+
/** SCSS/CSS output configuration */
|
|
9170
|
+
scss: scssConfigSchema.optional(),
|
|
9171
|
+
/** Build pipeline configuration */
|
|
9172
|
+
pipeline: tokensBuildPipelineSchema.optional(),
|
|
9173
|
+
/** Postprocess configuration */
|
|
9174
|
+
postprocess: postprocessConfigSchema.optional()
|
|
9175
|
+
});
|
|
9176
|
+
var buildConfigSchema = zod.z.object({
|
|
9177
|
+
outDir: zod.z.string().optional().default("dist"),
|
|
9178
|
+
clean: zod.z.boolean().optional().default(true),
|
|
9179
|
+
sourcemap: zod.z.boolean().optional().default(false),
|
|
9180
|
+
minify: zod.z.boolean().optional().default(true),
|
|
9181
|
+
parallel: zod.z.boolean().optional().default(true),
|
|
9182
|
+
maxConcurrency: zod.z.number().optional().default(4)
|
|
9183
|
+
});
|
|
9184
|
+
var globalConfigSchema = zod.z.object({
|
|
9185
|
+
logLevel: logLevelSchema.optional().default("info"),
|
|
9186
|
+
colors: zod.z.boolean().optional().default(true),
|
|
9187
|
+
ci: zod.z.boolean().optional().default(false),
|
|
9188
|
+
dryRun: zod.z.boolean().optional().default(false),
|
|
9189
|
+
cwd: zod.z.string().optional(),
|
|
9190
|
+
configPath: zod.z.string().optional(),
|
|
9191
|
+
framework: frameworkSchema.optional(),
|
|
9192
|
+
build: buildConfigSchema.optional()
|
|
9193
|
+
});
|
|
9194
|
+
var aliasesConfigSchema = zod.z.object({
|
|
9195
|
+
importAlias: zod.z.string().optional().default("@/"),
|
|
9196
|
+
ui: zod.z.string().optional().default("src/components/ui"),
|
|
9197
|
+
hooks: zod.z.string().optional().default("src/hooks"),
|
|
9198
|
+
utils: zod.z.string().optional().default("src/lib/utils"),
|
|
9199
|
+
components: zod.z.string().optional().default("src/components"),
|
|
9200
|
+
lib: zod.z.string().optional().default("src/lib")
|
|
9201
|
+
});
|
|
9202
|
+
var componentsConfigSchema = zod.z.object({
|
|
9203
|
+
enabled: zod.z.boolean().optional().default(true),
|
|
9204
|
+
registryUrl: zod.z.string().optional().default("https://registry.dsai.dev"),
|
|
9205
|
+
tsx: zod.z.boolean().optional().default(true),
|
|
9206
|
+
overwrite: zod.z.boolean().optional().default(false)
|
|
9207
|
+
});
|
|
9208
|
+
zod.z.object({
|
|
9209
|
+
$schema: zod.z.string().optional(),
|
|
9210
|
+
extends: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional(),
|
|
9211
|
+
global: globalConfigSchema.optional(),
|
|
9212
|
+
tokens: tokensConfigSchema.optional(),
|
|
9213
|
+
themes: themesConfigSchema.optional(),
|
|
9214
|
+
icons: iconsConfigSchema.optional(),
|
|
9215
|
+
aliases: aliasesConfigSchema.optional(),
|
|
9216
|
+
components: componentsConfigSchema.optional()
|
|
9217
|
+
});
|
|
8775
9218
|
|
|
8776
9219
|
// src/cli/commands/tokens.ts
|
|
9220
|
+
init_tokens();
|
|
9221
|
+
init_snapshot();
|
|
8777
9222
|
function createTokensCommand() {
|
|
8778
9223
|
const tokens = new commander.Command("tokens").description("Design token operations").helpCommand("help [command]", "Show help for a command");
|
|
8779
9224
|
tokens.command("build").description("Build design tokens").option("-p, --platforms <platforms>", "Platforms to build (comma-separated)", "all").option("-w, --watch", "Watch mode", false).option("--clean", "Clean output before build", false).option("--theme <name>", "Build only a specific theme (e.g., dark)").option("--list-themes", "List available themes from config").action(async (options, command) => {
|
|
@@ -10457,7 +10902,7 @@ function safeReadFile(basePath, ...relativePath) {
|
|
|
10457
10902
|
return void 0;
|
|
10458
10903
|
}
|
|
10459
10904
|
}
|
|
10460
|
-
function
|
|
10905
|
+
function detectPackageManager2(cwd) {
|
|
10461
10906
|
const basePath = path4.resolve(cwd);
|
|
10462
10907
|
if (safeExists(basePath, "bun.lockb") || safeExists(basePath, "bun.lock")) {
|
|
10463
10908
|
return "bun";
|
|
@@ -10772,7 +11217,7 @@ function detectProject(cwd = process.cwd()) {
|
|
|
10772
11217
|
isMonorepo: false,
|
|
10773
11218
|
framework: "unknown",
|
|
10774
11219
|
metaFramework: "none",
|
|
10775
|
-
packageManager:
|
|
11220
|
+
packageManager: detectPackageManager2(basePath),
|
|
10776
11221
|
typescript: false,
|
|
10777
11222
|
esm: false,
|
|
10778
11223
|
styling: "unknown",
|
|
@@ -10787,7 +11232,7 @@ function detectProject(cwd = process.cwd()) {
|
|
|
10787
11232
|
monorepoTool: monorepoInfo.tool,
|
|
10788
11233
|
framework: detectFramework(packageJson),
|
|
10789
11234
|
metaFramework: detectMetaFramework(packageJson, basePath),
|
|
10790
|
-
packageManager:
|
|
11235
|
+
packageManager: detectPackageManager2(basePath),
|
|
10791
11236
|
typescript: detectTypeScript(packageJson, basePath),
|
|
10792
11237
|
esm: detectESM(packageJson, basePath),
|
|
10793
11238
|
styling: detectStyling(packageJson, basePath),
|
|
@@ -13011,6 +13456,941 @@ async function runConfig(options) {
|
|
|
13011
13456
|
}
|
|
13012
13457
|
}
|
|
13013
13458
|
|
|
13459
|
+
// src/registry/component-map.ts
|
|
13460
|
+
var componentMap = {
|
|
13461
|
+
accordion: {
|
|
13462
|
+
type: "registry:ui",
|
|
13463
|
+
title: "Accordion",
|
|
13464
|
+
description: "Collapsible content panels for presenting information in a limited space.",
|
|
13465
|
+
categories: ["disclosure", "layout"]
|
|
13466
|
+
},
|
|
13467
|
+
alert: {
|
|
13468
|
+
type: "registry:ui",
|
|
13469
|
+
title: "Alert",
|
|
13470
|
+
description: "Contextual feedback messages for user actions.",
|
|
13471
|
+
categories: ["feedback"]
|
|
13472
|
+
},
|
|
13473
|
+
avatar: {
|
|
13474
|
+
type: "registry:ui",
|
|
13475
|
+
title: "Avatar",
|
|
13476
|
+
description: "Graphical representation of a user or entity.",
|
|
13477
|
+
categories: ["data-display"]
|
|
13478
|
+
},
|
|
13479
|
+
badge: {
|
|
13480
|
+
type: "registry:ui",
|
|
13481
|
+
title: "Badge",
|
|
13482
|
+
description: "Small count or status indicator, typically displayed on other elements.",
|
|
13483
|
+
categories: ["data-display"]
|
|
13484
|
+
},
|
|
13485
|
+
breadcrumb: {
|
|
13486
|
+
type: "registry:ui",
|
|
13487
|
+
title: "Breadcrumb",
|
|
13488
|
+
description: "Navigation aid showing the current page location within a hierarchy.",
|
|
13489
|
+
categories: ["navigation"]
|
|
13490
|
+
},
|
|
13491
|
+
button: {
|
|
13492
|
+
type: "registry:ui",
|
|
13493
|
+
title: "Button",
|
|
13494
|
+
description: "Trigger for actions and events.",
|
|
13495
|
+
categories: ["actions"]
|
|
13496
|
+
},
|
|
13497
|
+
card: {
|
|
13498
|
+
type: "registry:ui",
|
|
13499
|
+
title: "Card",
|
|
13500
|
+
description: "Flexible container for grouping related content and actions.",
|
|
13501
|
+
categories: ["layout", "data-display"]
|
|
13502
|
+
},
|
|
13503
|
+
"card-list": {
|
|
13504
|
+
type: "registry:ui",
|
|
13505
|
+
title: "CardList",
|
|
13506
|
+
description: "Responsive list of selectable cards with keyboard navigation.",
|
|
13507
|
+
categories: ["layout", "data-display"]
|
|
13508
|
+
},
|
|
13509
|
+
carousel: {
|
|
13510
|
+
type: "registry:ui",
|
|
13511
|
+
title: "Carousel",
|
|
13512
|
+
description: "Slideshow component for cycling through content.",
|
|
13513
|
+
categories: ["data-display"]
|
|
13514
|
+
},
|
|
13515
|
+
checkbox: {
|
|
13516
|
+
type: "registry:ui",
|
|
13517
|
+
title: "Checkbox",
|
|
13518
|
+
description: "Toggle control for boolean selections.",
|
|
13519
|
+
categories: ["forms"]
|
|
13520
|
+
},
|
|
13521
|
+
"checkbox-group": {
|
|
13522
|
+
type: "registry:ui",
|
|
13523
|
+
title: "CheckboxGroup",
|
|
13524
|
+
description: "Managed group of checkboxes with shared state.",
|
|
13525
|
+
categories: ["forms"]
|
|
13526
|
+
},
|
|
13527
|
+
dropdown: {
|
|
13528
|
+
type: "registry:ui",
|
|
13529
|
+
title: "Dropdown",
|
|
13530
|
+
description: "Toggleable overlay menu for displaying a list of actions.",
|
|
13531
|
+
categories: ["navigation", "actions"],
|
|
13532
|
+
npmDependencies: ["@floating-ui/react"]
|
|
13533
|
+
},
|
|
13534
|
+
icon: {
|
|
13535
|
+
type: "registry:ui",
|
|
13536
|
+
title: "Icon",
|
|
13537
|
+
description: "Scalable vector icon component with accessibility support.",
|
|
13538
|
+
categories: ["data-display"]
|
|
13539
|
+
},
|
|
13540
|
+
input: {
|
|
13541
|
+
type: "registry:ui",
|
|
13542
|
+
title: "Input",
|
|
13543
|
+
description: "Text input field with validation and formatting support.",
|
|
13544
|
+
categories: ["forms"]
|
|
13545
|
+
},
|
|
13546
|
+
"list-group": {
|
|
13547
|
+
type: "registry:ui",
|
|
13548
|
+
title: "ListGroup",
|
|
13549
|
+
description: "Flexible component for displaying a series of items.",
|
|
13550
|
+
categories: ["data-display", "navigation"]
|
|
13551
|
+
},
|
|
13552
|
+
modal: {
|
|
13553
|
+
type: "registry:ui",
|
|
13554
|
+
title: "Modal",
|
|
13555
|
+
description: "Dialog overlay for focused content and user interactions.",
|
|
13556
|
+
categories: ["feedback", "disclosure"]
|
|
13557
|
+
},
|
|
13558
|
+
navbar: {
|
|
13559
|
+
type: "registry:ui",
|
|
13560
|
+
title: "Navbar",
|
|
13561
|
+
description: "Responsive navigation header with branding and links.",
|
|
13562
|
+
categories: ["navigation"]
|
|
13563
|
+
},
|
|
13564
|
+
pagination: {
|
|
13565
|
+
type: "registry:ui",
|
|
13566
|
+
title: "Pagination",
|
|
13567
|
+
description: "Navigation controls for paged content.",
|
|
13568
|
+
categories: ["navigation"]
|
|
13569
|
+
},
|
|
13570
|
+
popover: {
|
|
13571
|
+
type: "registry:ui",
|
|
13572
|
+
title: "Popover",
|
|
13573
|
+
description: "Floating content panel anchored to a trigger element.",
|
|
13574
|
+
categories: ["disclosure"],
|
|
13575
|
+
npmDependencies: ["@floating-ui/react"]
|
|
13576
|
+
},
|
|
13577
|
+
progress: {
|
|
13578
|
+
type: "registry:ui",
|
|
13579
|
+
title: "Progress",
|
|
13580
|
+
description: "Visual indicator of task completion.",
|
|
13581
|
+
categories: ["feedback"]
|
|
13582
|
+
},
|
|
13583
|
+
radio: {
|
|
13584
|
+
type: "registry:ui",
|
|
13585
|
+
title: "Radio",
|
|
13586
|
+
description: "Single-select control within a group of options.",
|
|
13587
|
+
categories: ["forms"]
|
|
13588
|
+
},
|
|
13589
|
+
scrollspy: {
|
|
13590
|
+
type: "registry:ui",
|
|
13591
|
+
title: "Scrollspy",
|
|
13592
|
+
description: "Automatically highlights navigation links based on scroll position.",
|
|
13593
|
+
categories: ["navigation"]
|
|
13594
|
+
},
|
|
13595
|
+
select: {
|
|
13596
|
+
type: "registry:ui",
|
|
13597
|
+
title: "Select",
|
|
13598
|
+
description: "Dropdown selector for choosing from a list of options.",
|
|
13599
|
+
categories: ["forms"],
|
|
13600
|
+
npmDependencies: ["@floating-ui/react"]
|
|
13601
|
+
},
|
|
13602
|
+
"selectable-card": {
|
|
13603
|
+
type: "registry:ui",
|
|
13604
|
+
title: "SelectableCard",
|
|
13605
|
+
description: "Card variant that acts as a selectable option.",
|
|
13606
|
+
categories: ["forms", "data-display"]
|
|
13607
|
+
},
|
|
13608
|
+
sheet: {
|
|
13609
|
+
type: "registry:ui",
|
|
13610
|
+
title: "Sheet",
|
|
13611
|
+
description: "Sliding panel overlay from screen edges.",
|
|
13612
|
+
categories: ["disclosure", "layout"]
|
|
13613
|
+
},
|
|
13614
|
+
spinner: {
|
|
13615
|
+
type: "registry:ui",
|
|
13616
|
+
title: "Spinner",
|
|
13617
|
+
description: "Loading indicator for asynchronous operations.",
|
|
13618
|
+
categories: ["feedback"]
|
|
13619
|
+
},
|
|
13620
|
+
switch: {
|
|
13621
|
+
type: "registry:ui",
|
|
13622
|
+
title: "Switch",
|
|
13623
|
+
description: "Toggle control for binary on/off states.",
|
|
13624
|
+
categories: ["forms"]
|
|
13625
|
+
},
|
|
13626
|
+
table: {
|
|
13627
|
+
type: "registry:ui",
|
|
13628
|
+
title: "Table",
|
|
13629
|
+
description: "Data table with sorting, selection, and responsive layout.",
|
|
13630
|
+
categories: ["data-display"]
|
|
13631
|
+
},
|
|
13632
|
+
tabs: {
|
|
13633
|
+
type: "registry:ui",
|
|
13634
|
+
title: "Tabs",
|
|
13635
|
+
description: "Tabbed interface for switching between content panels.",
|
|
13636
|
+
categories: ["navigation", "layout"]
|
|
13637
|
+
},
|
|
13638
|
+
"tabs-pro": {
|
|
13639
|
+
type: "registry:ui",
|
|
13640
|
+
title: "TabsPro",
|
|
13641
|
+
description: "Advanced tabbed interface with closable, sortable, and overflow support.",
|
|
13642
|
+
categories: ["navigation", "layout"]
|
|
13643
|
+
},
|
|
13644
|
+
toast: {
|
|
13645
|
+
type: "registry:ui",
|
|
13646
|
+
title: "Toast",
|
|
13647
|
+
description: "Brief notification messages that auto-dismiss.",
|
|
13648
|
+
categories: ["feedback"]
|
|
13649
|
+
},
|
|
13650
|
+
tooltip: {
|
|
13651
|
+
type: "registry:ui",
|
|
13652
|
+
title: "Tooltip",
|
|
13653
|
+
description: "Informational popup displayed on hover or focus.",
|
|
13654
|
+
categories: ["data-display"],
|
|
13655
|
+
npmDependencies: ["@floating-ui/react"]
|
|
13656
|
+
},
|
|
13657
|
+
typography: {
|
|
13658
|
+
type: "registry:ui",
|
|
13659
|
+
title: "Typography",
|
|
13660
|
+
description: "Text rendering primitives with semantic variants.",
|
|
13661
|
+
categories: ["data-display"]
|
|
13662
|
+
}
|
|
13663
|
+
};
|
|
13664
|
+
var hookMap = {
|
|
13665
|
+
"use-async": {
|
|
13666
|
+
type: "registry:hook",
|
|
13667
|
+
title: "useAsync",
|
|
13668
|
+
description: "Manages async operation lifecycle (loading, error, data states).",
|
|
13669
|
+
categories: ["state"]
|
|
13670
|
+
},
|
|
13671
|
+
"use-callback-ref": {
|
|
13672
|
+
type: "registry:hook",
|
|
13673
|
+
title: "useCallbackRef",
|
|
13674
|
+
description: "Stable callback reference that always points to the latest function.",
|
|
13675
|
+
categories: ["refs"]
|
|
13676
|
+
},
|
|
13677
|
+
"use-click-outside": {
|
|
13678
|
+
type: "registry:hook",
|
|
13679
|
+
title: "useClickOutside",
|
|
13680
|
+
description: "Detects clicks outside of a target element.",
|
|
13681
|
+
categories: ["dom"]
|
|
13682
|
+
},
|
|
13683
|
+
"use-controllable-state": {
|
|
13684
|
+
type: "registry:hook",
|
|
13685
|
+
title: "useControllableState",
|
|
13686
|
+
description: "Manages state that can be either controlled or uncontrolled.",
|
|
13687
|
+
categories: ["state"]
|
|
13688
|
+
},
|
|
13689
|
+
"use-dark-mode": {
|
|
13690
|
+
type: "registry:hook",
|
|
13691
|
+
title: "useDarkMode",
|
|
13692
|
+
description: "Detects and toggles dark mode preference.",
|
|
13693
|
+
categories: ["theme"]
|
|
13694
|
+
},
|
|
13695
|
+
"use-debounce": {
|
|
13696
|
+
type: "registry:hook",
|
|
13697
|
+
title: "useDebounce",
|
|
13698
|
+
description: "Debounces a value or callback over a specified delay.",
|
|
13699
|
+
categories: ["timing"]
|
|
13700
|
+
},
|
|
13701
|
+
"use-field": {
|
|
13702
|
+
type: "registry:hook",
|
|
13703
|
+
title: "useField",
|
|
13704
|
+
description: "Form field state management with validation.",
|
|
13705
|
+
categories: ["forms"]
|
|
13706
|
+
},
|
|
13707
|
+
"use-focus-trap": {
|
|
13708
|
+
type: "registry:hook",
|
|
13709
|
+
title: "useFocusTrap",
|
|
13710
|
+
description: "Traps keyboard focus within a container for modal-like experiences.",
|
|
13711
|
+
categories: ["a11y"]
|
|
13712
|
+
},
|
|
13713
|
+
"use-form": {
|
|
13714
|
+
type: "registry:hook",
|
|
13715
|
+
title: "useForm",
|
|
13716
|
+
description: "Comprehensive form state management with validation.",
|
|
13717
|
+
categories: ["forms"]
|
|
13718
|
+
},
|
|
13719
|
+
"use-hover": {
|
|
13720
|
+
type: "registry:hook",
|
|
13721
|
+
title: "useHover",
|
|
13722
|
+
description: "Tracks hover state of an element with enter/leave delays.",
|
|
13723
|
+
categories: ["dom"]
|
|
13724
|
+
},
|
|
13725
|
+
"use-id": {
|
|
13726
|
+
type: "registry:hook",
|
|
13727
|
+
title: "useId",
|
|
13728
|
+
description: "Generates stable unique identifiers for accessibility attributes.",
|
|
13729
|
+
categories: ["a11y"]
|
|
13730
|
+
},
|
|
13731
|
+
"use-intersection-observer": {
|
|
13732
|
+
type: "registry:hook",
|
|
13733
|
+
title: "useIntersectionObserver",
|
|
13734
|
+
description: "Observes element visibility within the viewport.",
|
|
13735
|
+
categories: ["dom"]
|
|
13736
|
+
},
|
|
13737
|
+
"use-key-press": {
|
|
13738
|
+
type: "registry:hook",
|
|
13739
|
+
title: "useKeyPress",
|
|
13740
|
+
description: "Listens for specific keyboard key presses.",
|
|
13741
|
+
categories: ["dom"]
|
|
13742
|
+
},
|
|
13743
|
+
"use-local-storage": {
|
|
13744
|
+
type: "registry:hook",
|
|
13745
|
+
title: "useLocalStorage",
|
|
13746
|
+
description: "Persists state to localStorage with serialization.",
|
|
13747
|
+
categories: ["state", "storage"]
|
|
13748
|
+
},
|
|
13749
|
+
"use-media-query": {
|
|
13750
|
+
type: "registry:hook",
|
|
13751
|
+
title: "useMediaQuery",
|
|
13752
|
+
description: "Matches CSS media queries and provides responsive breakpoint helpers.",
|
|
13753
|
+
categories: ["responsive"]
|
|
13754
|
+
},
|
|
13755
|
+
"use-mounted": {
|
|
13756
|
+
type: "registry:hook",
|
|
13757
|
+
title: "useMounted",
|
|
13758
|
+
description: "Tracks whether the component is currently mounted.",
|
|
13759
|
+
categories: ["lifecycle"]
|
|
13760
|
+
},
|
|
13761
|
+
"use-previous": {
|
|
13762
|
+
type: "registry:hook",
|
|
13763
|
+
title: "usePrevious",
|
|
13764
|
+
description: "Returns the previous value of a variable across renders.",
|
|
13765
|
+
categories: ["state"]
|
|
13766
|
+
},
|
|
13767
|
+
"use-reduced-motion": {
|
|
13768
|
+
type: "registry:hook",
|
|
13769
|
+
title: "useReducedMotion",
|
|
13770
|
+
description: "Detects user preference for reduced motion.",
|
|
13771
|
+
categories: ["a11y"]
|
|
13772
|
+
},
|
|
13773
|
+
"use-resize-observer": {
|
|
13774
|
+
type: "registry:hook",
|
|
13775
|
+
title: "useResizeObserver",
|
|
13776
|
+
description: "Observes element size changes via ResizeObserver.",
|
|
13777
|
+
categories: ["dom"]
|
|
13778
|
+
},
|
|
13779
|
+
"use-roving-focus": {
|
|
13780
|
+
type: "registry:hook",
|
|
13781
|
+
title: "useRovingFocus",
|
|
13782
|
+
description: "Implements roving tabindex pattern for composite widgets.",
|
|
13783
|
+
categories: ["a11y"]
|
|
13784
|
+
},
|
|
13785
|
+
"use-scroll-lock": {
|
|
13786
|
+
type: "registry:hook",
|
|
13787
|
+
title: "useScrollLock",
|
|
13788
|
+
description: "Prevents body scrolling while active (for modals/overlays).",
|
|
13789
|
+
categories: ["dom"]
|
|
13790
|
+
},
|
|
13791
|
+
"use-session-storage": {
|
|
13792
|
+
type: "registry:hook",
|
|
13793
|
+
title: "useSessionStorage",
|
|
13794
|
+
description: "Persists state to sessionStorage with serialization.",
|
|
13795
|
+
categories: ["state", "storage"]
|
|
13796
|
+
},
|
|
13797
|
+
"use-throttle": {
|
|
13798
|
+
type: "registry:hook",
|
|
13799
|
+
title: "useThrottle",
|
|
13800
|
+
description: "Throttles a value or callback to fire at most once per interval.",
|
|
13801
|
+
categories: ["timing"]
|
|
13802
|
+
}
|
|
13803
|
+
};
|
|
13804
|
+
var utilMap = {
|
|
13805
|
+
cn: {
|
|
13806
|
+
type: "registry:util",
|
|
13807
|
+
title: "cn",
|
|
13808
|
+
description: "Conditional class name composition utility.",
|
|
13809
|
+
categories: ["styling"]
|
|
13810
|
+
},
|
|
13811
|
+
a11y: {
|
|
13812
|
+
type: "registry:util",
|
|
13813
|
+
title: "a11y",
|
|
13814
|
+
description: "Accessibility utilities including screen reader announcements and ARIA helpers.",
|
|
13815
|
+
categories: ["a11y"]
|
|
13816
|
+
},
|
|
13817
|
+
async: {
|
|
13818
|
+
type: "registry:util",
|
|
13819
|
+
title: "async",
|
|
13820
|
+
description: "Async operation utilities: abortable tasks, queues, exponential backoff.",
|
|
13821
|
+
categories: ["async"]
|
|
13822
|
+
},
|
|
13823
|
+
browser: {
|
|
13824
|
+
type: "registry:util",
|
|
13825
|
+
title: "browser",
|
|
13826
|
+
description: "Browser environment detection and feature checks.",
|
|
13827
|
+
categories: ["platform"]
|
|
13828
|
+
},
|
|
13829
|
+
collections: {
|
|
13830
|
+
type: "registry:util",
|
|
13831
|
+
title: "collections",
|
|
13832
|
+
description: "Collection utilities: chunk, paginate, memoize, selectors.",
|
|
13833
|
+
categories: ["data"]
|
|
13834
|
+
},
|
|
13835
|
+
color: {
|
|
13836
|
+
type: "registry:util",
|
|
13837
|
+
title: "color",
|
|
13838
|
+
description: "Color manipulation utilities: contrast, luminance, hex/rgb conversion.",
|
|
13839
|
+
categories: ["styling"]
|
|
13840
|
+
},
|
|
13841
|
+
date: {
|
|
13842
|
+
type: "registry:util",
|
|
13843
|
+
title: "date",
|
|
13844
|
+
description: "Date formatting and relative time utilities.",
|
|
13845
|
+
categories: ["formatting"]
|
|
13846
|
+
},
|
|
13847
|
+
"merge-refs": {
|
|
13848
|
+
type: "registry:util",
|
|
13849
|
+
title: "mergeRefs",
|
|
13850
|
+
description: "Merges multiple React refs into a single callback ref.",
|
|
13851
|
+
categories: ["refs"]
|
|
13852
|
+
},
|
|
13853
|
+
dx: {
|
|
13854
|
+
type: "registry:util",
|
|
13855
|
+
title: "dx",
|
|
13856
|
+
description: "Developer experience helpers: component creation, context factories, polymorphic patterns.",
|
|
13857
|
+
categories: ["dx"]
|
|
13858
|
+
},
|
|
13859
|
+
forms: {
|
|
13860
|
+
type: "registry:util",
|
|
13861
|
+
title: "forms",
|
|
13862
|
+
description: "Form utilities: validators, field error extraction, dirty checking.",
|
|
13863
|
+
categories: ["forms"]
|
|
13864
|
+
},
|
|
13865
|
+
keyboard: {
|
|
13866
|
+
type: "registry:util",
|
|
13867
|
+
title: "keyboard",
|
|
13868
|
+
description: "Keyboard event helpers for detecting specific keys.",
|
|
13869
|
+
categories: ["dom"]
|
|
13870
|
+
},
|
|
13871
|
+
layout: {
|
|
13872
|
+
type: "registry:util",
|
|
13873
|
+
title: "layout",
|
|
13874
|
+
description: "Layout measurement utilities: element bounds, viewport size, resize observation.",
|
|
13875
|
+
categories: ["dom"]
|
|
13876
|
+
},
|
|
13877
|
+
misc: {
|
|
13878
|
+
type: "registry:util",
|
|
13879
|
+
title: "misc",
|
|
13880
|
+
description: "Miscellaneous utilities: clear icon, safe input props, event helpers.",
|
|
13881
|
+
categories: ["misc"]
|
|
13882
|
+
},
|
|
13883
|
+
motion: {
|
|
13884
|
+
type: "registry:util",
|
|
13885
|
+
title: "motion",
|
|
13886
|
+
description: "Animation utilities: spring physics, easing functions, distance calculations.",
|
|
13887
|
+
categories: ["animation"]
|
|
13888
|
+
},
|
|
13889
|
+
number: {
|
|
13890
|
+
type: "registry:util",
|
|
13891
|
+
title: "number",
|
|
13892
|
+
description: "Number formatting and clamping utilities.",
|
|
13893
|
+
categories: ["formatting"]
|
|
13894
|
+
},
|
|
13895
|
+
object: {
|
|
13896
|
+
type: "registry:util",
|
|
13897
|
+
title: "object",
|
|
13898
|
+
description: "Object manipulation utilities: deep merge, pick, omit.",
|
|
13899
|
+
categories: ["data"]
|
|
13900
|
+
},
|
|
13901
|
+
platform: {
|
|
13902
|
+
type: "registry:util",
|
|
13903
|
+
title: "platform",
|
|
13904
|
+
description: "Platform detection utilities: browser, OS, device pixel ratio, text direction.",
|
|
13905
|
+
categories: ["platform"]
|
|
13906
|
+
},
|
|
13907
|
+
responsive: {
|
|
13908
|
+
type: "registry:util",
|
|
13909
|
+
title: "responsive",
|
|
13910
|
+
description: "Responsive design utilities.",
|
|
13911
|
+
categories: ["responsive"]
|
|
13912
|
+
},
|
|
13913
|
+
safety: {
|
|
13914
|
+
type: "registry:util",
|
|
13915
|
+
title: "safety",
|
|
13916
|
+
description: "Security utilities: clipboard access, crypto ID generation, token generation.",
|
|
13917
|
+
categories: ["security"]
|
|
13918
|
+
},
|
|
13919
|
+
string: {
|
|
13920
|
+
type: "registry:util",
|
|
13921
|
+
title: "string",
|
|
13922
|
+
description: "String manipulation utilities: capitalize, slugify, variant classes.",
|
|
13923
|
+
categories: ["formatting"]
|
|
13924
|
+
},
|
|
13925
|
+
telemetry: {
|
|
13926
|
+
type: "registry:util",
|
|
13927
|
+
title: "telemetry",
|
|
13928
|
+
description: "Telemetry utilities: error catching, performance measurement, timing.",
|
|
13929
|
+
categories: ["observability"]
|
|
13930
|
+
},
|
|
13931
|
+
timing: {
|
|
13932
|
+
type: "registry:util",
|
|
13933
|
+
title: "timing",
|
|
13934
|
+
description: "Timing utilities: debounce and throttle functions.",
|
|
13935
|
+
categories: ["timing"]
|
|
13936
|
+
},
|
|
13937
|
+
types: {
|
|
13938
|
+
type: "registry:util",
|
|
13939
|
+
title: "types",
|
|
13940
|
+
description: "Shared type guards and type utilities.",
|
|
13941
|
+
categories: ["types"]
|
|
13942
|
+
},
|
|
13943
|
+
validation: {
|
|
13944
|
+
type: "registry:util",
|
|
13945
|
+
title: "validation",
|
|
13946
|
+
description: "Input validation utilities: email, URL, href safety checks.",
|
|
13947
|
+
categories: ["validation"]
|
|
13948
|
+
}
|
|
13949
|
+
};
|
|
13950
|
+
var directoryToRegistryName = {
|
|
13951
|
+
Accordion: "accordion",
|
|
13952
|
+
Alert: "alert",
|
|
13953
|
+
Avatar: "avatar",
|
|
13954
|
+
Badge: "badge",
|
|
13955
|
+
Breadcrumb: "breadcrumb",
|
|
13956
|
+
Button: "button",
|
|
13957
|
+
Card: "card",
|
|
13958
|
+
CardList: "card-list",
|
|
13959
|
+
Carousel: "carousel",
|
|
13960
|
+
Checkbox: "checkbox",
|
|
13961
|
+
CheckboxGroup: "checkbox-group",
|
|
13962
|
+
Dropdown: "dropdown",
|
|
13963
|
+
Icon: "icon",
|
|
13964
|
+
Input: "input",
|
|
13965
|
+
ListGroup: "list-group",
|
|
13966
|
+
Modal: "modal",
|
|
13967
|
+
Navbar: "navbar",
|
|
13968
|
+
Pagination: "pagination",
|
|
13969
|
+
Popover: "popover",
|
|
13970
|
+
Progress: "progress",
|
|
13971
|
+
Radio: "radio",
|
|
13972
|
+
Scrollspy: "scrollspy",
|
|
13973
|
+
Select: "select",
|
|
13974
|
+
SelectableCard: "selectable-card",
|
|
13975
|
+
Sheet: "sheet",
|
|
13976
|
+
Spinner: "spinner",
|
|
13977
|
+
Switch: "switch",
|
|
13978
|
+
Table: "table",
|
|
13979
|
+
Tabs: "tabs",
|
|
13980
|
+
TabsPro: "tabs-pro",
|
|
13981
|
+
Toast: "toast",
|
|
13982
|
+
Tooltip: "tooltip",
|
|
13983
|
+
Typography: "typography"
|
|
13984
|
+
};
|
|
13985
|
+
var hookDirectoryToRegistryName = {
|
|
13986
|
+
useAsync: "use-async",
|
|
13987
|
+
useCallbackRef: "use-callback-ref",
|
|
13988
|
+
useClickOutside: "use-click-outside",
|
|
13989
|
+
useControllableState: "use-controllable-state",
|
|
13990
|
+
useDarkMode: "use-dark-mode",
|
|
13991
|
+
useDebounce: "use-debounce",
|
|
13992
|
+
useField: "use-field",
|
|
13993
|
+
useFocusTrap: "use-focus-trap",
|
|
13994
|
+
useForm: "use-form",
|
|
13995
|
+
useHover: "use-hover",
|
|
13996
|
+
useId: "use-id",
|
|
13997
|
+
useIntersectionObserver: "use-intersection-observer",
|
|
13998
|
+
useKeyPress: "use-key-press",
|
|
13999
|
+
useLocalStorage: "use-local-storage",
|
|
14000
|
+
useMediaQuery: "use-media-query",
|
|
14001
|
+
useMounted: "use-mounted",
|
|
14002
|
+
usePrevious: "use-previous",
|
|
14003
|
+
useReducedMotion: "use-reduced-motion",
|
|
14004
|
+
useResizeObserver: "use-resize-observer",
|
|
14005
|
+
useRovingFocus: "use-roving-focus",
|
|
14006
|
+
useScrollLock: "use-scroll-lock",
|
|
14007
|
+
useSessionStorage: "use-session-storage",
|
|
14008
|
+
useThrottle: "use-throttle"
|
|
14009
|
+
};
|
|
14010
|
+
|
|
14011
|
+
// src/registry/builder.ts
|
|
14012
|
+
var EXCLUDE_PATTERNS = [
|
|
14013
|
+
/\.test\.(tsx?|jsx?)$/,
|
|
14014
|
+
/\.spec\.(tsx?|jsx?)$/,
|
|
14015
|
+
/\.stories\.(tsx?|jsx?)$/,
|
|
14016
|
+
/\.figma\.(tsx?|jsx?)$/,
|
|
14017
|
+
/\.a11y\.test\./,
|
|
14018
|
+
/\.security\.test\./,
|
|
14019
|
+
/\.integration\.test\./,
|
|
14020
|
+
/README\.md$/
|
|
14021
|
+
];
|
|
14022
|
+
var REACT_BUILTINS = /* @__PURE__ */ new Set(["react", "react-dom", "react/jsx-runtime", "react-dom/client"]);
|
|
14023
|
+
var UTIL_SUBPATH_TO_REGISTRY = {
|
|
14024
|
+
index: "cn",
|
|
14025
|
+
keyboard: "keyboard",
|
|
14026
|
+
dom: "merge-refs",
|
|
14027
|
+
"dom/mergeRefs": "merge-refs",
|
|
14028
|
+
browser: "browser",
|
|
14029
|
+
validation: "validation",
|
|
14030
|
+
string: "string",
|
|
14031
|
+
misc: "misc",
|
|
14032
|
+
a11y: "a11y",
|
|
14033
|
+
types: "types",
|
|
14034
|
+
async: "async",
|
|
14035
|
+
collections: "collections",
|
|
14036
|
+
color: "color",
|
|
14037
|
+
date: "date",
|
|
14038
|
+
dx: "dx",
|
|
14039
|
+
forms: "forms",
|
|
14040
|
+
layout: "layout",
|
|
14041
|
+
motion: "motion",
|
|
14042
|
+
number: "number",
|
|
14043
|
+
object: "object",
|
|
14044
|
+
platform: "platform",
|
|
14045
|
+
responsive: "responsive",
|
|
14046
|
+
safety: "safety",
|
|
14047
|
+
telemetry: "telemetry",
|
|
14048
|
+
timing: "timing"
|
|
14049
|
+
};
|
|
14050
|
+
function shouldIncludeFile(filePath) {
|
|
14051
|
+
const ext = path4.extname(filePath);
|
|
14052
|
+
if (![".ts", ".tsx", ".css"].includes(ext)) return false;
|
|
14053
|
+
return !EXCLUDE_PATTERNS.some((pattern) => pattern.test(filePath));
|
|
14054
|
+
}
|
|
14055
|
+
function readSourceFiles(dirPath) {
|
|
14056
|
+
if (!fs3.existsSync(dirPath) || !fs3.statSync(dirPath).isDirectory()) return [];
|
|
14057
|
+
const results = [];
|
|
14058
|
+
for (const entry of fs3.readdirSync(dirPath, { withFileTypes: true })) {
|
|
14059
|
+
const fullPath = path4.join(dirPath, entry.name);
|
|
14060
|
+
if (entry.isDirectory()) {
|
|
14061
|
+
for (const sub of fs3.readdirSync(fullPath, { withFileTypes: true })) {
|
|
14062
|
+
if (sub.isFile()) {
|
|
14063
|
+
const subPath = path4.join(fullPath, sub.name);
|
|
14064
|
+
if (shouldIncludeFile(subPath)) {
|
|
14065
|
+
results.push({ path: path4.relative(dirPath, subPath), content: fs3.readFileSync(subPath, "utf-8") });
|
|
14066
|
+
}
|
|
14067
|
+
}
|
|
14068
|
+
}
|
|
14069
|
+
} else if (entry.isFile() && shouldIncludeFile(fullPath)) {
|
|
14070
|
+
results.push({ path: entry.name, content: fs3.readFileSync(fullPath, "utf-8") });
|
|
14071
|
+
}
|
|
14072
|
+
}
|
|
14073
|
+
return results;
|
|
14074
|
+
}
|
|
14075
|
+
function extractCnSource(utilsIndexPath) {
|
|
14076
|
+
const content = fs3.readFileSync(utilsIndexPath, "utf-8");
|
|
14077
|
+
const cnPattern = /(\/\*\*[\s\S]*?\*\/\s*)?export function cn\b[\s\S]*?\n\}/;
|
|
14078
|
+
const match = cnPattern.exec(content);
|
|
14079
|
+
return match ? match[0] : "export function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}";
|
|
14080
|
+
}
|
|
14081
|
+
function analyzeImports(files, knownNpmDeps) {
|
|
14082
|
+
const registryDeps = /* @__PURE__ */ new Set();
|
|
14083
|
+
const npmDeps = new Set(knownNpmDeps);
|
|
14084
|
+
const importPattern = /(?:import|export)\s+(?:[\s\S]*?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
14085
|
+
for (const file of files) {
|
|
14086
|
+
let m2;
|
|
14087
|
+
importPattern.lastIndex = 0;
|
|
14088
|
+
while ((m2 = importPattern.exec(file.content)) !== null) {
|
|
14089
|
+
const specifier = m2[1] ?? "";
|
|
14090
|
+
const typesPattern = /\.\.\/(?:\.\.\/)?types(?:\/.*)?$/;
|
|
14091
|
+
if (typesPattern.test(specifier)) {
|
|
14092
|
+
registryDeps.add("dsai-types");
|
|
14093
|
+
continue;
|
|
14094
|
+
}
|
|
14095
|
+
const hookPattern = /\.\.\/(?:\.\.\/)?hooks\/(\w+)/;
|
|
14096
|
+
const hookMatch = hookPattern.exec(specifier);
|
|
14097
|
+
if (hookMatch && hookMatch[1]) {
|
|
14098
|
+
const regName = hookDirectoryToRegistryName[hookMatch[1]];
|
|
14099
|
+
if (regName) registryDeps.add(regName);
|
|
14100
|
+
continue;
|
|
14101
|
+
}
|
|
14102
|
+
const utilPattern = /\.\.\/(?:\.\.\/)?utils(?:\/(.+))?$/;
|
|
14103
|
+
const utilMatch = utilPattern.exec(specifier);
|
|
14104
|
+
if (utilMatch) {
|
|
14105
|
+
const subpath = utilMatch[1] ?? "index";
|
|
14106
|
+
const regName = UTIL_SUBPATH_TO_REGISTRY[subpath];
|
|
14107
|
+
if (regName) registryDeps.add(regName);
|
|
14108
|
+
continue;
|
|
14109
|
+
}
|
|
14110
|
+
const compPattern = /^\.\.\/(\.\.\/)?(?:components\/)?([A-Z]\w+)(?:\/.*)?$/;
|
|
14111
|
+
const compMatch = compPattern.exec(specifier);
|
|
14112
|
+
if (compMatch && compMatch[2]) {
|
|
14113
|
+
const compDir = compMatch[2];
|
|
14114
|
+
const regName = directoryToRegistryName[compDir];
|
|
14115
|
+
if (regName) registryDeps.add(regName);
|
|
14116
|
+
continue;
|
|
14117
|
+
}
|
|
14118
|
+
if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
|
|
14119
|
+
const parts = specifier.split("/");
|
|
14120
|
+
const pkgName = specifier.startsWith("@") && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0] ?? specifier;
|
|
14121
|
+
if (pkgName && !REACT_BUILTINS.has(pkgName) && !pkgName.startsWith("@dsai-io/")) {
|
|
14122
|
+
npmDeps.add(pkgName);
|
|
14123
|
+
}
|
|
14124
|
+
}
|
|
14125
|
+
}
|
|
14126
|
+
}
|
|
14127
|
+
return { registryDeps, npmDeps };
|
|
14128
|
+
}
|
|
14129
|
+
function buildComponentItem(name, dirPath, log) {
|
|
14130
|
+
const meta = componentMap[name];
|
|
14131
|
+
if (!meta) {
|
|
14132
|
+
log(` [WARN] No metadata for component "${name}", skipping`);
|
|
14133
|
+
return null;
|
|
14134
|
+
}
|
|
14135
|
+
const sourceFiles = readSourceFiles(dirPath);
|
|
14136
|
+
if (sourceFiles.length === 0) {
|
|
14137
|
+
log(` [WARN] No source files found in ${dirPath}`);
|
|
14138
|
+
return null;
|
|
14139
|
+
}
|
|
14140
|
+
const { registryDeps, npmDeps } = analyzeImports(sourceFiles, meta.npmDependencies ?? []);
|
|
14141
|
+
const files = sourceFiles.map((f) => ({
|
|
14142
|
+
path: f.path,
|
|
14143
|
+
type: path4.extname(f.path) === ".css" ? "registry:style" : meta.type,
|
|
14144
|
+
content: f.content
|
|
14145
|
+
}));
|
|
14146
|
+
return {
|
|
14147
|
+
name,
|
|
14148
|
+
type: meta.type,
|
|
14149
|
+
title: meta.title,
|
|
14150
|
+
description: meta.description,
|
|
14151
|
+
dependencies: [...npmDeps].sort(),
|
|
14152
|
+
devDependencies: [],
|
|
14153
|
+
registryDependencies: [...registryDeps].sort(),
|
|
14154
|
+
files,
|
|
14155
|
+
categories: meta.categories
|
|
14156
|
+
};
|
|
14157
|
+
}
|
|
14158
|
+
function buildHookItem(name, dirPath, log) {
|
|
14159
|
+
const meta = hookMap[name];
|
|
14160
|
+
if (!meta) {
|
|
14161
|
+
log(` [WARN] No metadata for hook "${name}", skipping`);
|
|
14162
|
+
return null;
|
|
14163
|
+
}
|
|
14164
|
+
const sourceFiles = readSourceFiles(dirPath);
|
|
14165
|
+
if (sourceFiles.length === 0) {
|
|
14166
|
+
log(` [WARN] No source files found in ${dirPath}`);
|
|
14167
|
+
return null;
|
|
14168
|
+
}
|
|
14169
|
+
const { registryDeps, npmDeps } = analyzeImports(sourceFiles, meta.npmDependencies ?? []);
|
|
14170
|
+
const files = sourceFiles.map((f) => ({
|
|
14171
|
+
path: f.path,
|
|
14172
|
+
type: path4.extname(f.path) === ".css" ? "registry:style" : meta.type,
|
|
14173
|
+
content: f.content
|
|
14174
|
+
}));
|
|
14175
|
+
return {
|
|
14176
|
+
name,
|
|
14177
|
+
type: meta.type,
|
|
14178
|
+
title: meta.title,
|
|
14179
|
+
description: meta.description,
|
|
14180
|
+
dependencies: [...npmDeps].sort(),
|
|
14181
|
+
devDependencies: [],
|
|
14182
|
+
registryDependencies: [...registryDeps].sort(),
|
|
14183
|
+
files,
|
|
14184
|
+
categories: meta.categories
|
|
14185
|
+
};
|
|
14186
|
+
}
|
|
14187
|
+
function buildUtilItem(name, reactSrcDir, log) {
|
|
14188
|
+
const meta = utilMap[name];
|
|
14189
|
+
if (!meta) {
|
|
14190
|
+
log(` [WARN] No metadata for util "${name}", skipping`);
|
|
14191
|
+
return null;
|
|
14192
|
+
}
|
|
14193
|
+
let files;
|
|
14194
|
+
let registryDeps = /* @__PURE__ */ new Set();
|
|
14195
|
+
let npmDeps = /* @__PURE__ */ new Set();
|
|
14196
|
+
if (name === "cn") {
|
|
14197
|
+
const indexPath = path4.join(reactSrcDir, "utils", "index.ts");
|
|
14198
|
+
const cnSource = extractCnSource(indexPath);
|
|
14199
|
+
files = [{ path: "cn.ts", type: "registry:util", content: cnSource }];
|
|
14200
|
+
} else if (name === "merge-refs") {
|
|
14201
|
+
const dirPath = path4.join(reactSrcDir, "utils", "dom");
|
|
14202
|
+
const sourceFiles = readSourceFiles(dirPath);
|
|
14203
|
+
const analyzed = analyzeImports(sourceFiles, []);
|
|
14204
|
+
registryDeps = analyzed.registryDeps;
|
|
14205
|
+
npmDeps = analyzed.npmDeps;
|
|
14206
|
+
files = sourceFiles.map((f) => ({
|
|
14207
|
+
path: `dom/${f.path}`,
|
|
14208
|
+
type: path4.extname(f.path) === ".css" ? "registry:style" : "registry:util",
|
|
14209
|
+
content: f.content
|
|
14210
|
+
}));
|
|
14211
|
+
} else {
|
|
14212
|
+
const dirPath = path4.join(reactSrcDir, "utils", name);
|
|
14213
|
+
if (!fs3.existsSync(dirPath) || !fs3.statSync(dirPath).isDirectory()) {
|
|
14214
|
+
log(` [WARN] Util directory not found: ${dirPath}`);
|
|
14215
|
+
return null;
|
|
14216
|
+
}
|
|
14217
|
+
const sourceFiles = readSourceFiles(dirPath);
|
|
14218
|
+
if (sourceFiles.length === 0) {
|
|
14219
|
+
log(` [WARN] No source files found in ${dirPath}`);
|
|
14220
|
+
return null;
|
|
14221
|
+
}
|
|
14222
|
+
const analyzed = analyzeImports(sourceFiles, []);
|
|
14223
|
+
registryDeps = analyzed.registryDeps;
|
|
14224
|
+
npmDeps = analyzed.npmDeps;
|
|
14225
|
+
files = sourceFiles.map((f) => ({
|
|
14226
|
+
path: `${name}/${f.path}`,
|
|
14227
|
+
type: path4.extname(f.path) === ".css" ? "registry:style" : "registry:util",
|
|
14228
|
+
content: f.content
|
|
14229
|
+
}));
|
|
14230
|
+
}
|
|
14231
|
+
return {
|
|
14232
|
+
name,
|
|
14233
|
+
type: meta.type,
|
|
14234
|
+
title: meta.title,
|
|
14235
|
+
description: meta.description,
|
|
14236
|
+
dependencies: [...npmDeps].sort(),
|
|
14237
|
+
devDependencies: [],
|
|
14238
|
+
registryDependencies: [...registryDeps].sort(),
|
|
14239
|
+
files,
|
|
14240
|
+
categories: meta.categories
|
|
14241
|
+
};
|
|
14242
|
+
}
|
|
14243
|
+
function buildTypesItem(reactSrcDir, log) {
|
|
14244
|
+
const typesDir = path4.join(reactSrcDir, "types");
|
|
14245
|
+
const sourceFiles = readSourceFiles(typesDir);
|
|
14246
|
+
if (sourceFiles.length === 0) {
|
|
14247
|
+
log(" [WARN] No type files found");
|
|
14248
|
+
return null;
|
|
14249
|
+
}
|
|
14250
|
+
const files = sourceFiles.map((f) => {
|
|
14251
|
+
let content = f.content;
|
|
14252
|
+
content = content.replace(/export \{[^}]*\} from ['"]\.\.\/utils\/[^'"]+['"];?\n?/g, "");
|
|
14253
|
+
return {
|
|
14254
|
+
path: `types/${f.path}`,
|
|
14255
|
+
type: "registry:type",
|
|
14256
|
+
content
|
|
14257
|
+
};
|
|
14258
|
+
});
|
|
14259
|
+
return {
|
|
14260
|
+
name: "dsai-types",
|
|
14261
|
+
type: "registry:type",
|
|
14262
|
+
title: "Shared Types",
|
|
14263
|
+
description: "Shared type definitions (SafeHTMLAttributes, ComponentSize, PolymorphicComponentProps, etc.)",
|
|
14264
|
+
dependencies: [],
|
|
14265
|
+
devDependencies: [],
|
|
14266
|
+
registryDependencies: [],
|
|
14267
|
+
files,
|
|
14268
|
+
categories: ["types"]
|
|
14269
|
+
};
|
|
14270
|
+
}
|
|
14271
|
+
function buildRegistry(options) {
|
|
14272
|
+
const { reactSrcDir, outputDir, verbose = false } = options;
|
|
14273
|
+
const log = verbose ? (msg) => console.log(msg) : (_msg) => {
|
|
14274
|
+
};
|
|
14275
|
+
const componentsDir = path4.join(reactSrcDir, "components");
|
|
14276
|
+
const hooksDir = path4.join(reactSrcDir, "hooks");
|
|
14277
|
+
const allItems = [];
|
|
14278
|
+
log("[registry] Scanning components...");
|
|
14279
|
+
if (fs3.existsSync(componentsDir)) {
|
|
14280
|
+
for (const entry of fs3.readdirSync(componentsDir, { withFileTypes: true })) {
|
|
14281
|
+
if (!entry.isDirectory()) continue;
|
|
14282
|
+
const dirName = entry.name;
|
|
14283
|
+
const registryName = directoryToRegistryName[dirName];
|
|
14284
|
+
if (!registryName) {
|
|
14285
|
+
log(` [SKIP] Unknown component directory: ${dirName}`);
|
|
14286
|
+
continue;
|
|
14287
|
+
}
|
|
14288
|
+
log(` Building ${registryName}...`);
|
|
14289
|
+
const item = buildComponentItem(registryName, path4.join(componentsDir, dirName), log);
|
|
14290
|
+
if (item) allItems.push(item);
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
log("[registry] Scanning hooks...");
|
|
14294
|
+
if (fs3.existsSync(hooksDir)) {
|
|
14295
|
+
for (const entry of fs3.readdirSync(hooksDir, { withFileTypes: true })) {
|
|
14296
|
+
if (!entry.isDirectory()) continue;
|
|
14297
|
+
const dirName = entry.name;
|
|
14298
|
+
const registryName = hookDirectoryToRegistryName[dirName];
|
|
14299
|
+
if (!registryName) {
|
|
14300
|
+
log(` [SKIP] Unknown hook directory: ${dirName}`);
|
|
14301
|
+
continue;
|
|
14302
|
+
}
|
|
14303
|
+
log(` Building ${registryName}...`);
|
|
14304
|
+
const item = buildHookItem(registryName, path4.join(hooksDir, dirName), log);
|
|
14305
|
+
if (item) allItems.push(item);
|
|
14306
|
+
}
|
|
14307
|
+
}
|
|
14308
|
+
log("[registry] Scanning utils...");
|
|
14309
|
+
for (const name of Object.keys(utilMap)) {
|
|
14310
|
+
log(` Building ${name}...`);
|
|
14311
|
+
const item = buildUtilItem(name, reactSrcDir, log);
|
|
14312
|
+
if (item) allItems.push(item);
|
|
14313
|
+
}
|
|
14314
|
+
log("[registry] Building shared types...");
|
|
14315
|
+
const typesItem = buildTypesItem(reactSrcDir, log);
|
|
14316
|
+
if (typesItem) {
|
|
14317
|
+
allItems.push(typesItem);
|
|
14318
|
+
log(` Built dsai-types (${typesItem.files.length} files)`);
|
|
14319
|
+
}
|
|
14320
|
+
log(`[registry] Writing ${allItems.length} items to ${outputDir}...`);
|
|
14321
|
+
for (const sub of ["components", "hooks", "utils", "types"]) {
|
|
14322
|
+
const dir = path4.join(outputDir, sub);
|
|
14323
|
+
if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
|
|
14324
|
+
}
|
|
14325
|
+
const typeToSubdir = {
|
|
14326
|
+
"registry:ui": "components",
|
|
14327
|
+
"registry:component": "components",
|
|
14328
|
+
"registry:hook": "hooks",
|
|
14329
|
+
"registry:util": "utils",
|
|
14330
|
+
"registry:lib": "utils",
|
|
14331
|
+
"registry:type": "types"
|
|
14332
|
+
};
|
|
14333
|
+
for (const item of allItems) {
|
|
14334
|
+
const subdir = typeToSubdir[item.type] ?? "utils";
|
|
14335
|
+
const filePath = path4.join(outputDir, subdir, `${item.name}.json`);
|
|
14336
|
+
fs3.writeFileSync(filePath, JSON.stringify(item, null, 2) + "\n", "utf-8");
|
|
14337
|
+
log(` Wrote ${path4.relative(outputDir, filePath)}`);
|
|
14338
|
+
}
|
|
14339
|
+
const indexEntries = allItems.map((item) => ({
|
|
14340
|
+
name: item.name,
|
|
14341
|
+
type: item.type,
|
|
14342
|
+
title: item.title,
|
|
14343
|
+
description: item.description,
|
|
14344
|
+
dependencies: item.dependencies,
|
|
14345
|
+
registryDependencies: item.registryDependencies,
|
|
14346
|
+
categories: item.categories
|
|
14347
|
+
}));
|
|
14348
|
+
const registryIndex = {
|
|
14349
|
+
version: "0.1.0",
|
|
14350
|
+
count: indexEntries.length,
|
|
14351
|
+
items: indexEntries
|
|
14352
|
+
};
|
|
14353
|
+
fs3.writeFileSync(path4.join(outputDir, "index.json"), JSON.stringify(registryIndex, null, 2) + "\n", "utf-8");
|
|
14354
|
+
log(`[registry] Wrote index.json (${registryIndex.count} items)`);
|
|
14355
|
+
return registryIndex;
|
|
14356
|
+
}
|
|
14357
|
+
|
|
14358
|
+
// src/cli/commands/registry.ts
|
|
14359
|
+
function createRegistryCommand() {
|
|
14360
|
+
const cmd = new commander.Command("registry").description("Manage the component registry");
|
|
14361
|
+
cmd.command("build").description("Build registry JSON from @dsai-io/react source").option("--src <path>", "Path to @dsai-io/react/src directory").option("--out <path>", "Output directory for registry JSON", "registry").option("--verbose", "Show detailed logging", false).action(async (opts) => {
|
|
14362
|
+
const logger = createLogger(opts);
|
|
14363
|
+
const spinner = createSpinner();
|
|
14364
|
+
spinner.start("Building component registry...");
|
|
14365
|
+
try {
|
|
14366
|
+
const reactSrcDir = opts.src ? path4.resolve(opts.src) : path4.resolve(process.cwd(), "packages", "@dsai-io", "react", "src");
|
|
14367
|
+
const outputDir = path4.resolve(
|
|
14368
|
+
process.cwd(),
|
|
14369
|
+
"packages",
|
|
14370
|
+
"@dsai-io",
|
|
14371
|
+
"tools",
|
|
14372
|
+
opts.out
|
|
14373
|
+
);
|
|
14374
|
+
const index = buildRegistry({
|
|
14375
|
+
reactSrcDir,
|
|
14376
|
+
outputDir,
|
|
14377
|
+
verbose: opts.verbose
|
|
14378
|
+
});
|
|
14379
|
+
spinner.succeed(
|
|
14380
|
+
`Registry built: ${colors.bold(String(index.count))} items (${index.items.filter((i) => i.type === "registry:ui").length} components, ${index.items.filter((i) => i.type === "registry:hook").length} hooks, ${index.items.filter((i) => i.type === "registry:util").length} utils)`
|
|
14381
|
+
);
|
|
14382
|
+
console.log(`
|
|
14383
|
+
Output: ${colors.cyan(outputDir)}
|
|
14384
|
+
`);
|
|
14385
|
+
} catch (err) {
|
|
14386
|
+
spinner.fail("Failed to build registry");
|
|
14387
|
+
logger.error(err.message);
|
|
14388
|
+
process.exit(ExitCode.GeneralError);
|
|
14389
|
+
}
|
|
14390
|
+
});
|
|
14391
|
+
return cmd;
|
|
14392
|
+
}
|
|
14393
|
+
|
|
13014
14394
|
// src/version.ts
|
|
13015
14395
|
var version = "0.0.1";
|
|
13016
14396
|
|
|
@@ -13029,6 +14409,15 @@ Build, validate, and manage design tokens and icons.`
|
|
|
13029
14409
|
"after",
|
|
13030
14410
|
`
|
|
13031
14411
|
${colors.bold("Examples:")}
|
|
14412
|
+
${colors.muted("# Add components, hooks, or utils to your project")}
|
|
14413
|
+
$ dsai add button modal use-focus-trap cn
|
|
14414
|
+
|
|
14415
|
+
${colors.muted("# List everything available")}
|
|
14416
|
+
$ dsai add --list
|
|
14417
|
+
|
|
14418
|
+
${colors.muted("# Add all hooks")}
|
|
14419
|
+
$ dsai add --all --type hook
|
|
14420
|
+
|
|
13032
14421
|
${colors.muted("# Initialize configuration")}
|
|
13033
14422
|
$ dsai init
|
|
13034
14423
|
|
|
@@ -13066,16 +14455,24 @@ function setupErrorHandling(program2) {
|
|
|
13066
14455
|
var program;
|
|
13067
14456
|
async function run(args = process.argv) {
|
|
13068
14457
|
program = createProgram();
|
|
14458
|
+
program.addCommand(createAddCommand());
|
|
13069
14459
|
program.addCommand(createTokensCommand());
|
|
13070
14460
|
program.addCommand(createIconsCommand());
|
|
13071
14461
|
program.addCommand(createInitCommand());
|
|
13072
14462
|
program.addCommand(createConfigCommand());
|
|
14463
|
+
program.addCommand(createRegistryCommand());
|
|
13073
14464
|
setupErrorHandling(program);
|
|
13074
14465
|
await program.parseAsync(args);
|
|
13075
14466
|
}
|
|
13076
14467
|
function getProgram() {
|
|
13077
14468
|
return program;
|
|
13078
14469
|
}
|
|
14470
|
+
if (process.argv[1] === url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
14471
|
+
run().catch((error) => {
|
|
14472
|
+
console.error("Fatal error:", error);
|
|
14473
|
+
process.exit(1);
|
|
14474
|
+
});
|
|
14475
|
+
}
|
|
13079
14476
|
|
|
13080
14477
|
exports.ExitCode = ExitCode;
|
|
13081
14478
|
exports.colors = colors;
|