@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/registry.js
CHANGED
|
@@ -1,81 +1,49 @@
|
|
|
1
|
-
import { dependencyVersions, getRegistryItem } from "@nuee/registry";
|
|
2
|
-
|
|
3
|
-
if (URL.canParse(name))
|
|
4
|
-
return
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const item = await getRegistryItem(componentName);
|
|
12
|
-
components.add(componentName);
|
|
13
|
-
for (const file of item.files)
|
|
14
|
-
files.set(file.path, file);
|
|
15
|
-
for (const dependency of item.dependencies)
|
|
16
|
-
externalDependencies.add(dependency);
|
|
17
|
-
for (const dependency of item.registryDependencies) {
|
|
18
|
-
await visit(dependency);
|
|
19
|
-
}
|
|
1
|
+
import { dependencyVersions, getRegistryItem, parseRegistryItem, } from "@nuee/registry";
|
|
2
|
+
async function readRegistryItem(name) {
|
|
3
|
+
if (!URL.canParse(name))
|
|
4
|
+
return getRegistryItem(name);
|
|
5
|
+
const response = await fetch(name);
|
|
6
|
+
if (!response.ok)
|
|
7
|
+
throw new Error(`Could not load the registry: ${response.status}`);
|
|
8
|
+
const value = await response.json();
|
|
9
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10
|
+
throw new Error("This is not a valid Nuee registry item.");
|
|
20
11
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
const candidate = value;
|
|
13
|
+
const item = {
|
|
14
|
+
...candidate,
|
|
15
|
+
name: candidate.name === undefined ? name : candidate.name,
|
|
16
|
+
primaryExport: candidate.primaryExport === undefined
|
|
17
|
+
? (candidate.name ?? "Component")
|
|
18
|
+
: candidate.primaryExport,
|
|
19
|
+
registryDependencies: candidate.registryDependencies === undefined ? [] : candidate.registryDependencies,
|
|
27
20
|
};
|
|
21
|
+
return parseRegistryItem(item);
|
|
28
22
|
}
|
|
29
|
-
async function
|
|
23
|
+
export async function resolveComponent(name) {
|
|
24
|
+
const visited = new Set();
|
|
30
25
|
const components = new Set();
|
|
31
|
-
const
|
|
26
|
+
const dependencies = new Set();
|
|
32
27
|
const files = new Map();
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
const root = await readRegistryItem(name);
|
|
29
|
+
async function visit(key, item) {
|
|
30
|
+
if (visited.has(key))
|
|
35
31
|
return;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
visited.add(key);
|
|
33
|
+
const current = item ?? (await readRegistryItem(key));
|
|
34
|
+
components.add(current.name);
|
|
35
|
+
for (const file of current.files)
|
|
39
36
|
files.set(file.path, file);
|
|
40
|
-
for (const dependency of
|
|
41
|
-
|
|
42
|
-
for (const dependency of
|
|
43
|
-
await
|
|
44
|
-
}
|
|
45
|
-
async function visitRemote(itemUrl) {
|
|
46
|
-
const response = await fetch(itemUrl);
|
|
47
|
-
if (!response.ok)
|
|
48
|
-
throw new Error(`Could not load the registry: ${response.status}`);
|
|
49
|
-
const item = (await response.json());
|
|
50
|
-
if (!Array.isArray(item.files) ||
|
|
51
|
-
!Array.isArray(item.dependencies) ||
|
|
52
|
-
!item.files.every((file) => typeof file === "object" &&
|
|
53
|
-
file !== null &&
|
|
54
|
-
typeof file.path === "string" &&
|
|
55
|
-
typeof file.content === "string")) {
|
|
56
|
-
throw new Error("This is not a valid Nuee registry item.");
|
|
57
|
-
}
|
|
58
|
-
const itemName = item.name ?? itemUrl;
|
|
59
|
-
if (components.has(itemName))
|
|
60
|
-
return;
|
|
61
|
-
components.add(itemName);
|
|
62
|
-
for (const file of item.files)
|
|
63
|
-
files.set(file.path, file);
|
|
64
|
-
for (const dependency of item.dependencies)
|
|
65
|
-
externalDependencies.add(dependency);
|
|
66
|
-
for (const dependency of item.registryDependencies ?? []) {
|
|
67
|
-
if (URL.canParse(dependency))
|
|
68
|
-
await visitRemote(dependency);
|
|
69
|
-
else
|
|
70
|
-
await visitLocal(dependency);
|
|
71
|
-
}
|
|
72
|
-
return item.primaryExport ?? item.name ?? "Component";
|
|
37
|
+
for (const dependency of current.dependencies)
|
|
38
|
+
dependencies.add(dependency);
|
|
39
|
+
for (const dependency of current.registryDependencies)
|
|
40
|
+
await visit(dependency);
|
|
73
41
|
}
|
|
74
|
-
|
|
42
|
+
await visit(name, root);
|
|
75
43
|
return {
|
|
76
44
|
components: [...components],
|
|
77
|
-
externalDependencies: [...externalDependencies].map((dependency) => `${dependency}@${dependencyVersions[dependency] ?? "latest"}`),
|
|
78
45
|
files: [...files.values()],
|
|
79
|
-
|
|
46
|
+
externalDependencies: [...dependencies].map((dependency) => `${dependency}@${dependencyVersions[dependency] ?? "latest"}`),
|
|
47
|
+
primaryExport: root.primaryExport,
|
|
80
48
|
};
|
|
81
49
|
}
|
package/dist/source.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ArrayExpression } from "@babel/types";
|
|
2
|
+
export declare function parseSource(source: string): import("@babel/parser").ParseResult<import("@babel/types").File>;
|
|
3
|
+
type StylexImport = {
|
|
4
|
+
name: string;
|
|
5
|
+
direct: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function inspectViteConfig(source: string): {
|
|
8
|
+
plugins: ArrayExpression;
|
|
9
|
+
imports: StylexImport[];
|
|
10
|
+
hasCompiler: boolean;
|
|
11
|
+
} | undefined;
|
|
12
|
+
export declare function configureVite(source: string): string;
|
|
13
|
+
export declare function removeReducedMotionStyles(source: string): string;
|
|
14
|
+
export {};
|
package/dist/source.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { parse } from "@babel/parser";
|
|
2
|
+
import { traverseFast } from "@babel/types";
|
|
3
|
+
const parserOptions = { sourceType: "module", plugins: ["typescript", "jsx"] };
|
|
4
|
+
export function parseSource(source) {
|
|
5
|
+
return parse(source, { ...parserOptions, tokens: true, plugins: [...parserOptions.plugins] });
|
|
6
|
+
}
|
|
7
|
+
function getViteImports(body) {
|
|
8
|
+
const defineConfigNames = new Set();
|
|
9
|
+
const stylexImports = [];
|
|
10
|
+
for (const node of body) {
|
|
11
|
+
if (node.type !== "ImportDeclaration")
|
|
12
|
+
continue;
|
|
13
|
+
if (node.source.value === "vite") {
|
|
14
|
+
for (const specifier of node.specifiers) {
|
|
15
|
+
if (specifier.type !== "ImportSpecifier")
|
|
16
|
+
continue;
|
|
17
|
+
if (specifier.imported.type !== "Identifier")
|
|
18
|
+
continue;
|
|
19
|
+
if (specifier.imported.name !== "defineConfig")
|
|
20
|
+
continue;
|
|
21
|
+
defineConfigNames.add(specifier.local.name);
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (node.source.value !== "@stylexjs/unplugin" &&
|
|
26
|
+
node.source.value !== "@stylexjs/unplugin/vite")
|
|
27
|
+
continue;
|
|
28
|
+
for (const specifier of node.specifiers) {
|
|
29
|
+
if (specifier.type !== "ImportDefaultSpecifier")
|
|
30
|
+
continue;
|
|
31
|
+
stylexImports.push({
|
|
32
|
+
name: specifier.local.name,
|
|
33
|
+
direct: node.source.value.endsWith("/vite"),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { defineConfigNames, stylexImports };
|
|
38
|
+
}
|
|
39
|
+
function hasStylexCompiler(plugins, imports) {
|
|
40
|
+
for (const node of plugins.elements) {
|
|
41
|
+
if (node?.type !== "CallExpression")
|
|
42
|
+
continue;
|
|
43
|
+
const callee = node.callee;
|
|
44
|
+
if (callee.type === "Identifier") {
|
|
45
|
+
if (imports.some((binding) => binding.direct && binding.name === callee.name))
|
|
46
|
+
return true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (callee.type !== "MemberExpression" || callee.computed)
|
|
50
|
+
continue;
|
|
51
|
+
if (callee.object.type !== "Identifier")
|
|
52
|
+
continue;
|
|
53
|
+
if (callee.property.type !== "Identifier" || callee.property.name !== "vite")
|
|
54
|
+
continue;
|
|
55
|
+
const name = callee.object.name;
|
|
56
|
+
if (imports.some((binding) => !binding.direct && binding.name === name))
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
export function inspectViteConfig(source) {
|
|
62
|
+
const file = parseSource(source);
|
|
63
|
+
const { defineConfigNames, stylexImports } = getViteImports(file.program.body);
|
|
64
|
+
const exported = file.program.body.find((node) => node.type === "ExportDefaultDeclaration");
|
|
65
|
+
if (!exported || exported.type !== "ExportDefaultDeclaration")
|
|
66
|
+
return undefined;
|
|
67
|
+
let config = exported.declaration;
|
|
68
|
+
if (config.type === "CallExpression" && config.arguments.length === 1) {
|
|
69
|
+
const { callee } = config;
|
|
70
|
+
if (callee.type !== "Identifier" || !defineConfigNames.has(callee.name))
|
|
71
|
+
return undefined;
|
|
72
|
+
const argument = config.arguments[0];
|
|
73
|
+
if (argument.type !== "ObjectExpression")
|
|
74
|
+
return undefined;
|
|
75
|
+
config = argument;
|
|
76
|
+
}
|
|
77
|
+
if (config.type !== "ObjectExpression")
|
|
78
|
+
return undefined;
|
|
79
|
+
let plugins;
|
|
80
|
+
for (const property of config.properties) {
|
|
81
|
+
if (property.type === "SpreadElement" || property.computed)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (property.type !== "ObjectProperty")
|
|
84
|
+
continue;
|
|
85
|
+
const key = property.key;
|
|
86
|
+
const isPlugins = (key.type === "Identifier" && key.name === "plugins") ||
|
|
87
|
+
(key.type === "StringLiteral" && key.value === "plugins");
|
|
88
|
+
if (!isPlugins)
|
|
89
|
+
continue;
|
|
90
|
+
if (plugins || property.value.type !== "ArrayExpression")
|
|
91
|
+
return undefined;
|
|
92
|
+
plugins = property.value;
|
|
93
|
+
}
|
|
94
|
+
if (!plugins)
|
|
95
|
+
return undefined;
|
|
96
|
+
return {
|
|
97
|
+
plugins,
|
|
98
|
+
imports: stylexImports,
|
|
99
|
+
hasCompiler: hasStylexCompiler(plugins, stylexImports),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function configureVite(source) {
|
|
103
|
+
const inspected = inspectViteConfig(source);
|
|
104
|
+
if (!inspected || inspected.plugins.elements.some((node) => node?.type === "SpreadElement")) {
|
|
105
|
+
throw new Error("Could not safely update the Vite plugins array. Add the StyleX compiler manually.");
|
|
106
|
+
}
|
|
107
|
+
if (inspected.hasCompiler)
|
|
108
|
+
return source;
|
|
109
|
+
const binding = inspected.imports[0];
|
|
110
|
+
// An unused name avoids colliding with a user variable or an existing import.
|
|
111
|
+
let name = "nueeStylex";
|
|
112
|
+
while (source.includes(name))
|
|
113
|
+
name += "_";
|
|
114
|
+
let factory = `${name}.vite`;
|
|
115
|
+
if (binding)
|
|
116
|
+
factory = binding.direct ? binding.name : `${binding.name}.vite`;
|
|
117
|
+
const plugin = `${factory}({ unstable_moduleResolution: { type: "commonJS" } })`;
|
|
118
|
+
const offset = inspected.plugins.start + 1;
|
|
119
|
+
const configured = source.slice(0, offset) +
|
|
120
|
+
plugin +
|
|
121
|
+
(inspected.plugins.elements.length ? ", " : "") +
|
|
122
|
+
source.slice(offset);
|
|
123
|
+
const result = binding ? configured : `import ${name} from "@stylexjs/unplugin";\n${configured}`;
|
|
124
|
+
parseSource(result);
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
export function removeReducedMotionStyles(source) {
|
|
128
|
+
const file = parseSource(source);
|
|
129
|
+
const removals = [];
|
|
130
|
+
traverseFast(file, (node) => {
|
|
131
|
+
if (node.type !== "ObjectProperty" ||
|
|
132
|
+
node.computed ||
|
|
133
|
+
node.key.type !== "StringLiteral" ||
|
|
134
|
+
node.key.value !== "@media (prefers-reduced-motion: reduce)")
|
|
135
|
+
return;
|
|
136
|
+
const start = node.start;
|
|
137
|
+
let end = node.end;
|
|
138
|
+
const nextToken = file.tokens?.find((token) => token.start >= end && typeof token.type !== "string");
|
|
139
|
+
if (nextToken && source.slice(nextToken.start, nextToken.end) === ",")
|
|
140
|
+
end = nextToken.end;
|
|
141
|
+
removals.push({ start, end });
|
|
142
|
+
});
|
|
143
|
+
// Keep outer ranges first so nested rules are removed with their parent.
|
|
144
|
+
const outerRemovals = [];
|
|
145
|
+
let coveredEnd = -1;
|
|
146
|
+
for (const removal of removals.sort((a, b) => a.start - b.start)) {
|
|
147
|
+
if (removal.end <= coveredEnd)
|
|
148
|
+
continue;
|
|
149
|
+
outerRemovals.push(removal);
|
|
150
|
+
coveredEnd = removal.end;
|
|
151
|
+
}
|
|
152
|
+
let result = source;
|
|
153
|
+
let boundary = source.length;
|
|
154
|
+
for (const removal of outerRemovals.reverse()) {
|
|
155
|
+
if (removal.end > boundary)
|
|
156
|
+
continue;
|
|
157
|
+
result = result.slice(0, removal.start) + result.slice(removal.end);
|
|
158
|
+
boundary = removal.start;
|
|
159
|
+
}
|
|
160
|
+
parseSource(result);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuee/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,11 +23,14 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@
|
|
26
|
+
"@babel/parser": "7.29.8",
|
|
27
|
+
"@babel/types": "7.29.8",
|
|
28
|
+
"@nuee/registry": "0.5.0",
|
|
29
|
+
"get-tsconfig": "^4.14.3",
|
|
27
30
|
"jsonc-parser": "^3.3.1"
|
|
28
31
|
},
|
|
29
32
|
"devDependencies": {
|
|
30
|
-
"@types/node": "
|
|
33
|
+
"@types/node": "26.4.1",
|
|
31
34
|
"typescript": "7.0.2"
|
|
32
35
|
},
|
|
33
36
|
"scripts": {
|