stera-ui 0.8.0 → 0.9.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-JTKZDMNI.js +2 -0
- package/dist/chunk-42DL2YAQ.js +2 -0
- package/dist/chunk-FZGIVCWE.js +42175 -0
- package/dist/chunk-LUUYMQIF.js +97 -0
- package/dist/chunk-MBBLZJIK.js +2 -0
- package/dist/chunk-OPVLMYW5.js +2 -0
- package/dist/chunk-OSMC63WJ.js +2 -0
- package/dist/chunk-P2O7D5BG.js +2 -0
- package/dist/chunk-UVHQPGZ3.js +7 -0
- package/dist/chunk-XJ6VM67K.js +2 -0
- package/dist/cli.js +29 -32
- package/dist/index.js +2 -86
- package/dist/init-XAKB27HW.js +12 -0
- package/dist/list-W7ECLPKW.js +5 -0
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +2 -17
- package/dist/schema/index.js +2 -18
- package/dist/utils/index.d.ts +26 -3
- package/dist/utils/index.js +2 -58
- package/package.json +6 -8
- package/dist/add-WUTTJN25.js +0 -215
- package/dist/chunk-4E46BULJ.js +0 -79
- package/dist/chunk-5NLD52O5.js +0 -376
- package/dist/chunk-BJNLGEZJ.js +0 -100
- package/dist/chunk-KGMF6UW4.js +0 -21
- package/dist/chunk-KKUJRJ2N.js +0 -209
- package/dist/chunk-V4TMOT6I.js +0 -880
- package/dist/init-QYYCGWYV.js +0 -763
- package/dist/list-M73QTIWR.js +0 -44
package/dist/add-WUTTJN25.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
CONFIG_FILE,
|
|
4
|
-
findConfigPath,
|
|
5
|
-
installDependencies,
|
|
6
|
-
loadConfig,
|
|
7
|
-
migrateLegacyStyles,
|
|
8
|
-
writeComponentFiles,
|
|
9
|
-
writeStyles
|
|
10
|
-
} from "./chunk-5NLD52O5.js";
|
|
11
|
-
import {
|
|
12
|
-
ComponentNotFoundError,
|
|
13
|
-
createSpinner,
|
|
14
|
-
resolveDependencies
|
|
15
|
-
} from "./chunk-KKUJRJ2N.js";
|
|
16
|
-
import {
|
|
17
|
-
CHECK,
|
|
18
|
-
CROSS,
|
|
19
|
-
dim
|
|
20
|
-
} from "./chunk-KGMF6UW4.js";
|
|
21
|
-
|
|
22
|
-
// src/commands/add.ts
|
|
23
|
-
import path from "path";
|
|
24
|
-
|
|
25
|
-
// src/utils/transform.ts
|
|
26
|
-
function applyTransforms(content, ctx, transforms2) {
|
|
27
|
-
return transforms2.reduce((acc, fn) => fn(acc, ctx), content);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// src/utils/transform-imports.ts
|
|
31
|
-
var DEFAULT_ALIASES = {
|
|
32
|
-
utils: "@/lib/utils",
|
|
33
|
-
ui: "@/components/ui",
|
|
34
|
-
components: "@/components",
|
|
35
|
-
lib: "@/lib",
|
|
36
|
-
hooks: "@/hooks"
|
|
37
|
-
};
|
|
38
|
-
var transformImports = (content, ctx) => {
|
|
39
|
-
if (!ctx.filename.endsWith(".ts") && !ctx.filename.endsWith(".tsx")) {
|
|
40
|
-
return content;
|
|
41
|
-
}
|
|
42
|
-
const { aliases } = ctx.config;
|
|
43
|
-
const rules = [];
|
|
44
|
-
if (aliases.utils !== DEFAULT_ALIASES.utils) {
|
|
45
|
-
rules.push({
|
|
46
|
-
type: "exact",
|
|
47
|
-
from: DEFAULT_ALIASES.utils,
|
|
48
|
-
to: aliases.utils
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
if (aliases.ui !== DEFAULT_ALIASES.ui) {
|
|
52
|
-
rules.push({ type: "prefix", from: DEFAULT_ALIASES.ui, to: aliases.ui });
|
|
53
|
-
}
|
|
54
|
-
if (aliases.components !== DEFAULT_ALIASES.components) {
|
|
55
|
-
rules.push({
|
|
56
|
-
type: "prefix",
|
|
57
|
-
from: DEFAULT_ALIASES.components,
|
|
58
|
-
to: aliases.components
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
if (aliases.lib !== DEFAULT_ALIASES.lib) {
|
|
62
|
-
rules.push({ type: "prefix", from: DEFAULT_ALIASES.lib, to: aliases.lib });
|
|
63
|
-
}
|
|
64
|
-
if (aliases.hooks !== DEFAULT_ALIASES.hooks) {
|
|
65
|
-
rules.push({
|
|
66
|
-
type: "prefix",
|
|
67
|
-
from: DEFAULT_ALIASES.hooks,
|
|
68
|
-
to: aliases.hooks
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
if (rules.length === 0) {
|
|
72
|
-
return content;
|
|
73
|
-
}
|
|
74
|
-
return content.replace(
|
|
75
|
-
/from\s+(["'])([^"']+)\1/g,
|
|
76
|
-
(match, quote, importPath) => {
|
|
77
|
-
for (const rule of rules) {
|
|
78
|
-
if (rule.type === "exact" && importPath === rule.from) {
|
|
79
|
-
return `from ${quote}${rule.to}${quote}`;
|
|
80
|
-
}
|
|
81
|
-
if (rule.type === "prefix" && importPath.startsWith(rule.from + "/")) {
|
|
82
|
-
const rest = importPath.slice(rule.from.length);
|
|
83
|
-
return `from ${quote}${rule.to}${rest}${quote}`;
|
|
84
|
-
}
|
|
85
|
-
if (rule.type === "prefix" && importPath === rule.from) {
|
|
86
|
-
return `from ${quote}${rule.to}${quote}`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return match;
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// src/commands/add.ts
|
|
95
|
-
var transforms = [transformImports];
|
|
96
|
-
async function add(components, options) {
|
|
97
|
-
const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();
|
|
98
|
-
const configPath = findConfigPath(cwd);
|
|
99
|
-
if (!configPath) {
|
|
100
|
-
console.error(
|
|
101
|
-
` ${CROSS} ${CONFIG_FILE} not found. Run "stera-ui init" first.`
|
|
102
|
-
);
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
const config = loadConfig(cwd);
|
|
106
|
-
if (!config) {
|
|
107
|
-
console.error(` ${CROSS} Failed to parse ${CONFIG_FILE}.`);
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
const projectRoot = path.dirname(configPath);
|
|
111
|
-
if (components.includes("globals")) {
|
|
112
|
-
if (components.length > 1) {
|
|
113
|
-
console.error(
|
|
114
|
-
` ${CROSS} "stera-ui add globals" refreshes design tokens and cannot be combined with other components.`
|
|
115
|
-
);
|
|
116
|
-
console.error(
|
|
117
|
-
` Run "stera-ui add globals" and "stera-ui add ${components.filter((c) => c !== "globals").join(" ")}" separately.`
|
|
118
|
-
);
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
const spinner2 = createSpinner("Refreshing base styles");
|
|
122
|
-
let result;
|
|
123
|
-
let migrated = null;
|
|
124
|
-
try {
|
|
125
|
-
migrated = await migrateLegacyStyles(config, projectRoot);
|
|
126
|
-
result = await writeStyles(config, projectRoot, {
|
|
127
|
-
overwrite: options.overwrite
|
|
128
|
-
});
|
|
129
|
-
} catch (err) {
|
|
130
|
-
spinner2.fail("Failed to refresh base styles");
|
|
131
|
-
throw err;
|
|
132
|
-
}
|
|
133
|
-
spinner2.succeed(`Refreshed ${result.written.length} style files`);
|
|
134
|
-
if (migrated) {
|
|
135
|
-
console.log(
|
|
136
|
-
` ${CHECK} Migrated ${path.relative(projectRoot, migrated)} to ui/`
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
for (const target of result.written) {
|
|
140
|
-
console.log(` ${CHECK} ${target}`);
|
|
141
|
-
}
|
|
142
|
-
for (const file of result.skipped) {
|
|
143
|
-
const reason = file.reason === "unchanged" ? "unchanged" : "kept your version";
|
|
144
|
-
console.log(` ${dim(`- ${file.path} (${reason})`)}`);
|
|
145
|
-
}
|
|
146
|
-
console.log("");
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const spinner = createSpinner("Fetching registry");
|
|
150
|
-
let resolved;
|
|
151
|
-
try {
|
|
152
|
-
resolved = await resolveDependencies(components);
|
|
153
|
-
} catch (err) {
|
|
154
|
-
if (err instanceof ComponentNotFoundError) {
|
|
155
|
-
spinner.fail(err.message);
|
|
156
|
-
console.error(` Run "stera-ui list" to see available components.`);
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
spinner.fail("Failed to fetch registry");
|
|
160
|
-
throw err;
|
|
161
|
-
}
|
|
162
|
-
spinner.succeed("Registry resolved");
|
|
163
|
-
for (const item of resolved) {
|
|
164
|
-
for (const file of item.files ?? []) {
|
|
165
|
-
if (file.content) {
|
|
166
|
-
file.content = applyTransforms(
|
|
167
|
-
file.content,
|
|
168
|
-
{ config, filename: file.path },
|
|
169
|
-
transforms
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
const requested = new Set(components);
|
|
175
|
-
console.log("\n Installing components\n");
|
|
176
|
-
for (const item of resolved) {
|
|
177
|
-
const tag = requested.has(item.name) ? "" : dim(" (dependency)");
|
|
178
|
-
console.log(` \u2192 ${item.name}${tag}`);
|
|
179
|
-
}
|
|
180
|
-
const allNpmDeps = [];
|
|
181
|
-
for (const item of resolved) {
|
|
182
|
-
if (item.dependencies) {
|
|
183
|
-
allNpmDeps.push(...item.dependencies);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const uniqueNpmDeps = [...new Set(allNpmDeps)].sort();
|
|
187
|
-
if (uniqueNpmDeps.length > 0) {
|
|
188
|
-
console.log("\n npm packages\n");
|
|
189
|
-
for (const dep of uniqueNpmDeps) {
|
|
190
|
-
console.log(` \u2192 ${dep}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
console.log("");
|
|
194
|
-
const { written, skipped } = await writeComponentFiles(
|
|
195
|
-
resolved,
|
|
196
|
-
config,
|
|
197
|
-
projectRoot,
|
|
198
|
-
{ overwrite: options.overwrite }
|
|
199
|
-
);
|
|
200
|
-
for (const file of written) {
|
|
201
|
-
console.log(` ${CHECK} ${file}`);
|
|
202
|
-
}
|
|
203
|
-
for (const file of skipped) {
|
|
204
|
-
const label = file.reason === "unchanged" ? "(unchanged)" : "(skipped)";
|
|
205
|
-
console.log(` ${dim(`\xB7 ${file.path} ${label}`)}`);
|
|
206
|
-
}
|
|
207
|
-
if (uniqueNpmDeps.length > 0) {
|
|
208
|
-
console.log("");
|
|
209
|
-
await installDependencies(uniqueNpmDeps, projectRoot);
|
|
210
|
-
}
|
|
211
|
-
console.log("");
|
|
212
|
-
}
|
|
213
|
-
export {
|
|
214
|
-
add
|
|
215
|
-
};
|
package/dist/chunk-4E46BULJ.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// src/schema/index.ts
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
var registryItemTypeSchema = z.enum([
|
|
4
|
-
"registry:ui",
|
|
5
|
-
"registry:component",
|
|
6
|
-
"registry:hook",
|
|
7
|
-
"registry:lib",
|
|
8
|
-
"registry:style",
|
|
9
|
-
"registry:font"
|
|
10
|
-
]);
|
|
11
|
-
var registryItemFileSchema = z.object({
|
|
12
|
-
path: z.string(),
|
|
13
|
-
type: registryItemTypeSchema,
|
|
14
|
-
content: z.string().optional(),
|
|
15
|
-
target: z.string().optional()
|
|
16
|
-
});
|
|
17
|
-
var registryItemFontSchema = z.object({
|
|
18
|
-
family: z.string(),
|
|
19
|
-
provider: z.literal("google"),
|
|
20
|
-
import: z.string(),
|
|
21
|
-
variable: z.string(),
|
|
22
|
-
weight: z.array(z.string()).optional(),
|
|
23
|
-
subsets: z.array(z.string()).optional(),
|
|
24
|
-
selector: z.string().optional(),
|
|
25
|
-
dependency: z.string().optional()
|
|
26
|
-
});
|
|
27
|
-
var registryItemCommonSchema = z.object({
|
|
28
|
-
name: z.string(),
|
|
29
|
-
dependencies: z.array(z.string()).optional(),
|
|
30
|
-
registryDependencies: z.array(z.string()).optional(),
|
|
31
|
-
files: z.array(registryItemFileSchema).optional()
|
|
32
|
-
});
|
|
33
|
-
var registryItemSchema = z.discriminatedUnion("type", [
|
|
34
|
-
registryItemCommonSchema.extend({
|
|
35
|
-
type: z.literal("registry:font"),
|
|
36
|
-
font: registryItemFontSchema,
|
|
37
|
-
files: z.array(registryItemFileSchema).optional()
|
|
38
|
-
}),
|
|
39
|
-
registryItemCommonSchema.extend({
|
|
40
|
-
type: registryItemTypeSchema.exclude(["registry:font"]),
|
|
41
|
-
files: z.array(registryItemFileSchema)
|
|
42
|
-
})
|
|
43
|
-
]);
|
|
44
|
-
var registryIndexEntrySchema = z.object({
|
|
45
|
-
name: z.string(),
|
|
46
|
-
type: z.string(),
|
|
47
|
-
dependencies: z.array(z.string()).optional(),
|
|
48
|
-
registryDependencies: z.array(z.string()).optional()
|
|
49
|
-
});
|
|
50
|
-
var registryIndexSchema = z.object({
|
|
51
|
-
name: z.string(),
|
|
52
|
-
items: z.array(registryIndexEntrySchema)
|
|
53
|
-
});
|
|
54
|
-
var configSchema = z.object({
|
|
55
|
-
$schema: z.string().optional(),
|
|
56
|
-
version: z.literal(1),
|
|
57
|
-
css: z.string(),
|
|
58
|
-
aliases: z.object({
|
|
59
|
-
components: z.string(),
|
|
60
|
-
utils: z.string(),
|
|
61
|
-
ui: z.string(),
|
|
62
|
-
lib: z.string(),
|
|
63
|
-
hooks: z.string()
|
|
64
|
-
}),
|
|
65
|
-
fonts: z.object({
|
|
66
|
-
strategy: z.enum(["stera-default", "keep-existing", "skip"]),
|
|
67
|
-
nextFont: z.boolean().optional()
|
|
68
|
-
}).optional()
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
export {
|
|
72
|
-
registryItemTypeSchema,
|
|
73
|
-
registryItemFileSchema,
|
|
74
|
-
registryItemFontSchema,
|
|
75
|
-
registryItemSchema,
|
|
76
|
-
registryIndexEntrySchema,
|
|
77
|
-
registryIndexSchema,
|
|
78
|
-
configSchema
|
|
79
|
-
};
|
package/dist/chunk-5NLD52O5.js
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
createSpinner,
|
|
4
|
-
fetchRegistryItem
|
|
5
|
-
} from "./chunk-KKUJRJ2N.js";
|
|
6
|
-
|
|
7
|
-
// src/utils/resolve-config.ts
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import path from "path";
|
|
10
|
-
var CONFIG_FILE = "stera.config.json";
|
|
11
|
-
var LEGACY_CONFIG_FILE = "components.json";
|
|
12
|
-
function migrateConfig(raw) {
|
|
13
|
-
if (!("version" in raw) && "tailwind" in raw) {
|
|
14
|
-
const legacy = raw;
|
|
15
|
-
return {
|
|
16
|
-
version: 1,
|
|
17
|
-
css: legacy.tailwind.css || "src/styles/globals.css",
|
|
18
|
-
aliases: legacy.aliases
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
return raw;
|
|
22
|
-
}
|
|
23
|
-
var warnedLegacyFilename = false;
|
|
24
|
-
function warnLegacyFilenameOnce(legacyPath) {
|
|
25
|
-
if (warnedLegacyFilename) return;
|
|
26
|
-
warnedLegacyFilename = true;
|
|
27
|
-
console.warn(
|
|
28
|
-
` \u26A0 Found ${LEGACY_CONFIG_FILE}. Rename to ${CONFIG_FILE} \u2014 legacy filename support will be removed in a future release.
|
|
29
|
-
(${legacyPath})`
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
function findConfigPath(cwd) {
|
|
33
|
-
let dir = path.resolve(cwd);
|
|
34
|
-
while (true) {
|
|
35
|
-
const configPath = path.join(dir, CONFIG_FILE);
|
|
36
|
-
if (fs.existsSync(configPath)) return configPath;
|
|
37
|
-
const legacyPath = path.join(dir, LEGACY_CONFIG_FILE);
|
|
38
|
-
if (fs.existsSync(legacyPath)) return legacyPath;
|
|
39
|
-
const parent = path.dirname(dir);
|
|
40
|
-
if (parent === dir) return null;
|
|
41
|
-
dir = parent;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function loadConfig(cwd) {
|
|
45
|
-
const configPath = findConfigPath(cwd);
|
|
46
|
-
if (!configPath) return null;
|
|
47
|
-
if (path.basename(configPath) === LEGACY_CONFIG_FILE) {
|
|
48
|
-
warnLegacyFilenameOnce(configPath);
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
52
|
-
return migrateConfig(raw);
|
|
53
|
-
} catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// src/utils/install-deps.ts
|
|
59
|
-
import fs2 from "fs";
|
|
60
|
-
import path2 from "path";
|
|
61
|
-
import { detect } from "@antfu/ni";
|
|
62
|
-
import { execa } from "execa";
|
|
63
|
-
async function detectPackageManager(cwd) {
|
|
64
|
-
const detected = await detect({ programmatic: true, cwd });
|
|
65
|
-
if (detected === "pnpm@6" || detected === "pnpm") return "pnpm";
|
|
66
|
-
if (detected === "yarn@berry" || detected === "yarn") return "yarn";
|
|
67
|
-
if (detected === "bun") return "bun";
|
|
68
|
-
if (detected === "npm") return "npm";
|
|
69
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
70
|
-
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
71
|
-
if (userAgent.startsWith("yarn")) return "yarn";
|
|
72
|
-
if (userAgent.startsWith("bun")) return "bun";
|
|
73
|
-
return "npm";
|
|
74
|
-
}
|
|
75
|
-
function getInstallArgs(pm, deps) {
|
|
76
|
-
switch (pm) {
|
|
77
|
-
case "pnpm":
|
|
78
|
-
return ["pnpm", ["add", ...deps]];
|
|
79
|
-
case "yarn":
|
|
80
|
-
return ["yarn", ["add", ...deps]];
|
|
81
|
-
case "bun":
|
|
82
|
-
return ["bun", ["add", ...deps]];
|
|
83
|
-
default:
|
|
84
|
-
return ["npm", ["install", ...deps]];
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async function installDependencies(deps, cwd) {
|
|
88
|
-
if (deps.length === 0) return;
|
|
89
|
-
const pkgPath = path2.join(cwd, "package.json");
|
|
90
|
-
let existing = /* @__PURE__ */ new Set();
|
|
91
|
-
if (fs2.existsSync(pkgPath)) {
|
|
92
|
-
try {
|
|
93
|
-
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
94
|
-
existing = new Set(
|
|
95
|
-
Object.keys({ ...pkg.dependencies, ...pkg.devDependencies })
|
|
96
|
-
);
|
|
97
|
-
} catch {
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const toInstall = deps.filter((dep) => !existing.has(dep));
|
|
101
|
-
if (toInstall.length === 0) return;
|
|
102
|
-
const pm = await detectPackageManager(cwd);
|
|
103
|
-
const [cmd, args] = getInstallArgs(pm, toInstall);
|
|
104
|
-
const spinner = createSpinner(`Installing with ${pm}`);
|
|
105
|
-
try {
|
|
106
|
-
await execa(cmd, args, { cwd });
|
|
107
|
-
spinner.succeed(`Installed with ${pm}`);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
spinner.fail(`Install failed`);
|
|
110
|
-
if (error instanceof Error && "stdout" in error && typeof error.stdout === "string" && error.stdout.includes("ERR_PNPM_ADDING_TO_ROOT")) {
|
|
111
|
-
throw new Error(
|
|
112
|
-
`Cannot install dependencies at a pnpm workspace root.
|
|
113
|
-
Run stera-ui init from within a specific workspace package instead,
|
|
114
|
-
or use "pnpm add -w <package>" manually to install at the root.`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
throw error;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// src/utils/patch-css-vars.ts
|
|
122
|
-
import fs3 from "fs";
|
|
123
|
-
function patchCssVariables(filePath, patches) {
|
|
124
|
-
const content = fs3.readFileSync(filePath, "utf-8");
|
|
125
|
-
const lines = content.split("\n");
|
|
126
|
-
const patched = [];
|
|
127
|
-
const compiled = Object.entries(patches).map(([prop, newValue]) => ({
|
|
128
|
-
prop,
|
|
129
|
-
newValue,
|
|
130
|
-
regex: new RegExp(`(\\s*${escapeRegex(prop)}:\\s*).+?(;)`)
|
|
131
|
-
}));
|
|
132
|
-
for (let i = 0; i < lines.length; i++) {
|
|
133
|
-
for (const { prop, newValue, regex } of compiled) {
|
|
134
|
-
if (regex.test(lines[i])) {
|
|
135
|
-
lines[i] = lines[i].replace(regex, `$1${newValue}$2`);
|
|
136
|
-
if (!patched.includes(prop)) patched.push(prop);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (patched.length > 0) {
|
|
141
|
-
fs3.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
142
|
-
}
|
|
143
|
-
return patched;
|
|
144
|
-
}
|
|
145
|
-
function removeCssImport(filePath, importPath) {
|
|
146
|
-
const content = fs3.readFileSync(filePath, "utf-8");
|
|
147
|
-
const pattern = new RegExp(
|
|
148
|
-
`@import\\s+['"]${escapeRegex(importPath)}['"]\\s*;?\\n?`
|
|
149
|
-
);
|
|
150
|
-
if (!pattern.test(content)) return false;
|
|
151
|
-
fs3.writeFileSync(filePath, content.replace(pattern, ""), "utf-8");
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
function escapeRegex(str) {
|
|
155
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// src/utils/css-imports.ts
|
|
159
|
-
import fs4 from "fs/promises";
|
|
160
|
-
async function insertImportLine(filePath, importStatement) {
|
|
161
|
-
const content = await fs4.readFile(filePath, "utf-8");
|
|
162
|
-
const importPath = importStatement.match(/["']([^"']+)["']/)?.[1];
|
|
163
|
-
if (importPath) {
|
|
164
|
-
const escaped = importPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
165
|
-
if (new RegExp(`@import\\s+["']${escaped}["']`).test(content)) return;
|
|
166
|
-
}
|
|
167
|
-
const lines = content.split("\n");
|
|
168
|
-
let lastImportIndex = -1;
|
|
169
|
-
for (let i = 0; i < lines.length; i++) {
|
|
170
|
-
if (lines[i].trim().startsWith("@import")) {
|
|
171
|
-
lastImportIndex = i;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (lastImportIndex >= 0) {
|
|
175
|
-
lines.splice(lastImportIndex + 1, 0, importStatement);
|
|
176
|
-
} else {
|
|
177
|
-
lines.unshift(importStatement);
|
|
178
|
-
}
|
|
179
|
-
await fs4.writeFile(filePath, lines.join("\n"), "utf-8");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// src/utils/write-files.ts
|
|
183
|
-
import fs5 from "fs";
|
|
184
|
-
import path4 from "path";
|
|
185
|
-
import { confirm } from "@inquirer/prompts";
|
|
186
|
-
|
|
187
|
-
// src/utils/resolve-paths.ts
|
|
188
|
-
import path3 from "path";
|
|
189
|
-
import { loadConfig as loadConfig2, createMatchPath } from "tsconfig-paths";
|
|
190
|
-
var TYPE_TO_ALIAS = {
|
|
191
|
-
"registry:ui": "ui",
|
|
192
|
-
"registry:lib": "lib",
|
|
193
|
-
"registry:hook": "hooks",
|
|
194
|
-
"registry:component": "components"
|
|
195
|
-
};
|
|
196
|
-
var matcherCache = /* @__PURE__ */ new Map();
|
|
197
|
-
function getTsConfigMatcher(projectRoot) {
|
|
198
|
-
let matcher = matcherCache.get(projectRoot);
|
|
199
|
-
if (matcher !== void 0) return matcher;
|
|
200
|
-
const tsConfig = loadConfig2(projectRoot);
|
|
201
|
-
matcher = tsConfig.resultType === "success" && Object.keys(tsConfig.paths).length > 0 ? {
|
|
202
|
-
paths: tsConfig.paths,
|
|
203
|
-
match: createMatchPath(tsConfig.absoluteBaseUrl, tsConfig.paths)
|
|
204
|
-
} : null;
|
|
205
|
-
matcherCache.set(projectRoot, matcher);
|
|
206
|
-
return matcher;
|
|
207
|
-
}
|
|
208
|
-
function resolveAlias(alias, projectRoot) {
|
|
209
|
-
const matcher = getTsConfigMatcher(projectRoot);
|
|
210
|
-
if (matcher) {
|
|
211
|
-
const hasMatchingPrefix = Object.keys(matcher.paths).some((key) => {
|
|
212
|
-
const prefix = key.replace(/\/\*$/, "");
|
|
213
|
-
return alias === prefix || alias.startsWith(`${prefix}/`);
|
|
214
|
-
});
|
|
215
|
-
if (hasMatchingPrefix) {
|
|
216
|
-
const resolved = matcher.match(alias, void 0, () => true, [
|
|
217
|
-
".ts",
|
|
218
|
-
".tsx"
|
|
219
|
-
]);
|
|
220
|
-
if (resolved) {
|
|
221
|
-
return path3.relative(projectRoot, resolved);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
throw new Error(
|
|
226
|
-
`Could not resolve alias "${alias}" from tsconfig.json. Ensure compilerOptions.paths defines a mapping for it (e.g. "${alias}/*"), then re-run. See https://ui.stera.sh/docs/installation.`
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
function resolveOutputPath(config, projectRoot, file) {
|
|
230
|
-
const alias = TYPE_TO_ALIAS[file.type];
|
|
231
|
-
if (alias) {
|
|
232
|
-
const dir = resolveAlias(config.aliases[alias], projectRoot);
|
|
233
|
-
const filename = path3.basename(file.path);
|
|
234
|
-
return path3.join(projectRoot, dir, filename);
|
|
235
|
-
}
|
|
236
|
-
if (file.type === "registry:style") {
|
|
237
|
-
const cssDir = path3.dirname(config.css);
|
|
238
|
-
const filename = path3.basename(file.path);
|
|
239
|
-
return path3.join(projectRoot, cssDir, filename);
|
|
240
|
-
}
|
|
241
|
-
return path3.join(projectRoot, file.path);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// src/utils/write-files.ts
|
|
245
|
-
async function confirmOverwrite(relativePath) {
|
|
246
|
-
if (!process.stdin.isTTY) {
|
|
247
|
-
console.log(
|
|
248
|
-
` Skipping ${relativePath} (already exists, use --overwrite to replace)`
|
|
249
|
-
);
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
return confirm({
|
|
253
|
-
message: `${relativePath} already exists. Overwrite?`,
|
|
254
|
-
default: false
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
async function writeComponentFiles(items, config, projectRoot, options = {}) {
|
|
258
|
-
const written = [];
|
|
259
|
-
const skipped = [];
|
|
260
|
-
for (const item of items) {
|
|
261
|
-
for (const file of item.files ?? []) {
|
|
262
|
-
const outputPath = resolveOutputPath(config, projectRoot, file);
|
|
263
|
-
const relativePath = path4.relative(projectRoot, outputPath);
|
|
264
|
-
if (fs5.existsSync(outputPath)) {
|
|
265
|
-
const existing = fs5.readFileSync(outputPath, "utf-8");
|
|
266
|
-
if (existing === file.content) {
|
|
267
|
-
skipped.push({ path: relativePath, reason: "unchanged" });
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
if (!options.overwrite) {
|
|
271
|
-
const confirmed = await confirmOverwrite(relativePath);
|
|
272
|
-
if (!confirmed) {
|
|
273
|
-
skipped.push({ path: relativePath, reason: "declined" });
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
const dir = path4.dirname(outputPath);
|
|
279
|
-
fs5.mkdirSync(dir, { recursive: true });
|
|
280
|
-
fs5.writeFileSync(outputPath, file.content ?? "", "utf-8");
|
|
281
|
-
written.push(relativePath);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return { written, skipped };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// src/utils/write-styles.ts
|
|
288
|
-
import fs6 from "fs/promises";
|
|
289
|
-
import { existsSync } from "fs";
|
|
290
|
-
import path5 from "path";
|
|
291
|
-
var INDEX_TARGET = "ui/index.css";
|
|
292
|
-
var TYPOGRAPHY_TARGET = "ui/typography.css";
|
|
293
|
-
var PROTECTED_TARGETS = /* @__PURE__ */ new Set([TYPOGRAPHY_TARGET, "ui/colors.css"]);
|
|
294
|
-
var LEGACY_FILENAME = "stera-ui.css";
|
|
295
|
-
var LEGACY_IMPORT = "./stera-ui.css";
|
|
296
|
-
function partitionImports(content) {
|
|
297
|
-
const lines = content.split("\n");
|
|
298
|
-
const hoisted = [];
|
|
299
|
-
const kept = [];
|
|
300
|
-
for (const line of lines) {
|
|
301
|
-
const specifier = line.trim().match(/^@import\s+["'](.+?)["']/)?.[1];
|
|
302
|
-
if (specifier === void 0) {
|
|
303
|
-
kept.push(line);
|
|
304
|
-
} else if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
305
|
-
kept.push(line);
|
|
306
|
-
} else if (specifier !== "tailwindcss") {
|
|
307
|
-
hoisted.push(line.trim());
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
311
|
-
return { content: cleaned, hoisted };
|
|
312
|
-
}
|
|
313
|
-
async function migrateLegacyStyles(config, cwd) {
|
|
314
|
-
const globalsPath = path5.resolve(cwd, config.css);
|
|
315
|
-
const legacyPath = path5.join(path5.dirname(globalsPath), LEGACY_FILENAME);
|
|
316
|
-
if (!existsSync(legacyPath)) return null;
|
|
317
|
-
await fs6.rm(legacyPath);
|
|
318
|
-
if (existsSync(globalsPath)) {
|
|
319
|
-
removeCssImport(globalsPath, LEGACY_IMPORT);
|
|
320
|
-
await insertImportLine(globalsPath, `@import "./${INDEX_TARGET}";`);
|
|
321
|
-
}
|
|
322
|
-
return legacyPath;
|
|
323
|
-
}
|
|
324
|
-
async function writeStyles(config, cwd, options = {}) {
|
|
325
|
-
const item = await fetchRegistryItem("globals");
|
|
326
|
-
const cssDir = path5.dirname(path5.resolve(cwd, config.css));
|
|
327
|
-
const written = [];
|
|
328
|
-
const skipped = [];
|
|
329
|
-
let extraImports = [];
|
|
330
|
-
for (const file of item.files ?? []) {
|
|
331
|
-
const target = file.target ?? path5.basename(file.path);
|
|
332
|
-
const outputPath = path5.join(cssDir, target);
|
|
333
|
-
let content = file.content ?? "";
|
|
334
|
-
if (target === INDEX_TARGET) {
|
|
335
|
-
const partitioned = partitionImports(content);
|
|
336
|
-
content = partitioned.content;
|
|
337
|
-
extraImports = partitioned.hoisted;
|
|
338
|
-
}
|
|
339
|
-
if (PROTECTED_TARGETS.has(target) && existsSync(outputPath)) {
|
|
340
|
-
const existing = await fs6.readFile(outputPath, "utf-8");
|
|
341
|
-
if (existing === content) {
|
|
342
|
-
skipped.push({ path: target, reason: "unchanged" });
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
if (!options.overwrite && !await confirmOverwrite(target)) {
|
|
346
|
-
skipped.push({ path: target, reason: "declined" });
|
|
347
|
-
continue;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
await fs6.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
351
|
-
await fs6.writeFile(outputPath, content, "utf-8");
|
|
352
|
-
written.push(target);
|
|
353
|
-
}
|
|
354
|
-
return {
|
|
355
|
-
indexPath: path5.join(cssDir, INDEX_TARGET),
|
|
356
|
-
typographyPath: path5.join(cssDir, TYPOGRAPHY_TARGET),
|
|
357
|
-
extraImports,
|
|
358
|
-
dependencies: item.dependencies ?? [],
|
|
359
|
-
written,
|
|
360
|
-
skipped
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export {
|
|
365
|
-
CONFIG_FILE,
|
|
366
|
-
LEGACY_CONFIG_FILE,
|
|
367
|
-
findConfigPath,
|
|
368
|
-
loadConfig,
|
|
369
|
-
installDependencies,
|
|
370
|
-
patchCssVariables,
|
|
371
|
-
insertImportLine,
|
|
372
|
-
writeComponentFiles,
|
|
373
|
-
TYPOGRAPHY_TARGET,
|
|
374
|
-
migrateLegacyStyles,
|
|
375
|
-
writeStyles
|
|
376
|
-
};
|