@nooeh/cli 0.1.0 → 0.2.0
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 +5 -4
- package/dist/arguments.d.ts +1 -1
- package/dist/config.d.ts +3 -6
- package/dist/config.js +21 -61
- package/dist/doctor.js +9 -9
- package/dist/index.js +1 -1
- package/dist/init.js +11 -10
- package/dist/new-component.js +3 -3
- package/package.json +1 -1
package/dist/add.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
|
-
import { defaultConfig, hasConfig, readConfig,
|
|
4
|
+
import { defaultConfig, hasConfig, readConfig, resolveConfigPath } from "./config.js";
|
|
5
5
|
import { installDependencies } from "./dependencies.js";
|
|
6
6
|
import { init } from "./init.js";
|
|
7
7
|
import { resolveComponent } from "./registry.js";
|
|
@@ -70,8 +70,8 @@ export async function add(projectDirectory, componentName, options = {}) {
|
|
|
70
70
|
}
|
|
71
71
|
const config = options["dry-run"] && shouldInitialize ? defaultConfig : await readConfig(projectDirectory);
|
|
72
72
|
const resolved = await resolveComponent(componentName);
|
|
73
|
-
const uiDirectory =
|
|
74
|
-
const tokenDirectory =
|
|
73
|
+
const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
|
|
74
|
+
const tokenDirectory = resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens");
|
|
75
75
|
let isOverwriteConfirmed = false;
|
|
76
76
|
async function confirmOverwrite() {
|
|
77
77
|
if (isOverwriteConfirmed)
|
|
@@ -101,5 +101,6 @@ export async function add(projectDirectory, componentName, options = {}) {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
console.log(`Added ${componentName}.`);
|
|
104
|
-
console.log(`
|
|
104
|
+
console.log(`Export: ${primaryExport}`);
|
|
105
|
+
console.log(`Location: ${relative(projectDirectory, join(uiDirectory, `${componentName}.tsx`))}`);
|
|
105
106
|
}
|
package/dist/arguments.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type CliOptions = Record<string, boolean | string | undefined> & {
|
|
|
6
6
|
force?: boolean;
|
|
7
7
|
"skip-dependencies"?: boolean;
|
|
8
8
|
tokens?: string;
|
|
9
|
-
|
|
9
|
+
ui?: string;
|
|
10
10
|
};
|
|
11
11
|
export declare function parseArguments(arguments_: readonly string[]): {
|
|
12
12
|
command: string;
|
package/dist/config.d.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
export declare const configFileName = "nooeh.json";
|
|
2
|
-
export declare const configVersion = 2;
|
|
3
2
|
export type NooehConfig = {
|
|
4
|
-
|
|
3
|
+
paths: {
|
|
5
4
|
ui: string;
|
|
5
|
+
tokens: string;
|
|
6
6
|
};
|
|
7
|
-
tokens: string;
|
|
8
|
-
version?: number;
|
|
9
7
|
};
|
|
10
8
|
export declare const defaultConfig: NooehConfig;
|
|
11
9
|
export declare function hasConfig(projectDirectory: string): Promise<boolean>;
|
|
12
10
|
export declare function validateConfig(config: unknown): NooehConfig;
|
|
13
11
|
export declare function readConfig(projectDirectory: string): Promise<NooehConfig>;
|
|
14
12
|
export declare function writeConfig(projectDirectory: string, config: NooehConfig): Promise<string>;
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function resolveAliasPath(projectDirectory: string, alias: string): Promise<string>;
|
|
13
|
+
export declare function resolveConfigPath(projectDirectory: string, path: string, name: string): string;
|
package/dist/config.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { access, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
export const configFileName = "nooeh.json";
|
|
4
|
-
export const configVersion = 2;
|
|
5
4
|
export const defaultConfig = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
paths: {
|
|
6
|
+
ui: "src/components/ui",
|
|
7
|
+
tokens: "src/design/nooeh",
|
|
8
|
+
},
|
|
9
9
|
};
|
|
10
10
|
export async function hasConfig(projectDirectory) {
|
|
11
11
|
try {
|
|
@@ -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.
|
|
29
|
-
throw new Error("
|
|
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.");
|
|
30
30
|
}
|
|
31
|
-
if (candidate.
|
|
32
|
-
throw new Error(
|
|
31
|
+
if (!candidate.paths || typeof candidate.paths.ui !== "string" || !candidate.paths.ui.trim()) {
|
|
32
|
+
throw new Error("Configure paths.ui.");
|
|
33
33
|
}
|
|
34
|
-
if (typeof candidate.tokens !== "string" || !candidate.tokens.trim()) {
|
|
35
|
-
throw new Error("Configure tokens.");
|
|
34
|
+
if (typeof candidate.paths.tokens !== "string" || !candidate.paths.tokens.trim()) {
|
|
35
|
+
throw new Error("Configure paths.tokens.");
|
|
36
36
|
}
|
|
37
|
-
if (isAbsolute(candidate.tokens)) {
|
|
38
|
-
throw new Error("
|
|
37
|
+
if (isAbsolute(candidate.paths.ui) || isAbsolute(candidate.paths.tokens)) {
|
|
38
|
+
throw new Error("paths must stay inside the project directory.");
|
|
39
39
|
}
|
|
40
40
|
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
paths: {
|
|
42
|
+
ui: candidate.paths.ui,
|
|
43
|
+
tokens: candidate.paths.tokens,
|
|
44
|
+
},
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
function isNotFoundError(error) {
|
|
@@ -61,54 +62,13 @@ export async function readConfig(projectDirectory) {
|
|
|
61
62
|
}
|
|
62
63
|
export async function writeConfig(projectDirectory, config) {
|
|
63
64
|
const validatedConfig = validateConfig(config);
|
|
64
|
-
ensureRelativePath(projectDirectory, validatedConfig.
|
|
65
|
+
ensureRelativePath(projectDirectory, validatedConfig.paths.ui, "paths.ui");
|
|
66
|
+
ensureRelativePath(projectDirectory, validatedConfig.paths.tokens, "paths.tokens");
|
|
65
67
|
const configPath = resolve(projectDirectory, configFileName);
|
|
66
68
|
await writeFile(configPath, `${JSON.stringify(validatedConfig, null, 2)}\n`, "utf8");
|
|
67
69
|
return configPath;
|
|
68
70
|
}
|
|
69
|
-
export function
|
|
70
|
-
ensureRelativePath(projectDirectory,
|
|
71
|
-
return resolve(projectDirectory,
|
|
72
|
-
}
|
|
73
|
-
function findAliasTarget(alias, paths) {
|
|
74
|
-
for (const [pattern, targets] of Object.entries(paths ?? {})) {
|
|
75
|
-
const target = targets[0];
|
|
76
|
-
if (!target)
|
|
77
|
-
continue;
|
|
78
|
-
const starIndex = pattern.indexOf("*");
|
|
79
|
-
if (starIndex === -1) {
|
|
80
|
-
if (alias === pattern)
|
|
81
|
-
return target;
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const prefix = pattern.slice(0, starIndex);
|
|
85
|
-
const suffix = pattern.slice(starIndex + 1);
|
|
86
|
-
if (!alias.startsWith(prefix) || !alias.endsWith(suffix))
|
|
87
|
-
continue;
|
|
88
|
-
const value = alias.slice(prefix.length, alias.length - suffix.length);
|
|
89
|
-
return target.replaceAll("*", value);
|
|
90
|
-
}
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
export async function resolveAliasPath(projectDirectory, alias) {
|
|
94
|
-
for (const fileName of ["tsconfig.json", "jsconfig.json"]) {
|
|
95
|
-
const configPath = resolve(projectDirectory, fileName);
|
|
96
|
-
try {
|
|
97
|
-
const projectConfig = JSON.parse(await readFile(configPath, "utf8"));
|
|
98
|
-
const compilerOptions = projectConfig.compilerOptions ?? {};
|
|
99
|
-
const aliasTarget = findAliasTarget(alias, compilerOptions.paths);
|
|
100
|
-
if (!aliasTarget)
|
|
101
|
-
continue;
|
|
102
|
-
const baseDirectory = resolve(projectDirectory, compilerOptions.baseUrl ?? ".");
|
|
103
|
-
const resolvedPath = resolve(baseDirectory, aliasTarget);
|
|
104
|
-
ensureRelativePath(projectDirectory, resolvedPath, "UI");
|
|
105
|
-
return resolvedPath;
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
if (isNotFoundError(error))
|
|
109
|
-
continue;
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
throw new Error(`Could not find the ${alias} alias in compilerOptions.paths of tsconfig.json or jsconfig.json.`);
|
|
71
|
+
export function resolveConfigPath(projectDirectory, path, name) {
|
|
72
|
+
ensureRelativePath(projectDirectory, path, name);
|
|
73
|
+
return resolve(projectDirectory, path);
|
|
114
74
|
}
|
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,
|
|
3
|
+
import { hasConfig, readConfig, resolveConfigPath } from "./config.js";
|
|
4
4
|
async function readPackageJson(projectDirectory) {
|
|
5
5
|
try {
|
|
6
6
|
return JSON.parse(await readFile(resolve(projectDirectory, "package.json"), "utf8"));
|
|
@@ -73,13 +73,13 @@ export async function doctor(projectDirectory) {
|
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
75
|
const config = await readConfig(projectDirectory);
|
|
76
|
-
const uiDirectory =
|
|
76
|
+
const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
|
|
77
77
|
checks.push({
|
|
78
|
-
detail: `${config.
|
|
79
|
-
name: "UI
|
|
78
|
+
detail: `${config.paths.ui} → ${uiDirectory}`,
|
|
79
|
+
name: "UI path",
|
|
80
80
|
status: "pass",
|
|
81
81
|
});
|
|
82
|
-
const tokenDirectory =
|
|
82
|
+
const tokenDirectory = resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens");
|
|
83
83
|
const tokenFiles = [
|
|
84
84
|
"color-palette.stylex.ts",
|
|
85
85
|
"tokens.stylex.ts",
|
|
@@ -97,12 +97,12 @@ export async function doctor(projectDirectory) {
|
|
|
97
97
|
}));
|
|
98
98
|
checks.push(hasTokenFiles.every(Boolean)
|
|
99
99
|
? {
|
|
100
|
-
detail: `${config.tokens} contains local token sources.`,
|
|
100
|
+
detail: `${config.paths.tokens} contains local token sources.`,
|
|
101
101
|
name: "Local tokens",
|
|
102
102
|
status: "pass",
|
|
103
103
|
}
|
|
104
104
|
: {
|
|
105
|
-
detail: `Create local token sources in ${config.tokens} with \`nooeh init --force\`.`,
|
|
105
|
+
detail: `Create local token sources in ${config.paths.tokens} with \`nooeh init --force\`.`,
|
|
106
106
|
name: "Local tokens",
|
|
107
107
|
status: "warn",
|
|
108
108
|
});
|
|
@@ -125,14 +125,14 @@ export async function doctor(projectDirectory) {
|
|
|
125
125
|
name: "StyleX compiler",
|
|
126
126
|
status: "warn",
|
|
127
127
|
});
|
|
128
|
-
checks.push(entrySources.some((source) => source.includes("
|
|
128
|
+
checks.push(entrySources.some((source) => source.includes("nooeh.css") || source.includes("@nooeh/ui/global.css"))
|
|
129
129
|
? {
|
|
130
130
|
detail: "An application entry imports nooeh global CSS.",
|
|
131
131
|
name: "Global CSS",
|
|
132
132
|
status: "pass",
|
|
133
133
|
}
|
|
134
134
|
: {
|
|
135
|
-
detail: "Import
|
|
135
|
+
detail: "Import the generated nooeh.css file from an application entry point.",
|
|
136
136
|
name: "Global CSS",
|
|
137
137
|
status: "warn",
|
|
138
138
|
});
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ export async function run(arguments_ = process.argv.slice(2)) {
|
|
|
31
31
|
console.log(`Nooeh CLI
|
|
32
32
|
|
|
33
33
|
Usage:
|
|
34
|
-
nooeh init
|
|
34
|
+
nooeh init [--ui <path>] [--tokens <path>]
|
|
35
35
|
nooeh init --framework vite
|
|
36
36
|
nooeh add <component> [--skip-dependencies] [--dry-run]
|
|
37
37
|
nooeh doctor
|
package/dist/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, relative, sep } from "node:path";
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
|
-
import { configFileName, defaultConfig, hasConfig,
|
|
4
|
+
import { configFileName, defaultConfig, hasConfig, resolveConfigPath, 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) {
|
|
@@ -61,7 +61,7 @@ async function writeViteFiles(projectDirectory, tokenDirectory) {
|
|
|
61
61
|
const configuredVite = configureVite(configSource);
|
|
62
62
|
const { entryPath, stylePath, themePath } = getNooehPaths(projectDirectory, tokenDirectory);
|
|
63
63
|
const entrySource = await readFile(entryPath, "utf8");
|
|
64
|
-
const styleImport =
|
|
64
|
+
const styleImport = `import "${toModuleSpecifier(dirname(entryPath), stylePath)}";`;
|
|
65
65
|
const themeImport = `import { applyNooehTheme } from "${toModuleSpecifier(dirname(entryPath), themePath)}";`;
|
|
66
66
|
const themeApply = "applyNooehTheme();";
|
|
67
67
|
const imports = [styleImport, themeImport].filter((line) => !entrySource.includes(line));
|
|
@@ -77,7 +77,7 @@ function getNooehPaths(projectDirectory, tokenDirectory) {
|
|
|
77
77
|
const sourceDirectory = getSourceDirectory(projectDirectory);
|
|
78
78
|
return {
|
|
79
79
|
entryPath: join(sourceDirectory, "main.tsx"),
|
|
80
|
-
stylePath: join(
|
|
80
|
+
stylePath: join(dirname(tokenDirectory), "nooeh.css"),
|
|
81
81
|
themePath: join(tokenDirectory, "theme.ts"),
|
|
82
82
|
};
|
|
83
83
|
}
|
|
@@ -112,15 +112,16 @@ export async function init(projectDirectory, options) {
|
|
|
112
112
|
if (options.framework && options.framework !== "vite") {
|
|
113
113
|
throw new Error(`Unsupported framework: ${options.framework}. Use vite or omit --framework.`);
|
|
114
114
|
}
|
|
115
|
-
const
|
|
115
|
+
const uiPath = options.ui ??
|
|
116
116
|
(readline
|
|
117
|
-
? await ask("Enter the UI
|
|
118
|
-
: defaultConfig.
|
|
117
|
+
? await ask("Enter the UI directory.", defaultConfig.paths.ui, readline)
|
|
118
|
+
: defaultConfig.paths.ui);
|
|
119
119
|
const tokens = options.tokens ??
|
|
120
120
|
(readline
|
|
121
|
-
? await ask("Enter the token directory.", defaultConfig.tokens, readline)
|
|
122
|
-
: defaultConfig.tokens);
|
|
123
|
-
const tokenDirectory =
|
|
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");
|
|
124
125
|
if (!options["skip-dependencies"]) {
|
|
125
126
|
await installDependencies(projectDirectory, ["@stylexjs/stylex"]);
|
|
126
127
|
await installDependencies(projectDirectory, ["@stylexjs/unplugin"], true);
|
|
@@ -133,7 +134,7 @@ export async function init(projectDirectory, options) {
|
|
|
133
134
|
console.log(`Created ${relative(projectDirectory, stylePath)} and ${relative(projectDirectory, themePath)}.`);
|
|
134
135
|
console.log("Import the CSS and call applyNooehTheme() from your application entry point.");
|
|
135
136
|
}
|
|
136
|
-
await writeConfig(projectDirectory, {
|
|
137
|
+
await writeConfig(projectDirectory, { paths: { ui: uiPath, tokens } });
|
|
137
138
|
}
|
|
138
139
|
finally {
|
|
139
140
|
readline?.close();
|
package/dist/new-component.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { access, mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, relative, sep } from "node:path";
|
|
3
|
-
import { readConfig,
|
|
3
|
+
import { readConfig, resolveConfigPath } from "./config.js";
|
|
4
4
|
function toPascalCase(name) {
|
|
5
5
|
return name
|
|
6
6
|
.split("-")
|
|
@@ -13,10 +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 =
|
|
16
|
+
const uiDirectory = resolveConfigPath(projectDirectory, config.paths.ui, "paths.ui");
|
|
17
17
|
const componentName = toPascalCase(name);
|
|
18
18
|
const componentPath = join(uiDirectory, `${name}.tsx`);
|
|
19
|
-
const tokenPath = join(
|
|
19
|
+
const tokenPath = join(resolveConfigPath(projectDirectory, config.paths.tokens, "paths.tokens"), "tokens.stylex.ts");
|
|
20
20
|
const relativeTokenPath = relative(dirname(componentPath), tokenPath)
|
|
21
21
|
.replace(/\.ts$/, "")
|
|
22
22
|
.split(sep)
|