@nuee/cli 0.4.1 → 0.5.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.d.ts +5 -5
- package/dist/add.js +69 -67
- package/dist/arguments.d.ts +13 -3
- package/dist/arguments.js +17 -18
- package/dist/config.d.ts +4 -0
- package/dist/config.js +57 -31
- package/dist/dependencies.d.ts +1 -0
- package/dist/dependencies.js +25 -4
- package/dist/doctor.js +108 -93
- package/dist/index.js +25 -25
- package/dist/init.d.ts +21 -0
- package/dist/init.js +88 -81
- package/dist/new-component.js +28 -14
- package/dist/registry.js +36 -68
- package/dist/source.d.ts +14 -0
- package/dist/source.js +162 -0
- package/package.json +6 -3
package/dist/doctor.js
CHANGED
|
@@ -1,22 +1,7 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { hasConfig, readConfig, resolveConfigAlias } from "./config.js";
|
|
4
|
-
|
|
5
|
-
try {
|
|
6
|
-
return JSON.parse(await readFile(resolve(projectDirectory, "package.json"), "utf8"));
|
|
7
|
-
}
|
|
8
|
-
catch {
|
|
9
|
-
return undefined;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
async function readProjectFile(projectDirectory, fileName) {
|
|
13
|
-
try {
|
|
14
|
-
return await readFile(resolve(projectDirectory, fileName), "utf8");
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
4
|
+
import { inspectViteConfig } from "./source.js";
|
|
20
5
|
const entryFileNames = [
|
|
21
6
|
"src/main.tsx",
|
|
22
7
|
"src/main.jsx",
|
|
@@ -31,105 +16,132 @@ const entryFileNames = [
|
|
|
31
16
|
"app/layout.tsx",
|
|
32
17
|
"app/layout.jsx",
|
|
33
18
|
];
|
|
19
|
+
const viteConfigFileNames = [
|
|
20
|
+
"vite.config.ts",
|
|
21
|
+
"vite.config.mts",
|
|
22
|
+
"vite.config.js",
|
|
23
|
+
"vite.config.mjs",
|
|
24
|
+
];
|
|
25
|
+
const tokenFileNames = ["color-palette.stylex.ts", "semantic.stylex.ts", "themes.stylex.ts"];
|
|
26
|
+
function isNotFoundError(error) {
|
|
27
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
28
|
+
}
|
|
29
|
+
async function readProjectFile(projectDirectory, fileName) {
|
|
30
|
+
try {
|
|
31
|
+
return await readFile(resolve(projectDirectory, fileName), "utf8");
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (!isNotFoundError(error))
|
|
35
|
+
throw error;
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function readPackageJson(projectDirectory) {
|
|
40
|
+
const source = await readProjectFile(projectDirectory, "package.json");
|
|
41
|
+
return source === undefined ? undefined : JSON.parse(source);
|
|
42
|
+
}
|
|
34
43
|
async function readEntrySources(projectDirectory) {
|
|
35
|
-
const sources = await Promise.all(entryFileNames.map(
|
|
44
|
+
const sources = await Promise.all(entryFileNames.map((fileName) => readProjectFile(projectDirectory, fileName)));
|
|
36
45
|
return sources.filter((source) => source !== undefined);
|
|
37
46
|
}
|
|
38
47
|
async function hasStylexCompiler(projectDirectory) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"rspack.config.mjs",
|
|
55
|
-
"rspack.config.js",
|
|
56
|
-
];
|
|
57
|
-
const sources = await Promise.all(configFileNames.map(async (fileName) => readProjectFile(projectDirectory, fileName)));
|
|
58
|
-
return sources.some((source) => source?.includes("@stylexjs/unplugin") && /\b(?:stylex|unplugin)\.vite\(/.test(source));
|
|
48
|
+
const sources = await Promise.all(viteConfigFileNames.map((fileName) => readProjectFile(projectDirectory, fileName)));
|
|
49
|
+
return sources.some((source) => source !== undefined && inspectViteConfig(source)?.hasCompiler);
|
|
50
|
+
}
|
|
51
|
+
async function hasTokenFiles(tokenDirectory) {
|
|
52
|
+
for (const fileName of tokenFileNames) {
|
|
53
|
+
try {
|
|
54
|
+
await access(resolve(tokenDirectory, fileName));
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (!isNotFoundError(error))
|
|
58
|
+
throw error;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
59
63
|
}
|
|
60
64
|
function hasDependency(packageJson, dependency) {
|
|
61
65
|
return Boolean(packageJson?.dependencies?.[dependency] ?? packageJson?.devDependencies?.[dependency]);
|
|
62
66
|
}
|
|
63
|
-
|
|
64
|
-
const checks = [];
|
|
65
|
-
const packageJson = await readPackageJson(projectDirectory);
|
|
66
|
-
const entrySources = await readEntrySources(projectDirectory);
|
|
67
|
+
async function inspectLocalConfiguration(projectDirectory) {
|
|
67
68
|
if (!(await hasConfig(projectDirectory))) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
detail: "Run `nuee init` to configure UI and styles aliases.",
|
|
72
|
+
name: "nuee.json",
|
|
73
|
+
status: "warn",
|
|
74
|
+
},
|
|
75
|
+
];
|
|
73
76
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
const config = await readConfig(projectDirectory);
|
|
78
|
+
try {
|
|
79
|
+
const uiDirectory = await resolveConfigAlias(projectDirectory, config.aliases.ui, "aliases.ui");
|
|
80
|
+
const tokenDirectory = await resolveConfigAlias(projectDirectory, config.aliases.styles, "aliases.styles");
|
|
81
|
+
const tokenCheck = (await hasTokenFiles(tokenDirectory))
|
|
82
|
+
? {
|
|
83
|
+
detail: `${config.aliases.styles} contains local token sources.`,
|
|
84
|
+
name: "Local tokens",
|
|
85
|
+
status: "pass",
|
|
86
|
+
}
|
|
87
|
+
: {
|
|
88
|
+
detail: `Create local token sources in ${config.aliases.styles} with \`nuee init --force\`.`,
|
|
89
|
+
name: "Local tokens",
|
|
90
|
+
status: "warn",
|
|
91
|
+
};
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
80
94
|
detail: `${config.aliases.ui} → ${uiDirectory}`,
|
|
81
95
|
name: "UI path",
|
|
82
96
|
status: "pass",
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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 \`nuee init --force\`.`,
|
|
102
|
-
name: "Local tokens",
|
|
103
|
-
status: "warn",
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
checks.push({
|
|
97
|
+
},
|
|
98
|
+
tokenCheck,
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return [
|
|
103
|
+
{
|
|
108
104
|
detail: error instanceof Error ? error.message : "Could not resolve nuee aliases.",
|
|
109
105
|
name: "Aliases",
|
|
110
106
|
status: "warn",
|
|
111
|
-
}
|
|
112
|
-
|
|
107
|
+
},
|
|
108
|
+
];
|
|
113
109
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
}
|
|
111
|
+
export async function doctor(projectDirectory) {
|
|
112
|
+
const packageJson = await readPackageJson(projectDirectory);
|
|
113
|
+
const entrySources = await readEntrySources(projectDirectory);
|
|
114
|
+
const checks = await inspectLocalConfiguration(projectDirectory);
|
|
115
|
+
if (hasDependency(packageJson, "@stylexjs/stylex")) {
|
|
116
|
+
checks.push({
|
|
117
|
+
detail: "@stylexjs/stylex is installed.",
|
|
118
|
+
name: "StyleX runtime",
|
|
119
|
+
status: "pass",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
checks.push({
|
|
117
124
|
detail: "It is installed automatically by the first `nuee add`. Use --skip-dependencies to skip installation.",
|
|
118
125
|
name: "StyleX runtime",
|
|
119
126
|
status: "warn",
|
|
120
127
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
}
|
|
129
|
+
if (await hasStylexCompiler(projectDirectory)) {
|
|
130
|
+
checks.push({
|
|
131
|
+
detail: "A Vite plugins array enables the StyleX compiler.",
|
|
124
132
|
name: "StyleX compiler",
|
|
125
133
|
status: "pass",
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
checks.push({
|
|
138
|
+
detail: "Could not verify a Vite StyleX compiler. Other bundlers require manual verification. Vite users can run `nuee init --vite`.",
|
|
129
139
|
name: "StyleX compiler",
|
|
130
140
|
status: "warn",
|
|
131
141
|
});
|
|
132
|
-
|
|
142
|
+
}
|
|
143
|
+
const hasCssEntry = entrySources.some((source) => /import\s+["'][^"']+\.css["']/.test(source));
|
|
144
|
+
checks.push(hasCssEntry
|
|
133
145
|
? {
|
|
134
146
|
detail: "An application entry imports a CSS entry point for StyleX output.",
|
|
135
147
|
name: "CSS entry point",
|
|
@@ -140,17 +152,20 @@ export async function doctor(projectDirectory) {
|
|
|
140
152
|
name: "CSS entry point",
|
|
141
153
|
status: "warn",
|
|
142
154
|
});
|
|
143
|
-
|
|
144
|
-
|
|
155
|
+
if (hasDependency(packageJson, "@stylexjs/unplugin")) {
|
|
156
|
+
checks.push({
|
|
145
157
|
detail: "@stylexjs/unplugin is installed.",
|
|
146
158
|
name: "StyleX build plugin",
|
|
147
159
|
status: "pass",
|
|
148
|
-
}
|
|
149
|
-
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
checks.push({
|
|
150
164
|
detail: "Add @stylexjs/unplugin to your bundler configuration, such as Vite or esbuild.",
|
|
151
165
|
name: "StyleX build plugin",
|
|
152
166
|
status: "warn",
|
|
153
167
|
});
|
|
168
|
+
}
|
|
154
169
|
for (const check of checks) {
|
|
155
170
|
console.log(`${check.status === "pass" ? "✓" : "!"} ${check.name}: ${check.detail}`);
|
|
156
171
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { add } from "./add.js";
|
|
3
3
|
import { parseArguments } from "./arguments.js";
|
|
4
|
-
import { doctor } from "./doctor.js";
|
|
5
4
|
import { docs, list } from "./docs.js";
|
|
5
|
+
import { doctor } from "./doctor.js";
|
|
6
6
|
import { init } from "./init.js";
|
|
7
7
|
import { newComponent } from "./new-component.js";
|
|
8
8
|
export async function run(arguments_ = process.argv.slice(2)) {
|
|
9
|
-
const { command, options, positionals } = parseArguments(arguments_);
|
|
10
|
-
const projectDirectory = resolve(String(options.cwd ?? process.cwd()));
|
|
11
9
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
const { command, options, positionals } = parseArguments(arguments_);
|
|
11
|
+
const projectDirectory = resolve(String(options.cwd ?? process.cwd()));
|
|
12
|
+
switch (command) {
|
|
13
|
+
case "init":
|
|
14
|
+
await init(projectDirectory, options);
|
|
15
|
+
break;
|
|
16
|
+
case "add":
|
|
17
|
+
await add(projectDirectory, positionals, options);
|
|
18
|
+
break;
|
|
19
|
+
case "doctor":
|
|
20
|
+
return await doctor(projectDirectory);
|
|
21
|
+
case "docs":
|
|
22
|
+
docs(positionals[0]);
|
|
23
|
+
break;
|
|
24
|
+
case "list":
|
|
25
|
+
list();
|
|
26
|
+
break;
|
|
27
|
+
case "new":
|
|
28
|
+
await newComponent(projectDirectory, positionals[0]);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
console.log(`Nuee CLI
|
|
32
32
|
|
|
33
33
|
Usage:
|
|
34
|
-
nuee init [--ui <path>] [--
|
|
35
|
-
nuee init --framework vite
|
|
34
|
+
nuee init [--ui <path>] [--styles <path>] [--vite]
|
|
36
35
|
nuee add <component...> [--skip-dependencies] [--dry-run]
|
|
37
36
|
nuee doctor
|
|
38
37
|
nuee list
|
|
39
38
|
nuee docs [component]
|
|
40
39
|
nuee new <kebab-case-name>`);
|
|
40
|
+
break;
|
|
41
41
|
}
|
|
42
42
|
return true;
|
|
43
43
|
}
|
package/dist/init.d.ts
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
1
|
import type { CliOptions } from "./arguments.js";
|
|
2
|
+
type PlannedFile = {
|
|
3
|
+
path: string;
|
|
4
|
+
source: string;
|
|
5
|
+
flag: "w" | "wx";
|
|
6
|
+
};
|
|
7
|
+
export declare function prepareInitialization(projectDirectory: string, options: CliOptions): Promise<{
|
|
8
|
+
files: PlannedFile[];
|
|
9
|
+
runtimeDependencies: readonly string[];
|
|
10
|
+
buildDependencies: readonly string[];
|
|
11
|
+
config: {
|
|
12
|
+
accessibility: {
|
|
13
|
+
respectReducedMotion: boolean;
|
|
14
|
+
};
|
|
15
|
+
aliases: {
|
|
16
|
+
ui: string;
|
|
17
|
+
styles: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}>;
|
|
21
|
+
export declare function applyInitialization(projectDirectory: string, plan: Awaited<ReturnType<typeof prepareInitialization>>): Promise<void>;
|
|
2
22
|
export declare function init(projectDirectory: string, options: CliOptions, shouldLog?: boolean): Promise<void>;
|
|
23
|
+
export {};
|
package/dist/init.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { 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 { defaultConfig, hasConfig, resolveConfigAlias, writeConfig } from "./config.js";
|
|
5
|
-
import { installDependencies } from "./dependencies.js";
|
|
6
4
|
import { getFoundationFiles } from "@nuee/registry";
|
|
5
|
+
import { defaultConfig, getDefaultAliases, hasConfig, resolveConfigAlias, writeConfig, } from "./config.js";
|
|
6
|
+
import { getMissingDependencies, installDependencies } from "./dependencies.js";
|
|
7
|
+
import { configureVite } from "./source.js";
|
|
7
8
|
async function ask(question, defaultValue, readline) {
|
|
8
9
|
const answer = await readline.question(`${question} (${defaultValue}) `);
|
|
9
10
|
return answer.trim() || defaultValue;
|
|
10
11
|
}
|
|
11
|
-
async function
|
|
12
|
+
async function findViteConfig(projectDirectory) {
|
|
12
13
|
const configFileNames = [
|
|
13
14
|
"vite.config.ts",
|
|
14
15
|
"vite.config.mts",
|
|
@@ -18,7 +19,6 @@ async function readViteConfig(projectDirectory) {
|
|
|
18
19
|
for (const fileName of configFileNames) {
|
|
19
20
|
const path = join(projectDirectory, fileName);
|
|
20
21
|
try {
|
|
21
|
-
await access(path);
|
|
22
22
|
return { path, source: await readFile(path, "utf8") };
|
|
23
23
|
}
|
|
24
24
|
catch (error) {
|
|
@@ -31,73 +31,58 @@ async function readViteConfig(projectDirectory) {
|
|
|
31
31
|
throw error;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
function configureVite(source) {
|
|
37
|
-
const importLine = 'import stylex from "@stylexjs/unplugin";';
|
|
38
|
-
const pluginPattern = /plugins:\s*\[([^\]]*)\]/s;
|
|
39
|
-
const stylexPlugin = 'stylex.vite({ unstable_moduleResolution: { type: "commonJS" } })';
|
|
40
|
-
if (!source.includes("stylex.vite(") && !pluginPattern.test(source)) {
|
|
41
|
-
throw new Error("Could not safely update the Vite plugins array. Add stylex.vite() manually.");
|
|
42
|
-
}
|
|
43
|
-
if (source.includes("stylex.vite("))
|
|
44
|
-
return source;
|
|
45
|
-
return (source.includes(importLine) ? source : `${importLine}\n${source}`).replace(pluginPattern, (_, plugins) => {
|
|
46
|
-
const prefix = plugins.trim() ? `${stylexPlugin}, ${plugins}` : stylexPlugin;
|
|
47
|
-
return `plugins: [${prefix}]`;
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
async function writeViteFiles(projectDirectory, tokenDirectory, refreshLegacyTokens) {
|
|
51
|
-
const { path: configPath, source: configSource } = await readViteConfig(projectDirectory);
|
|
52
|
-
const configuredVite = configureVite(configSource);
|
|
53
|
-
await writeNueeFiles(projectDirectory, tokenDirectory, refreshLegacyTokens);
|
|
54
|
-
await addResetImport(projectDirectory, tokenDirectory);
|
|
55
|
-
await writeFile(configPath, configuredVite, "utf8");
|
|
34
|
+
return undefined;
|
|
56
35
|
}
|
|
57
36
|
function getRelativeImportPath(from, to) {
|
|
58
37
|
const path = relative(dirname(from), to).split(sep).join("/");
|
|
59
38
|
return path.startsWith(".") ? path : `./${path}`;
|
|
60
39
|
}
|
|
61
|
-
async function
|
|
62
|
-
const
|
|
63
|
-
const resetImport = `@import "${getRelativeImportPath(cssPath, join(tokenDirectory, "reset.css"))}";`;
|
|
64
|
-
try {
|
|
65
|
-
const source = await readFile(cssPath, "utf8");
|
|
66
|
-
if (source.includes(resetImport))
|
|
67
|
-
return;
|
|
68
|
-
await writeFile(cssPath, `${resetImport}\n\n${source}`, "utf8");
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
72
|
-
await writeFile(cssPath, `${resetImport}\n`, "utf8");
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
throw error;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
async function writeNueeFiles(projectDirectory, tokenDirectory, refreshLegacyTokens = false) {
|
|
79
|
-
await mkdir(tokenDirectory, { recursive: true });
|
|
40
|
+
async function prepareFoundationFiles(tokenDirectory, refreshLegacyTokens) {
|
|
41
|
+
const files = [];
|
|
80
42
|
for (const file of await getFoundationFiles()) {
|
|
81
|
-
|
|
43
|
+
const path = join(tokenDirectory, file.name);
|
|
44
|
+
let currentSource;
|
|
45
|
+
try {
|
|
46
|
+
currentSource = await readFile(path, "utf8");
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (typeof error !== "object" ||
|
|
50
|
+
error === null ||
|
|
51
|
+
!("code" in error) ||
|
|
52
|
+
error.code !== "ENOENT")
|
|
53
|
+
throw error;
|
|
54
|
+
files.push({ path, source: file.content, flag: "wx" });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (refreshLegacyTokens &&
|
|
58
|
+
file.name === "semantic.stylex.ts" &&
|
|
59
|
+
currentSource.includes('bgCanvas: "initial"') &&
|
|
60
|
+
currentSource.includes('overlay: "initial"')) {
|
|
61
|
+
files.push({ path, source: file.content, flag: "w" });
|
|
62
|
+
}
|
|
82
63
|
}
|
|
64
|
+
return files;
|
|
83
65
|
}
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
async function writeTokenFile(path, source, shouldRefreshLegacySources, fileName) {
|
|
66
|
+
async function prepareResetImport(projectDirectory, tokenDirectory) {
|
|
67
|
+
const path = join(projectDirectory, "src/index.css");
|
|
68
|
+
const resetImport = `@import "${getRelativeImportPath(path, join(tokenDirectory, "reset.css"))}";`;
|
|
69
|
+
let source;
|
|
90
70
|
try {
|
|
91
|
-
|
|
92
|
-
if (shouldRefreshLegacySources && isLegacySemanticSource(fileName, currentSource)) {
|
|
93
|
-
await writeFile(path, source, "utf8");
|
|
94
|
-
}
|
|
71
|
+
source = await readFile(path, "utf8");
|
|
95
72
|
}
|
|
96
|
-
catch {
|
|
97
|
-
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (typeof error !== "object" ||
|
|
75
|
+
error === null ||
|
|
76
|
+
!("code" in error) ||
|
|
77
|
+
error.code !== "ENOENT")
|
|
78
|
+
throw error;
|
|
79
|
+
return { path, source: `${resetImport}\n`, flag: "wx" };
|
|
98
80
|
}
|
|
81
|
+
if (source.includes(resetImport))
|
|
82
|
+
return undefined;
|
|
83
|
+
return { path, source: `${resetImport}\n\n${source}`, flag: "w" };
|
|
99
84
|
}
|
|
100
|
-
export async function
|
|
85
|
+
export async function prepareInitialization(projectDirectory, options) {
|
|
101
86
|
if ((await hasConfig(projectDirectory)) && !options.force) {
|
|
102
87
|
throw new Error("nuee.json already exists. Use --force to create it again.");
|
|
103
88
|
}
|
|
@@ -106,40 +91,62 @@ export async function init(projectDirectory, options, shouldLog = true) {
|
|
|
106
91
|
? createInterface({ input: process.stdin, output: process.stdout })
|
|
107
92
|
: null;
|
|
108
93
|
try {
|
|
109
|
-
|
|
110
|
-
throw new Error(`Unsupported framework: ${options.framework}. Use vite or omit --framework.`);
|
|
111
|
-
}
|
|
94
|
+
const defaultAliases = await getDefaultAliases(projectDirectory);
|
|
112
95
|
const uiAlias = options.ui ??
|
|
113
96
|
(readline
|
|
114
|
-
? await ask("Enter the UI import alias.",
|
|
115
|
-
:
|
|
97
|
+
? await ask("Enter the UI import alias.", defaultAliases.ui, readline)
|
|
98
|
+
: defaultAliases.ui);
|
|
116
99
|
const stylesAlias = options.styles ??
|
|
117
100
|
options.tokens ??
|
|
118
101
|
(readline
|
|
119
|
-
? await ask("Enter the styles import alias.",
|
|
120
|
-
:
|
|
102
|
+
? await ask("Enter the styles import alias.", defaultAliases.styles, readline)
|
|
103
|
+
: defaultAliases.styles);
|
|
121
104
|
const tokenDirectory = await resolveConfigAlias(projectDirectory, stylesAlias, "aliases.styles");
|
|
122
105
|
await resolveConfigAlias(projectDirectory, uiAlias, "aliases.ui");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await installDependencies(projectDirectory, ["@stylexjs/unplugin"], true);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
if (options.framework === "vite") {
|
|
130
|
-
await writeViteFiles(projectDirectory, tokenDirectory, Boolean(options.force));
|
|
106
|
+
const viteConfig = options.vite ? await findViteConfig(projectDirectory) : undefined;
|
|
107
|
+
if (options.vite && !viteConfig) {
|
|
108
|
+
throw new Error("Could not find a Vite config file.");
|
|
131
109
|
}
|
|
132
|
-
|
|
133
|
-
|
|
110
|
+
const configuredVite = viteConfig ? configureVite(viteConfig.source) : undefined;
|
|
111
|
+
const files = await prepareFoundationFiles(tokenDirectory, Boolean(options.force));
|
|
112
|
+
if (viteConfig && configuredVite !== undefined) {
|
|
113
|
+
const resetFile = await prepareResetImport(projectDirectory, tokenDirectory);
|
|
114
|
+
if (resetFile)
|
|
115
|
+
files.push(resetFile);
|
|
116
|
+
files.push({ path: viteConfig.path, source: configuredVite, flag: "w" });
|
|
134
117
|
}
|
|
135
|
-
await
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
118
|
+
const runtimeDependencies = await getMissingDependencies(projectDirectory, [
|
|
119
|
+
"@stylexjs/stylex",
|
|
120
|
+
]);
|
|
121
|
+
const buildDependencies = await getMissingDependencies(projectDirectory, [
|
|
122
|
+
"@stylexjs/unplugin",
|
|
123
|
+
]);
|
|
124
|
+
return {
|
|
125
|
+
files,
|
|
126
|
+
runtimeDependencies: options["skip-dependencies"] ? [] : runtimeDependencies,
|
|
127
|
+
buildDependencies: options["skip-dependencies"] || !options.vite ? [] : buildDependencies,
|
|
128
|
+
config: {
|
|
129
|
+
accessibility: defaultConfig.accessibility,
|
|
130
|
+
aliases: { ui: uiAlias, styles: stylesAlias },
|
|
131
|
+
},
|
|
132
|
+
};
|
|
139
133
|
}
|
|
140
134
|
finally {
|
|
141
135
|
readline?.close();
|
|
142
136
|
}
|
|
137
|
+
}
|
|
138
|
+
export async function applyInitialization(projectDirectory, plan) {
|
|
139
|
+
await installDependencies(projectDirectory, plan.runtimeDependencies);
|
|
140
|
+
await installDependencies(projectDirectory, plan.buildDependencies, true);
|
|
141
|
+
for (const file of plan.files) {
|
|
142
|
+
await mkdir(dirname(file.path), { recursive: true });
|
|
143
|
+
await writeFile(file.path, file.source, { encoding: "utf8", flag: file.flag });
|
|
144
|
+
}
|
|
145
|
+
await writeConfig(projectDirectory, plan.config);
|
|
146
|
+
}
|
|
147
|
+
export async function init(projectDirectory, options, shouldLog = true) {
|
|
148
|
+
const plan = await prepareInitialization(projectDirectory, options);
|
|
149
|
+
await applyInitialization(projectDirectory, plan);
|
|
143
150
|
if (shouldLog)
|
|
144
151
|
console.log("✔ Initialized Nuee.");
|
|
145
152
|
}
|
package/dist/new-component.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { readConfig, resolveConfigAlias } from "./config.js";
|
|
4
4
|
function toPascalCase(name) {
|
|
5
5
|
return name
|
|
6
6
|
.split("-")
|
|
7
|
-
.filter(Boolean)
|
|
8
7
|
.map((part) => `${part[0]?.toUpperCase()}${part.slice(1)}`)
|
|
9
8
|
.join("");
|
|
10
9
|
}
|
|
@@ -17,19 +16,34 @@ export async function newComponent(projectDirectory, name) {
|
|
|
17
16
|
const componentName = toPascalCase(name);
|
|
18
17
|
const componentPath = join(uiDirectory, `${name}.tsx`);
|
|
19
18
|
const tokenImport = `${config.aliases.styles}/semantic.stylex`;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
await mkdir(uiDirectory, { recursive: true });
|
|
20
|
+
try {
|
|
21
|
+
await writeFile(componentPath, `import { colorVars, radiusVars, spacingVars } from "${tokenImport}";
|
|
22
|
+
import * as stylex from "@stylexjs/stylex";
|
|
23
|
+
import type { ComponentProps } from "react";
|
|
24
|
+
|
|
25
|
+
const styles = stylex.create({
|
|
26
|
+
root: {
|
|
27
|
+
backgroundColor: colorVars.bgSurface,
|
|
28
|
+
borderRadius: radiusVars.sm,
|
|
29
|
+
padding: spacingVars.space3,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export type ${componentName}Props = Omit<ComponentProps<"div">, "className" | "style"> & {
|
|
34
|
+
xstyle?: stylex.StyleXStyles;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export function ${componentName}({ xstyle, ...props }: ${componentName}Props) {
|
|
38
|
+
return <div {...props} {...stylex.props(styles.root, xstyle)} />;
|
|
39
|
+
}
|
|
40
|
+
`, { flag: "wx" });
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST") {
|
|
44
|
+
throw new Error(`${componentPath} already exists. Existing components will not be overwritten.`);
|
|
30
45
|
}
|
|
46
|
+
throw error;
|
|
31
47
|
}
|
|
32
|
-
await mkdir(uiDirectory, { recursive: true });
|
|
33
|
-
await writeFile(componentPath, `import { colorVars, radiusVars, spacingVars } from "${tokenImport}";\nimport * as stylex from "@stylexjs/stylex";\nimport type { ComponentProps } from "react";\n\nconst styles = stylex.create({\n root: {\n backgroundColor: colorVars.bgSurface,\n borderRadius: radiusVars.sm,\n padding: spacingVars.space3,\n },\n});\n\nexport type ${componentName}Props = ComponentProps<"div"> & {\n xstyle?: stylex.StyleXStyles;\n};\n\nexport function ${componentName}({ className, style, xstyle, ...props }: ${componentName}Props) {\n const stylexProps = stylex.props(styles.root, xstyle);\n\n return (\n <div\n {...props}\n className={[stylexProps.className, className].filter(Boolean).join(" ")}\n style={{ ...stylexProps.style, ...style }}\n />\n );\n}\n`, { flag: "wx" });
|
|
34
48
|
console.log(`Created a ${name} component scaffold: ${componentPath}`);
|
|
35
49
|
}
|