@nooeh/cli 0.2.0 → 0.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/dist/add.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { mkdir, readFile, writeFile } from "node:fs/promises";
2
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
2
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
3
3
  import { createInterface } from "node:readline/promises";
4
- import { defaultConfig, hasConfig, readConfig, resolveConfigPath } from "./config.js";
4
+ import { defaultConfig, hasConfig, readConfig, resolveConfigAlias } from "./config.js";
5
5
  import { installDependencies } from "./dependencies.js";
6
6
  import { init } from "./init.js";
7
7
  import { resolveComponent } from "./registry.js";
@@ -49,14 +49,8 @@ function resolveTargetPath(uiDirectory, filePath) {
49
49
  }
50
50
  return targetPath;
51
51
  }
52
- function replaceTokenImport(source, targetPath, tokenDirectory) {
53
- const tokenModulePath = join(tokenDirectory, "tokens.stylex.ts");
54
- const relativePath = relative(dirname(targetPath), tokenModulePath)
55
- .replace(/\.ts$/, "")
56
- .split(sep)
57
- .join("/");
58
- const tokenModule = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
59
- return source.replaceAll("@nooeh/tokens/tokens.stylex", tokenModule);
52
+ function replaceTokenImport(source, stylesAlias) {
53
+ return source.replaceAll("@nooeh/tokens/semantic.stylex", `${stylesAlias}/semantic.stylex`);
60
54
  }
61
55
  export async function add(projectDirectory, componentName, options = {}) {
62
56
  if (!componentName)
@@ -70,8 +64,7 @@ export async function add(projectDirectory, componentName, options = {}) {
70
64
  }
71
65
  const config = options["dry-run"] && shouldInitialize ? defaultConfig : await readConfig(projectDirectory);
72
66
  const resolved = await resolveComponent(componentName);
73
- const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
74
- const tokenDirectory = resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens");
67
+ const uiDirectory = await resolveConfigAlias(projectDirectory, config.aliases.ui, "aliases.ui");
75
68
  let isOverwriteConfirmed = false;
76
69
  async function confirmOverwrite() {
77
70
  if (isOverwriteConfirmed)
@@ -85,7 +78,7 @@ export async function add(projectDirectory, componentName, options = {}) {
85
78
  console.log(`Will add: ${targetPath}`);
86
79
  continue;
87
80
  }
88
- await writeSource(replaceTokenImport(file.content, targetPath, tokenDirectory), targetPath, confirmOverwrite);
81
+ await writeSource(replaceTokenImport(file.content, config.aliases.styles), targetPath, confirmOverwrite);
89
82
  }
90
83
  const shouldInstallDependencies = resolved.externalDependencies.length > 0 &&
91
84
  !options.skipDependencyInstall &&
@@ -5,6 +5,7 @@ export type CliOptions = Record<string, boolean | string | undefined> & {
5
5
  "dry-run"?: boolean;
6
6
  force?: boolean;
7
7
  "skip-dependencies"?: boolean;
8
+ styles?: string;
8
9
  tokens?: string;
9
10
  ui?: string;
10
11
  };
package/dist/config.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export declare const configFileName = "nooeh.json";
2
2
  export type NooehConfig = {
3
- paths: {
3
+ aliases: {
4
4
  ui: string;
5
- tokens: string;
5
+ styles: string;
6
6
  };
7
7
  };
8
8
  export declare const defaultConfig: NooehConfig;
@@ -11,3 +11,4 @@ export declare function validateConfig(config: unknown): NooehConfig;
11
11
  export declare function readConfig(projectDirectory: string): Promise<NooehConfig>;
12
12
  export declare function writeConfig(projectDirectory: string, config: NooehConfig): Promise<string>;
13
13
  export declare function resolveConfigPath(projectDirectory: string, path: string, name: string): string;
14
+ export declare function resolveConfigAlias(projectDirectory: string, alias: string, name: string): Promise<string>;
package/dist/config.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { access, readFile, writeFile } from "node:fs/promises";
2
- import { isAbsolute, relative, resolve } from "node:path";
2
+ import { isAbsolute, join, relative, resolve } from "node:path";
3
3
  export const configFileName = "nooeh.json";
4
4
  export const defaultConfig = {
5
- paths: {
6
- ui: "src/components/ui",
7
- tokens: "src/design/nooeh",
5
+ aliases: {
6
+ ui: "@/components/ui",
7
+ styles: "@/styles",
8
8
  },
9
9
  };
10
10
  export async function hasConfig(projectDirectory) {
@@ -25,22 +25,23 @@ function ensureRelativePath(projectDirectory, path, name) {
25
25
  }
26
26
  export function validateConfig(config) {
27
27
  const candidate = config;
28
- if (!candidate.paths && (candidate.aliases || candidate.tokens)) {
29
- throw new Error("This nooeh.json uses an older format. Run `nooeh init --force` to create path-based configuration.");
28
+ if (candidate.paths || candidate.tokens) {
29
+ throw new Error("This nooeh.json uses an older format. Run `nooeh init --force` to create alias-based configuration.");
30
30
  }
31
- if (!candidate.paths || typeof candidate.paths.ui !== "string" || !candidate.paths.ui.trim()) {
32
- throw new Error("Configure paths.ui.");
31
+ if (!candidate.aliases || typeof candidate.aliases !== "object") {
32
+ throw new Error("Configure aliases.");
33
33
  }
34
- if (typeof candidate.paths.tokens !== "string" || !candidate.paths.tokens.trim()) {
35
- throw new Error("Configure paths.tokens.");
34
+ const aliases = candidate.aliases;
35
+ if (typeof aliases.ui !== "string" || !aliases.ui.trim()) {
36
+ throw new Error("Configure aliases.ui.");
36
37
  }
37
- if (isAbsolute(candidate.paths.ui) || isAbsolute(candidate.paths.tokens)) {
38
- throw new Error("paths must stay inside the project directory.");
38
+ if (typeof aliases.styles !== "string" || !aliases.styles.trim()) {
39
+ throw new Error("Configure aliases.styles.");
39
40
  }
40
41
  return {
41
- paths: {
42
- ui: candidate.paths.ui,
43
- tokens: candidate.paths.tokens,
42
+ aliases: {
43
+ ui: aliases.ui,
44
+ styles: aliases.styles,
44
45
  },
45
46
  };
46
47
  }
@@ -62,8 +63,6 @@ export async function readConfig(projectDirectory) {
62
63
  }
63
64
  export async function writeConfig(projectDirectory, config) {
64
65
  const validatedConfig = validateConfig(config);
65
- ensureRelativePath(projectDirectory, validatedConfig.paths.ui, "paths.ui");
66
- ensureRelativePath(projectDirectory, validatedConfig.paths.tokens, "paths.tokens");
67
66
  const configPath = resolve(projectDirectory, configFileName);
68
67
  await writeFile(configPath, `${JSON.stringify(validatedConfig, null, 2)}\n`, "utf8");
69
68
  return configPath;
@@ -72,3 +71,46 @@ export function resolveConfigPath(projectDirectory, path, name) {
72
71
  ensureRelativePath(projectDirectory, path, name);
73
72
  return resolve(projectDirectory, path);
74
73
  }
74
+ async function readTsConfig(projectDirectory) {
75
+ for (const fileName of ["tsconfig.json", "jsconfig.json"]) {
76
+ try {
77
+ return JSON.parse(await readFile(resolve(projectDirectory, fileName), "utf8"));
78
+ }
79
+ catch (error) {
80
+ if (!isNotFoundError(error)) {
81
+ continue;
82
+ }
83
+ }
84
+ }
85
+ return undefined;
86
+ }
87
+ function resolvePathAlias(alias, paths) {
88
+ for (const [pattern, targets] of Object.entries(paths)) {
89
+ const wildcardIndex = pattern.indexOf("*");
90
+ if (wildcardIndex === -1) {
91
+ if (pattern === alias)
92
+ return targets[0];
93
+ continue;
94
+ }
95
+ const prefix = pattern.slice(0, wildcardIndex);
96
+ const suffix = pattern.slice(wildcardIndex + 1);
97
+ if (!alias.startsWith(prefix) || !alias.endsWith(suffix))
98
+ continue;
99
+ const wildcard = alias.slice(prefix.length, alias.length - suffix.length);
100
+ return targets[0]?.replace("*", wildcard);
101
+ }
102
+ return undefined;
103
+ }
104
+ export async function resolveConfigAlias(projectDirectory, alias, name) {
105
+ if (alias.startsWith("@/")) {
106
+ return resolveConfigPath(projectDirectory, join("src", alias.slice(2)), name);
107
+ }
108
+ const tsConfig = await readTsConfig(projectDirectory);
109
+ const target = tsConfig?.compilerOptions?.paths
110
+ ? resolvePathAlias(alias, tsConfig.compilerOptions.paths)
111
+ : undefined;
112
+ if (!target) {
113
+ throw new Error(`Could not resolve ${name} (${alias}). Add it to tsconfig.json or jsconfig.json compilerOptions.paths.`);
114
+ }
115
+ return resolveConfigPath(projectDirectory, join(tsConfig?.compilerOptions?.baseUrl ?? ".", target), name);
116
+ }
package/dist/doctor.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { access, readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
- import { hasConfig, readConfig, resolveConfigPath } from "./config.js";
3
+ import { hasConfig, readConfig, resolveConfigAlias } from "./config.js";
4
4
  async function readPackageJson(projectDirectory) {
5
5
  try {
6
6
  return JSON.parse(await readFile(resolve(projectDirectory, "package.json"), "utf8"));
@@ -55,7 +55,7 @@ async function hasStylexCompiler(projectDirectory) {
55
55
  "rspack.config.js",
56
56
  ];
57
57
  const sources = await Promise.all(configFileNames.map(async (fileName) => readProjectFile(projectDirectory, fileName)));
58
- return sources.some((source) => source?.includes("@stylexjs/unplugin") && source.includes("stylex("));
58
+ return sources.some((source) => source?.includes("@stylexjs/unplugin") && source.includes("stylex.vite("));
59
59
  }
60
60
  function hasDependency(packageJson, dependency) {
61
61
  return Boolean(packageJson?.dependencies?.[dependency] ?? packageJson?.devDependencies?.[dependency]);
@@ -66,46 +66,50 @@ export async function doctor(projectDirectory) {
66
66
  const entrySources = await readEntrySources(projectDirectory);
67
67
  if (!(await hasConfig(projectDirectory))) {
68
68
  checks.push({
69
- detail: "Run `nooeh init` to configure the default UI alias.",
69
+ detail: "Run `nooeh init` to configure UI and styles aliases.",
70
70
  name: "nooeh.json",
71
71
  status: "warn",
72
72
  });
73
73
  }
74
74
  else {
75
75
  const config = await readConfig(projectDirectory);
76
- const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
77
- checks.push({
78
- detail: `${config.paths.ui} → ${uiDirectory}`,
79
- name: "UI path",
80
- status: "pass",
81
- });
82
- const tokenDirectory = resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens");
83
- const tokenFiles = [
84
- "color-palette.stylex.ts",
85
- "tokens.stylex.ts",
86
- "themes.stylex.ts",
87
- "theme.ts",
88
- ];
89
- const hasTokenFiles = await Promise.all(tokenFiles.map(async (fileName) => {
90
- try {
91
- await access(resolve(tokenDirectory, fileName));
92
- return true;
93
- }
94
- catch {
95
- return false;
96
- }
97
- }));
98
- checks.push(hasTokenFiles.every(Boolean)
99
- ? {
100
- detail: `${config.paths.tokens} contains local token sources.`,
101
- name: "Local tokens",
76
+ try {
77
+ const uiDirectory = await resolveConfigAlias(projectDirectory, config.aliases.ui, "aliases.ui");
78
+ const tokenDirectory = await resolveConfigAlias(projectDirectory, config.aliases.styles, "aliases.styles");
79
+ checks.push({
80
+ detail: `${config.aliases.ui} → ${uiDirectory}`,
81
+ name: "UI path",
102
82
  status: "pass",
103
- }
104
- : {
105
- detail: `Create local token sources in ${config.paths.tokens} with \`nooeh init --force\`.`,
106
- name: "Local tokens",
83
+ });
84
+ const tokenFiles = ["color-palette.stylex.ts", "semantic.stylex.ts", "themes.stylex.ts"];
85
+ const hasTokenFiles = await Promise.all(tokenFiles.map(async (fileName) => {
86
+ try {
87
+ await access(resolve(tokenDirectory, fileName));
88
+ return true;
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }));
94
+ checks.push(hasTokenFiles.every(Boolean)
95
+ ? {
96
+ detail: `${config.aliases.styles} contains local token sources.`,
97
+ name: "Local tokens",
98
+ status: "pass",
99
+ }
100
+ : {
101
+ detail: `Create local token sources in ${config.aliases.styles} with \`nooeh init --force\`.`,
102
+ name: "Local tokens",
103
+ status: "warn",
104
+ });
105
+ }
106
+ catch (error) {
107
+ checks.push({
108
+ detail: error instanceof Error ? error.message : "Could not resolve nooeh aliases.",
109
+ name: "Aliases",
107
110
  status: "warn",
108
111
  });
112
+ }
109
113
  }
110
114
  checks.push(hasDependency(packageJson, "@stylexjs/stylex")
111
115
  ? { detail: "@stylexjs/stylex is installed.", name: "StyleX runtime", status: "pass" }
@@ -125,26 +129,15 @@ export async function doctor(projectDirectory) {
125
129
  name: "StyleX compiler",
126
130
  status: "warn",
127
131
  });
128
- checks.push(entrySources.some((source) => source.includes("nooeh.css") || source.includes("@nooeh/ui/global.css"))
129
- ? {
130
- detail: "An application entry imports nooeh global CSS.",
131
- name: "Global CSS",
132
- status: "pass",
133
- }
134
- : {
135
- detail: "Import the generated nooeh.css file from an application entry point.",
136
- name: "Global CSS",
137
- status: "warn",
138
- });
139
- checks.push(entrySources.some((source) => source.includes("applyNooehTheme()"))
132
+ checks.push(entrySources.some((source) => /import\s+["'][^"']+\.css["']/.test(source))
140
133
  ? {
141
- detail: "An application entry applies a nooeh theme.",
142
- name: "Theme application",
134
+ detail: "An application entry imports a CSS entry point for StyleX output.",
135
+ name: "CSS entry point",
143
136
  status: "pass",
144
137
  }
145
138
  : {
146
- detail: "Call applyNooehTheme() before rendering your application.",
147
- name: "Theme application",
139
+ detail: "Import an application CSS file from an entry point so StyleX can emit CSS.",
140
+ name: "CSS entry point",
148
141
  status: "warn",
149
142
  });
150
143
  checks.push(hasDependency(packageJson, "@stylexjs/unplugin")
package/dist/init.js CHANGED
@@ -1,16 +1,13 @@
1
1
  import { access, mkdir, readFile, writeFile } from "node:fs/promises";
2
- import { dirname, join, relative, sep } from "node:path";
2
+ import { join, relative } from "node:path";
3
3
  import { createInterface } from "node:readline/promises";
4
- import { configFileName, defaultConfig, hasConfig, resolveConfigPath, writeConfig, } from "./config.js";
4
+ import { configFileName, defaultConfig, hasConfig, resolveConfigAlias, writeConfig, } from "./config.js";
5
5
  import { installDependencies } from "./dependencies.js";
6
6
  import { getTokenFiles } from "@nooeh/registry";
7
7
  async function ask(question, defaultValue, readline) {
8
8
  const answer = await readline.question(`${question} (${defaultValue}) `);
9
9
  return answer.trim() || defaultValue;
10
10
  }
11
- function getSourceDirectory(projectDirectory) {
12
- return join(projectDirectory, "src");
13
- }
14
11
  async function readViteConfig(projectDirectory) {
15
12
  const configFileNames = [
16
13
  "vite.config.ts",
@@ -37,60 +34,39 @@ async function readViteConfig(projectDirectory) {
37
34
  throw new Error("Could not find a Vite config file.");
38
35
  }
39
36
  function configureVite(source) {
40
- const importLine = 'import stylex from "@stylexjs/unplugin/vite";';
37
+ const importLine = 'import stylex from "@stylexjs/unplugin";';
41
38
  const pluginPattern = /plugins:\s*\[([^\]]*)\]/s;
42
- if (source.includes("stylex("))
43
- return source;
44
- if (!pluginPattern.test(source)) {
45
- throw new Error("Could not safely update the Vite plugins array. Add stylex({ useCSSLayers: true }) manually.");
39
+ const configPattern = /defineConfig\(\{\s*/;
40
+ if (!source.includes("stylex.vite(") && !pluginPattern.test(source)) {
41
+ throw new Error("Could not safely update the Vite plugins array. Add stylex.vite({ useCSSLayers: true }) manually.");
46
42
  }
47
- const withImport = source.includes(importLine) ? source : `${importLine}\n${source}`;
48
- return withImport.replace(pluginPattern, (_, plugins) => {
49
- const prefix = plugins.trim()
50
- ? `stylex({ useCSSLayers: true }), ${plugins}`
51
- : "stylex({ useCSSLayers: true })";
52
- return `plugins: [${prefix}]`;
53
- });
54
- }
55
- function toModuleSpecifier(fromDirectory, path) {
56
- const source = relative(fromDirectory, path).replace(/\.ts$/, "").split(sep).join("/");
57
- return source.startsWith(".") ? source : `./${source}`;
43
+ const withStylex = source.includes("stylex.vite(")
44
+ ? source
45
+ : (source.includes(importLine) ? source : `${importLine}\n${source}`).replace(pluginPattern, (_, plugins) => {
46
+ const prefix = plugins.trim()
47
+ ? `stylex.vite({ useCSSLayers: true }), ${plugins}`
48
+ : "stylex.vite({ useCSSLayers: true })";
49
+ return `plugins: [${prefix}]`;
50
+ });
51
+ if (withStylex.includes("alias:"))
52
+ return withStylex;
53
+ if (!configPattern.test(withStylex)) {
54
+ throw new Error('Could not safely add the "@" Vite alias. Add resolve.alias["@"] manually.');
55
+ }
56
+ return withStylex.replace(configPattern, 'defineConfig({\n resolve: { alias: { "@": new URL("./src", import.meta.url).pathname } },\n ');
58
57
  }
59
58
  async function writeViteFiles(projectDirectory, tokenDirectory) {
60
59
  const { path: configPath, source: configSource } = await readViteConfig(projectDirectory);
61
60
  const configuredVite = configureVite(configSource);
62
- const { entryPath, stylePath, themePath } = getNooehPaths(projectDirectory, tokenDirectory);
63
- const entrySource = await readFile(entryPath, "utf8");
64
- const styleImport = `import "${toModuleSpecifier(dirname(entryPath), stylePath)}";`;
65
- const themeImport = `import { applyNooehTheme } from "${toModuleSpecifier(dirname(entryPath), themePath)}";`;
66
- const themeApply = "applyNooehTheme();";
67
- const imports = [styleImport, themeImport].filter((line) => !entrySource.includes(line));
68
- const nextEntrySource = `${imports.join("\n")}\n${entrySource}`;
69
61
  await writeNooehFiles(projectDirectory, tokenDirectory);
70
- await writeFile(entryPath, nextEntrySource.includes(themeApply)
71
- ? nextEntrySource
72
- : `${imports.length ? `${imports.join("\n")}\n` : ""}${themeApply}\n${entrySource}`, "utf8");
73
62
  await writeFile(configPath, configuredVite, "utf8");
74
- console.log(`Configured Vite and created ${relative(projectDirectory, stylePath)}.`);
75
- }
76
- function getNooehPaths(projectDirectory, tokenDirectory) {
77
- const sourceDirectory = getSourceDirectory(projectDirectory);
78
- return {
79
- entryPath: join(sourceDirectory, "main.tsx"),
80
- stylePath: join(dirname(tokenDirectory), "nooeh.css"),
81
- themePath: join(tokenDirectory, "theme.ts"),
82
- };
63
+ console.log(`Configured Vite and created ${relative(projectDirectory, tokenDirectory)}.`);
83
64
  }
84
65
  async function writeNooehFiles(projectDirectory, tokenDirectory) {
85
- const { entryPath, stylePath, themePath } = getNooehPaths(projectDirectory, tokenDirectory);
86
- await mkdir(dirname(stylePath), { recursive: true });
87
66
  await mkdir(tokenDirectory, { recursive: true });
88
- await writeFileIfMissing(stylePath, '@import "@nooeh/ui/global.css";\n');
89
67
  for (const file of await getTokenFiles()) {
90
68
  await writeFileIfMissing(join(tokenDirectory, file.name), file.content);
91
69
  }
92
- await writeFileIfMissing(themePath, `import { darkColorTheme, darkShadowTheme, lightColorTheme, lightShadowTheme } from "./themes.stylex";\nimport * as stylex from "@stylexjs/stylex";\n\nexport type NooehColorMode = "light" | "dark";\n\nconst themeClassNames = [\n stylex.props(lightColorTheme, lightShadowTheme).className,\n stylex.props(darkColorTheme, darkShadowTheme).className,\n]\n .filter(Boolean)\n .flatMap((className) => className.split(" "));\n\nexport function applyNooehTheme(mode: NooehColorMode = "light") {\n const colorTheme = mode === "dark" ? darkColorTheme : lightColorTheme;\n const shadowTheme = mode === "dark" ? darkShadowTheme : lightShadowTheme;\n const themeClassName = stylex.props(colorTheme, shadowTheme).className ?? "";\n const root = document.documentElement;\n\n root.dataset.theme = mode;\n root.classList.remove(...themeClassNames);\n root.classList.add(...themeClassName.split(" ").filter(Boolean));\n}\n`);
93
- return { entryPath, stylePath, themePath };
94
70
  }
95
71
  async function writeFileIfMissing(path, source) {
96
72
  try {
@@ -112,29 +88,32 @@ export async function init(projectDirectory, options) {
112
88
  if (options.framework && options.framework !== "vite") {
113
89
  throw new Error(`Unsupported framework: ${options.framework}. Use vite or omit --framework.`);
114
90
  }
115
- const uiPath = options.ui ??
91
+ const uiAlias = options.ui ??
116
92
  (readline
117
- ? await ask("Enter the UI directory.", defaultConfig.paths.ui, readline)
118
- : defaultConfig.paths.ui);
119
- const tokens = options.tokens ??
93
+ ? await ask("Enter the UI import alias.", defaultConfig.aliases.ui, readline)
94
+ : defaultConfig.aliases.ui);
95
+ const stylesAlias = options.styles ??
96
+ options.tokens ??
120
97
  (readline
121
- ? await ask("Enter the token directory.", defaultConfig.paths.tokens, readline)
122
- : defaultConfig.paths.tokens);
123
- const tokenDirectory = resolveConfigPath(projectDirectory, tokens, "paths.tokens");
124
- resolveConfigPath(projectDirectory, uiPath, "paths.ui");
98
+ ? await ask("Enter the styles import alias.", defaultConfig.aliases.styles, readline)
99
+ : defaultConfig.aliases.styles);
100
+ const tokenDirectory = await resolveConfigAlias(projectDirectory, stylesAlias, "aliases.styles");
101
+ await resolveConfigAlias(projectDirectory, uiAlias, "aliases.ui");
125
102
  if (!options["skip-dependencies"]) {
126
103
  await installDependencies(projectDirectory, ["@stylexjs/stylex"]);
127
- await installDependencies(projectDirectory, ["@stylexjs/unplugin"], true);
104
+ if (options.framework === "vite") {
105
+ await installDependencies(projectDirectory, ["@stylexjs/unplugin"], true);
106
+ }
128
107
  }
129
108
  if (options.framework === "vite") {
130
109
  await writeViteFiles(projectDirectory, tokenDirectory);
131
110
  }
132
111
  else {
133
- const { stylePath, themePath } = await writeNooehFiles(projectDirectory, tokenDirectory);
134
- console.log(`Created ${relative(projectDirectory, stylePath)} and ${relative(projectDirectory, themePath)}.`);
135
- console.log("Import the CSS and call applyNooehTheme() from your application entry point.");
112
+ await writeNooehFiles(projectDirectory, tokenDirectory);
113
+ console.log(`Created ${relative(projectDirectory, tokenDirectory)}.`);
114
+ console.log("Configure the StyleX compiler for your bundler before importing added components.");
136
115
  }
137
- await writeConfig(projectDirectory, { paths: { ui: uiPath, tokens } });
116
+ await writeConfig(projectDirectory, { aliases: { ui: uiAlias, styles: stylesAlias } });
138
117
  }
139
118
  finally {
140
119
  readline?.close();
@@ -1,6 +1,6 @@
1
1
  import { access, mkdir, writeFile } from "node:fs/promises";
2
- import { dirname, join, relative, sep } from "node:path";
3
- import { readConfig, resolveConfigPath } from "./config.js";
2
+ import { join } from "node:path";
3
+ import { readConfig, resolveConfigAlias } from "./config.js";
4
4
  function toPascalCase(name) {
5
5
  return name
6
6
  .split("-")
@@ -13,17 +13,10 @@ export async function newComponent(projectDirectory, name) {
13
13
  throw new Error("Enter a component name in kebab-case. For example: status-chip.");
14
14
  }
15
15
  const config = await readConfig(projectDirectory);
16
- const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
16
+ const uiDirectory = await resolveConfigAlias(projectDirectory, config.aliases.ui, "aliases.ui");
17
17
  const componentName = toPascalCase(name);
18
18
  const componentPath = join(uiDirectory, `${name}.tsx`);
19
- const tokenPath = join(resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens"), "tokens.stylex.ts");
20
- const relativeTokenPath = relative(dirname(componentPath), tokenPath)
21
- .replace(/\.ts$/, "")
22
- .split(sep)
23
- .join("/");
24
- const tokenImport = relativeTokenPath.startsWith(".")
25
- ? relativeTokenPath
26
- : `./${relativeTokenPath}`;
19
+ const tokenImport = `${config.aliases.styles}/semantic.stylex`;
27
20
  const files = [componentPath];
28
21
  for (const file of files) {
29
22
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nooeh/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "nooeh": "./dist/cli.js"
@@ -19,7 +19,7 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@nooeh/registry": "0.1.0"
22
+ "@nooeh/registry": "0.1.1"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^22.20.1",