@yahoo/uds 3.96.0 → 3.97.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/cli/commands/purge.cjs +26 -0
- package/dist/cli/commands/purge.d.cts +15 -0
- package/dist/cli/commands/purge.d.ts +15 -0
- package/dist/cli/commands/purge.js +25 -0
- package/dist/cli/commands/sync.cjs +96 -0
- package/dist/cli/commands/sync.d.cts +16 -0
- package/dist/cli/commands/sync.d.ts +16 -0
- package/dist/cli/commands/sync.js +93 -0
- package/dist/cli/commands/utils/purgeCSS.cjs +258 -0
- package/dist/cli/commands/utils/purgeCSS.d.cts +59 -0
- package/dist/cli/commands/utils/purgeCSS.d.ts +59 -0
- package/dist/cli/commands/utils/purgeCSS.js +244 -0
- package/dist/cli/commands/utils/sortKeys.cjs +23 -0
- package/dist/cli/commands/utils/sortKeys.d.cts +5 -0
- package/dist/cli/commands/utils/sortKeys.d.ts +5 -0
- package/dist/cli/commands/utils/sortKeys.js +21 -0
- package/dist/cli/commands/version.cjs +21 -0
- package/dist/cli/commands/version.d.cts +7 -0
- package/dist/cli/commands/version.d.ts +7 -0
- package/dist/cli/commands/version.js +18 -0
- package/dist/cli/dist/cli.cjs +78 -0
- package/dist/cli/dist/cli.js +78 -0
- package/dist/cli/dist/commands/codemod/codemod.cjs +81 -0
- package/dist/cli/dist/commands/codemod/codemod.js +79 -0
- package/dist/cli/dist/commands/editor-rules.cjs +107 -0
- package/dist/cli/dist/commands/editor-rules.js +106 -0
- package/dist/cli/dist/lib/args.cjs +32 -0
- package/dist/cli/dist/lib/args.js +31 -0
- package/dist/cli/dist/lib/colors.cjs +26 -0
- package/dist/cli/dist/lib/colors.js +18 -0
- package/dist/cli/dist/lib/print.cjs +13 -0
- package/dist/cli/dist/lib/print.js +12 -0
- package/dist/cli/dist/lib/spinner.cjs +59 -0
- package/dist/cli/dist/lib/spinner.js +57 -0
- package/dist/cli/dist/utils/analytics.cjs +33 -0
- package/dist/cli/dist/utils/analytics.js +32 -0
- package/dist/cli/dist/utils/getCommandHelp.cjs +58 -0
- package/dist/cli/dist/utils/getCommandHelp.js +56 -0
- package/dist/cli/dist/utils/getDirChoices.cjs +27 -0
- package/dist/cli/dist/utils/getDirChoices.js +25 -0
- package/dist/cli/dist/utils/rules/config.cjs +56 -0
- package/dist/cli/dist/utils/rules/config.js +53 -0
- package/dist/cli/runner.cjs +14 -0
- package/dist/cli/runner.d.cts +2 -0
- package/dist/cli/runner.d.ts +2 -0
- package/dist/cli/runner.js +14 -0
- package/dist/styles/styler.d.cts +32 -32
- package/dist/styles/styler.d.ts +32 -32
- package/dist/tailwind/tailwindPlugin.d.cts +1 -1
- package/dist/tailwind/tailwindPlugin.d.ts +1 -1
- package/dist/tailwind/utils/getShadowStyles.d.cts +4 -4
- package/dist/tailwind/utils/getShadowStyles.d.ts +4 -4
- package/dist/uds/scripts/utils/tsMorph.cjs +1 -1
- package/dist/uds/scripts/utils/tsMorph.d.cts +1 -1
- package/dist/uds/scripts/utils/tsMorph.d.ts +1 -1
- package/package.json +5 -8
- package/uds.js +11 -1
- package/dist/cli.mjs +0 -897
package/dist/cli.mjs
DELETED
|
@@ -1,897 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import packageJson from "@yahoo/uds/package.json" with { type: "json" };
|
|
3
|
-
import updateNotifier from "simple-update-notifier";
|
|
4
|
-
import prompts from "prompts";
|
|
5
|
-
import { execSync } from "node:child_process";
|
|
6
|
-
import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
-
import path, { dirname, join } from "node:path";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
import fg from "fast-glob";
|
|
10
|
-
import { Node, Project, SyntaxKind, ts } from "ts-morph";
|
|
11
|
-
import { DARK_COLOR_MODE_CLASSNAME, LARGE_SCALE_MODE_CLASSNAME, LIGHT_COLOR_MODE_CLASSNAME, MEDIUM_SCALE_MODE_CLASSNAME, SMALL_SCALE_MODE_CLASSNAME, XLARGE_SCALE_MODE_CLASSNAME, XSMALL_SCALE_MODE_CLASSNAME, XXLARGE_SCALE_MODE_CLASSNAME, XXXLARGE_SCALE_MODE_CLASSNAME } from "./css-tokens/dist/index.js";
|
|
12
|
-
import { variants } from "./styles/variants.js";
|
|
13
|
-
import { componentToTwClasses, componentToVariants, componentsDependencies, variantsList } from "./tailwind/purger/index.js";
|
|
14
|
-
import { findReferencesAsJsxElements, getUsedPropsInReference } from "./tailwind/tsMorph.js";
|
|
15
|
-
import { defaultTokensConfig } from "./defaultTokensConfig.js";
|
|
16
|
-
import { configToBreakpointsConfigContext } from "./runtime/breakpointsConfig.js";
|
|
17
|
-
import { configToToastConfigContext } from "./runtime/toastConfig.js";
|
|
18
|
-
|
|
19
|
-
//#region cli/utils/analytics.ts
|
|
20
|
-
async function trackEvent(eventName, eventParams) {
|
|
21
|
-
try {
|
|
22
|
-
let userEmail = "unknown";
|
|
23
|
-
if (process.env.CI) userEmail = "CI";
|
|
24
|
-
else try {
|
|
25
|
-
userEmail = execSync("git config user.email", {
|
|
26
|
-
encoding: "utf8",
|
|
27
|
-
stdio: "pipe"
|
|
28
|
-
}).trim();
|
|
29
|
-
} catch {}
|
|
30
|
-
const team = process.env.UDS_TEAM_SLUG;
|
|
31
|
-
const request = new Request("https://config.uds.build/api/cli-analytics", {
|
|
32
|
-
method: "POST",
|
|
33
|
-
body: JSON.stringify({
|
|
34
|
-
userEmail,
|
|
35
|
-
team,
|
|
36
|
-
eventName,
|
|
37
|
-
eventParams
|
|
38
|
-
}),
|
|
39
|
-
headers: { "Content-Type": "application/json" }
|
|
40
|
-
});
|
|
41
|
-
await fetch(request);
|
|
42
|
-
} catch (_error) {}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
//#endregion
|
|
46
|
-
//#region cli/lib/args.ts
|
|
47
|
-
/**
|
|
48
|
-
* Parse command line arguments.
|
|
49
|
-
* @param argv - Arguments to parse (typically process.argv.slice(2))
|
|
50
|
-
* @returns Parsed positional args and options
|
|
51
|
-
*/
|
|
52
|
-
function parseArgs(argv) {
|
|
53
|
-
const positional = [];
|
|
54
|
-
const options = {};
|
|
55
|
-
for (let i = 0; i < argv.length; i++) {
|
|
56
|
-
const arg = argv[i];
|
|
57
|
-
if (arg.startsWith("--")) {
|
|
58
|
-
const key = arg.slice(2);
|
|
59
|
-
const next = argv[i + 1];
|
|
60
|
-
options[key] = next && !next.startsWith("-") ? (i++, next) : "true";
|
|
61
|
-
} else if (arg.startsWith("-") && arg.length === 2) {
|
|
62
|
-
const key = arg.slice(1);
|
|
63
|
-
const next = argv[i + 1];
|
|
64
|
-
options[key] = next && !next.startsWith("-") ? (i++, next) : "true";
|
|
65
|
-
} else positional.push(arg);
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
positional,
|
|
69
|
-
options
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region cli/lib/colors.ts
|
|
75
|
-
/**
|
|
76
|
-
* ANSI escape code color utilities for terminal output.
|
|
77
|
-
* Zero dependencies - uses standard ANSI escape sequences.
|
|
78
|
-
*/
|
|
79
|
-
const red = (text) => `\x1b[31m${text}\x1b[0m`;
|
|
80
|
-
const green = (text) => `\x1b[32m${text}\x1b[0m`;
|
|
81
|
-
const yellow = (text) => `\x1b[33m${text}\x1b[0m`;
|
|
82
|
-
const blue = (text) => `\x1b[34m${text}\x1b[0m`;
|
|
83
|
-
const magenta = (text) => `\x1b[35m${text}\x1b[0m`;
|
|
84
|
-
const cyan = (text) => `\x1b[36m${text}\x1b[0m`;
|
|
85
|
-
const white = (text) => `\x1b[37m${text}\x1b[0m`;
|
|
86
|
-
const gray = (text) => `\x1b[2m${text}\x1b[0m`;
|
|
87
|
-
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region cli/lib/print.ts
|
|
90
|
-
/**
|
|
91
|
-
* Console output wrapper.
|
|
92
|
-
*/
|
|
93
|
-
function print(...args) {
|
|
94
|
-
console.log(...args);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
//#endregion
|
|
98
|
-
//#region cli/lib/spinner.ts
|
|
99
|
-
/**
|
|
100
|
-
* Simple terminal spinner for showing progress during long operations.
|
|
101
|
-
* Uses Braille spinner characters for a smooth animation.
|
|
102
|
-
*/
|
|
103
|
-
let spinnerInterval = null;
|
|
104
|
-
let currentMessage = "";
|
|
105
|
-
const frames = [
|
|
106
|
-
"⠋",
|
|
107
|
-
"⠙",
|
|
108
|
-
"⠹",
|
|
109
|
-
"⠸",
|
|
110
|
-
"⠼",
|
|
111
|
-
"⠴",
|
|
112
|
-
"⠦",
|
|
113
|
-
"⠧",
|
|
114
|
-
"⠇",
|
|
115
|
-
"⠏"
|
|
116
|
-
];
|
|
117
|
-
let frameIndex = 0;
|
|
118
|
-
/**
|
|
119
|
-
* Start a spinner with a message.
|
|
120
|
-
* Only one spinner can be active at a time.
|
|
121
|
-
*/
|
|
122
|
-
function spinStart(message) {
|
|
123
|
-
if (spinnerInterval) spinStop();
|
|
124
|
-
currentMessage = message;
|
|
125
|
-
frameIndex = 0;
|
|
126
|
-
process.stdout.write("\x1B[?25l");
|
|
127
|
-
spinnerInterval = setInterval(() => {
|
|
128
|
-
const frame = frames[frameIndex];
|
|
129
|
-
process.stdout.write(`\r${frame} ${currentMessage}`);
|
|
130
|
-
frameIndex = (frameIndex + 1) % frames.length;
|
|
131
|
-
}, 80);
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Stop the spinner and optionally show a final message.
|
|
135
|
-
* @param iconOrMessage - Optional icon to show OR the message if second param not provided
|
|
136
|
-
* @param message - Optional final message to display
|
|
137
|
-
*/
|
|
138
|
-
function spinStop(iconOrMessage, message) {
|
|
139
|
-
if (spinnerInterval) {
|
|
140
|
-
clearInterval(spinnerInterval);
|
|
141
|
-
spinnerInterval = null;
|
|
142
|
-
}
|
|
143
|
-
process.stdout.write("\r\x1B[K");
|
|
144
|
-
process.stdout.write("\x1B[?25h");
|
|
145
|
-
if (iconOrMessage || message) {
|
|
146
|
-
const finalMessage = message ? `${iconOrMessage} ${message}` : iconOrMessage;
|
|
147
|
-
console.log(finalMessage);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
//#endregion
|
|
152
|
-
//#region cli/utils/getCommandHelp.ts
|
|
153
|
-
const CODEMOD_SUBCOMMANDS = [
|
|
154
|
-
{
|
|
155
|
-
name: "sizingProps",
|
|
156
|
-
description: "Convert sizing props to classNames"
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: "spacingProps",
|
|
160
|
-
description: "Migrate spacing props from old to new values"
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: "tailwindClassesToProps",
|
|
164
|
-
description: "Convert Tailwind classes to UDS props"
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: "flattenButtonVariant",
|
|
168
|
-
description: "Flatten Button variant props"
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: "buttonType",
|
|
172
|
-
description: "Add type attribute to Button components"
|
|
173
|
-
}
|
|
174
|
-
];
|
|
175
|
-
const banner$1 = `
|
|
176
|
-
█ █ █▀▄ ▄▀▀ ▄▀▀ █ █
|
|
177
|
-
▀▄█ █▄▀ ▄██ ▀▄▄ █▄▄ █
|
|
178
|
-
Universal Design System
|
|
179
|
-
`.trim();
|
|
180
|
-
async function getCommandHelp(props) {
|
|
181
|
-
const { name, commandPath, notes } = props;
|
|
182
|
-
const category = commandPath?.[0];
|
|
183
|
-
print(`\n${green(banner$1)}\n`);
|
|
184
|
-
print(`${magenta("Usage:")} ${white(`${name} <command>`)}\n`);
|
|
185
|
-
if (category === "codemod") {
|
|
186
|
-
print(`${magenta("Codemods:")}`);
|
|
187
|
-
const widest = Math.max(...CODEMOD_SUBCOMMANDS.map((c) => c.name.length)) + 4;
|
|
188
|
-
for (const cmd of CODEMOD_SUBCOMMANDS) print(` ${cyan(`${name} codemod ${cmd.name}`.padEnd(widest + 12))} ${gray(cmd.description)}`);
|
|
189
|
-
}
|
|
190
|
-
if (notes) print(`\n${magenta("Notes:")} ${notes}`);
|
|
191
|
-
print("");
|
|
192
|
-
}
|
|
193
|
-
async function getSubCommandsChoices(_props) {
|
|
194
|
-
return CODEMOD_SUBCOMMANDS.map((cmd) => ({
|
|
195
|
-
title: `${cmd.name} (${cmd.description})`,
|
|
196
|
-
value: cmd.name,
|
|
197
|
-
selected: true
|
|
198
|
-
}));
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//#endregion
|
|
202
|
-
//#region cli/utils/getDirChoices.ts
|
|
203
|
-
const lessCommonDirs = [
|
|
204
|
-
"node_modules",
|
|
205
|
-
".git",
|
|
206
|
-
".github",
|
|
207
|
-
".husky",
|
|
208
|
-
".vscode",
|
|
209
|
-
"dist",
|
|
210
|
-
"build",
|
|
211
|
-
"public"
|
|
212
|
-
];
|
|
213
|
-
const getDirChoices = (rootDir = ".") => {
|
|
214
|
-
return fs.readdirSync(rootDir).filter((dir) => fs.statSync(dir).isDirectory() && dir !== "node_modules" && !dir.startsWith(".")).map((dir) => ({
|
|
215
|
-
title: dir,
|
|
216
|
-
value: dir,
|
|
217
|
-
selected: !lessCommonDirs.includes(dir)
|
|
218
|
-
}));
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
//#endregion
|
|
222
|
-
//#region cli/commands/codemod/codemod.ts
|
|
223
|
-
var codemod_default = {
|
|
224
|
-
name: "codemod",
|
|
225
|
-
description: `Apply a codemod`,
|
|
226
|
-
run: async (props) => {
|
|
227
|
-
const subCommands = await getSubCommandsChoices(props);
|
|
228
|
-
const subCommandIsValid = subCommands.some(({ value }) => props?.first === value);
|
|
229
|
-
const wantsHelp = props.options.help || props.options.h;
|
|
230
|
-
const isRootCommand = Boolean(!props?.first);
|
|
231
|
-
const dirChoices = getDirChoices();
|
|
232
|
-
if (wantsHelp) return getCommandHelp(props);
|
|
233
|
-
const runCodeMod = async (codemod, selectedDirs) => {
|
|
234
|
-
return (await import(`./${codemod}`)).default.run({
|
|
235
|
-
...props,
|
|
236
|
-
selectedDirs
|
|
237
|
-
});
|
|
238
|
-
};
|
|
239
|
-
if (isRootCommand) {
|
|
240
|
-
const { selectedDirs, selectedCodemods, didConfirm } = await prompts([
|
|
241
|
-
{
|
|
242
|
-
type: "multiselect",
|
|
243
|
-
name: "selectedDirs",
|
|
244
|
-
instructions: false,
|
|
245
|
-
message: "Where are your sourcefiles?",
|
|
246
|
-
hint: "(Space to select. Return to submit)",
|
|
247
|
-
choices: dirChoices
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
type: "multiselect",
|
|
251
|
-
name: "selectedCodemods",
|
|
252
|
-
instructions: false,
|
|
253
|
-
message: "Select the codemods you want to run",
|
|
254
|
-
hint: "(Space to select. Return to submit)",
|
|
255
|
-
choices: subCommands
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
type: "toggle",
|
|
259
|
-
name: "didConfirm",
|
|
260
|
-
message: "Are you ready?",
|
|
261
|
-
initial: true,
|
|
262
|
-
active: "yes",
|
|
263
|
-
inactive: "no"
|
|
264
|
-
}
|
|
265
|
-
]);
|
|
266
|
-
if (!selectedDirs?.length || !selectedCodemods?.length || !didConfirm) process.exit(1);
|
|
267
|
-
return Promise.all(selectedCodemods.map(async (codemod) => {
|
|
268
|
-
await runCodeMod(codemod, selectedDirs);
|
|
269
|
-
return trackEvent("codemod", { codemod });
|
|
270
|
-
}));
|
|
271
|
-
} else if (subCommandIsValid) {
|
|
272
|
-
const { selectedDirs } = await prompts({
|
|
273
|
-
type: "multiselect",
|
|
274
|
-
name: "selectedDirs",
|
|
275
|
-
instructions: false,
|
|
276
|
-
message: "Where are your sourcefiles?",
|
|
277
|
-
hint: "(Space to select. Return to submit)",
|
|
278
|
-
choices: dirChoices
|
|
279
|
-
});
|
|
280
|
-
if (!selectedDirs?.length) process.exit(1);
|
|
281
|
-
const codemod = props.first;
|
|
282
|
-
await runCodeMod(codemod, selectedDirs);
|
|
283
|
-
return trackEvent("codemod", { codemod });
|
|
284
|
-
} else await getCommandHelp({
|
|
285
|
-
...props,
|
|
286
|
-
notes: `That codemod does not exist. Try one of the codemods listed above!`
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
//#endregion
|
|
292
|
-
//#region cli/rules/config.ts
|
|
293
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
294
|
-
const EDITOR_CONFIGS = { cursor: {
|
|
295
|
-
name: "Cursor",
|
|
296
|
-
description: "AI-powered coding assistant rules for UDS development",
|
|
297
|
-
rules: [
|
|
298
|
-
{
|
|
299
|
-
name: "UDS Components",
|
|
300
|
-
description: "Component development guidelines and patterns",
|
|
301
|
-
files: [{
|
|
302
|
-
source: "rules/cursor/uds/components.mdc",
|
|
303
|
-
target: ".cursor/rules/uds/components.mdc",
|
|
304
|
-
type: "file"
|
|
305
|
-
}]
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
name: "UDS Tailwind",
|
|
309
|
-
description: "Tailwind CSS configuration and setup guidelines",
|
|
310
|
-
files: [{
|
|
311
|
-
source: "rules/cursor/uds/tailwind.mdc",
|
|
312
|
-
target: ".cursor/rules/uds/tailwind.mdc",
|
|
313
|
-
type: "file"
|
|
314
|
-
}]
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
name: "UDS Icons",
|
|
318
|
-
description: "Icon usage and documentation guidelines",
|
|
319
|
-
files: [{
|
|
320
|
-
source: "rules/cursor/uds/icons.mdc",
|
|
321
|
-
target: ".cursor/rules/uds/icons.mdc",
|
|
322
|
-
type: "file"
|
|
323
|
-
}]
|
|
324
|
-
}
|
|
325
|
-
]
|
|
326
|
-
} };
|
|
327
|
-
function getAvailableEditors() {
|
|
328
|
-
return Object.keys(EDITOR_CONFIGS);
|
|
329
|
-
}
|
|
330
|
-
function getEditorConfig(editor) {
|
|
331
|
-
return EDITOR_CONFIGS[editor];
|
|
332
|
-
}
|
|
333
|
-
function getRuleContent(rulePath) {
|
|
334
|
-
return readFileSync(join(__dirname, rulePath), "utf-8");
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
//#endregion
|
|
338
|
-
//#region cli/commands/editor-rules.ts
|
|
339
|
-
var editor_rules_default = {
|
|
340
|
-
name: "editor-rules",
|
|
341
|
-
description: "🎯 Generate editor rules for various code editors and AI tools",
|
|
342
|
-
alias: ["rules", "editor"],
|
|
343
|
-
run: async ({ options }) => {
|
|
344
|
-
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
345
|
-
print(blue("🎯 UDS Editor Rules Command"));
|
|
346
|
-
print("");
|
|
347
|
-
print(green("Description: Generate editor rules for various code editors and AI tools"));
|
|
348
|
-
print("");
|
|
349
|
-
print(yellow("Options:"));
|
|
350
|
-
print(" --force, -f Force overwrite existing rules directory");
|
|
351
|
-
print(" --output, -o Output directory (defaults to workspace root)");
|
|
352
|
-
print(" --editor, -e Specific editor/tool (defaults to all)");
|
|
353
|
-
print("");
|
|
354
|
-
print(blue("Available editors/tools:"));
|
|
355
|
-
const editors = getAvailableEditors();
|
|
356
|
-
for (const editor of editors) {
|
|
357
|
-
const config = getEditorConfig(editor);
|
|
358
|
-
if (config) print(` • ${editor}: ${config.description}`);
|
|
359
|
-
}
|
|
360
|
-
print("");
|
|
361
|
-
print(blue("Examples:"));
|
|
362
|
-
print(" uds editor-rules # Generate all rules in current directory");
|
|
363
|
-
print(" uds editor-rules --editor cursor # Generate only Cursor rules");
|
|
364
|
-
print(" uds editor-rules --output /path # Generate rules in specific directory");
|
|
365
|
-
print(" uds editor-rules --force # Force overwrite existing rules");
|
|
366
|
-
print("");
|
|
367
|
-
print(green("What it generates:"));
|
|
368
|
-
print(" • Cursor Rules (.cursor/uds/)");
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
try {
|
|
372
|
-
const outputDir = options.output || process.cwd();
|
|
373
|
-
const selectedEditor = options.editor?.toLowerCase();
|
|
374
|
-
const force = options.force === "true" || options.force === true;
|
|
375
|
-
print(blue(`📁 Generating editor rules in: ${outputDir}`));
|
|
376
|
-
if (selectedEditor) {
|
|
377
|
-
const editorConfig = getEditorConfig(selectedEditor);
|
|
378
|
-
if (!editorConfig) {
|
|
379
|
-
print(red(`❌ Unknown editor: ${selectedEditor}`));
|
|
380
|
-
print(yellow("Available editors:"));
|
|
381
|
-
const editors = getAvailableEditors();
|
|
382
|
-
for (const editor of editors) {
|
|
383
|
-
const config = getEditorConfig(editor);
|
|
384
|
-
if (config) print(` • ${editor}: ${config.description}`);
|
|
385
|
-
}
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
await generateEditorRules(outputDir, selectedEditor, editorConfig, force);
|
|
389
|
-
} else {
|
|
390
|
-
const editors = getAvailableEditors();
|
|
391
|
-
for (const editor of editors) {
|
|
392
|
-
const editorConfig = getEditorConfig(editor);
|
|
393
|
-
if (editorConfig) await generateEditorRules(outputDir, editor, editorConfig, force);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
print(green("🎉 Editor rules generated successfully!"));
|
|
397
|
-
print(blue("📝 Rules are now available for your development environment"));
|
|
398
|
-
await trackEvent("editor_rules_generated", {
|
|
399
|
-
output_dir: outputDir,
|
|
400
|
-
force: force || false,
|
|
401
|
-
editor: selectedEditor || "all"
|
|
402
|
-
});
|
|
403
|
-
} catch (error) {
|
|
404
|
-
print(red(`❌ Error generating editor rules: ${error}`));
|
|
405
|
-
process.exitCode = 1;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
async function generateEditorRules(outputDir, editorName, editorConfig, force = false) {
|
|
410
|
-
print(blue(`\n🔧 Generating ${editorConfig.name} rules...`));
|
|
411
|
-
for (const rule of editorConfig.rules) {
|
|
412
|
-
print(yellow(` 📝 ${rule.name}: ${rule.description}`));
|
|
413
|
-
for (const file of rule.files) {
|
|
414
|
-
const targetPath = join(outputDir, file.target);
|
|
415
|
-
const targetDir = join(targetPath, "..");
|
|
416
|
-
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
417
|
-
if (existsSync(targetPath)) if (force) print(yellow(` 🗑️ Overwriting: ${file.target}`));
|
|
418
|
-
else {
|
|
419
|
-
print(red(` ❌ File already exists: ${file.target}`));
|
|
420
|
-
print(yellow(" Use --force to overwrite existing files"));
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
try {
|
|
424
|
-
writeFileSync(targetPath, getRuleContent(file.source));
|
|
425
|
-
print(green(` ✅ Created: ${file.target}`));
|
|
426
|
-
} catch (error) {
|
|
427
|
-
print(red(` ❌ Error creating ${file.target}: ${error}`));
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
//#endregion
|
|
434
|
-
//#region cli/utils/purgeCSS.ts
|
|
435
|
-
const scaleModeToClass = {
|
|
436
|
-
large: LARGE_SCALE_MODE_CLASSNAME,
|
|
437
|
-
medium: MEDIUM_SCALE_MODE_CLASSNAME,
|
|
438
|
-
small: SMALL_SCALE_MODE_CLASSNAME,
|
|
439
|
-
xLarge: XLARGE_SCALE_MODE_CLASSNAME,
|
|
440
|
-
xSmall: XSMALL_SCALE_MODE_CLASSNAME,
|
|
441
|
-
xxLarge: XXLARGE_SCALE_MODE_CLASSNAME,
|
|
442
|
-
xxxLarge: XXXLARGE_SCALE_MODE_CLASSNAME
|
|
443
|
-
};
|
|
444
|
-
const colorModeToClass = {
|
|
445
|
-
dark: DARK_COLOR_MODE_CLASSNAME,
|
|
446
|
-
light: LIGHT_COLOR_MODE_CLASSNAME
|
|
447
|
-
};
|
|
448
|
-
const getFiles = async (entry) => {
|
|
449
|
-
try {
|
|
450
|
-
const workspaceDir = process.env.PWD || process.cwd();
|
|
451
|
-
if (!workspaceDir) throw new Error("Workspace directory not found.");
|
|
452
|
-
return await fg(["**/*.jsx", "**/*.tsx"], {
|
|
453
|
-
cwd: path.join(workspaceDir, entry),
|
|
454
|
-
absolute: true
|
|
455
|
-
});
|
|
456
|
-
} catch {
|
|
457
|
-
throw new Error(`Couldn't find the entry directory: ${entry}. Please make sure it exists.`);
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
/**
|
|
461
|
-
* Find all JSX references for a named import.
|
|
462
|
-
*
|
|
463
|
-
* @example
|
|
464
|
-
* const references = findNamedImportReferences(project, '@yahoo/uds', 'HStack')
|
|
465
|
-
*/
|
|
466
|
-
function findNamedImportReferences(project, moduleSpecifierValue, namedImportName) {
|
|
467
|
-
const references = [];
|
|
468
|
-
for (const sourceFile of project.getSourceFiles()) for (const importDeclaration of sourceFile.getImportDeclarations()) if (importDeclaration.getModuleSpecifierValue() === moduleSpecifierValue) {
|
|
469
|
-
for (const namedImport of importDeclaration.getNamedImports()) if (namedImport.getName() === namedImportName) {
|
|
470
|
-
const identifier = namedImport.getFirstDescendantByKindOrThrow(ts.SyntaxKind.Identifier);
|
|
471
|
-
references.push(...findReferencesAsJsxElements(identifier));
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
return references;
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Given a file it returns the list of imports from @yahoo/uds
|
|
478
|
-
*/
|
|
479
|
-
const parseFiles = (project, files) => {
|
|
480
|
-
const importsSet = /* @__PURE__ */ new Set();
|
|
481
|
-
files.map((file) => {
|
|
482
|
-
return project.getSourceFile(file)?.getImportDeclarations().filter((declaration) => {
|
|
483
|
-
return declaration.getModuleSpecifier().getText().includes("@yahoo/uds") || declaration.getModuleSpecifier().getText().includes("@yahoo/uds/experimental");
|
|
484
|
-
}).map((declaration) => {
|
|
485
|
-
return declaration.getNamedImports().map((namedImport) => namedImport.getName());
|
|
486
|
-
}).flat() ?? [];
|
|
487
|
-
}).flat().forEach((item) => {
|
|
488
|
-
if (!importsSet.has(item)) importsSet.add(item);
|
|
489
|
-
});
|
|
490
|
-
return Array.from(importsSet);
|
|
491
|
-
};
|
|
492
|
-
const getTailwindSafelist = (project, componentList) => {
|
|
493
|
-
const safeList = [];
|
|
494
|
-
const validVariants = new Set(variantsList);
|
|
495
|
-
const usedProps = /* @__PURE__ */ new Map();
|
|
496
|
-
componentList.forEach((component) => {
|
|
497
|
-
if (isUDSComponent(component)) {
|
|
498
|
-
componentToVariants[component].forEach(([propName, usedValues]) => {
|
|
499
|
-
if (validVariants.has(propName)) {
|
|
500
|
-
const options = usedProps.get(propName) ?? /* @__PURE__ */ new Set();
|
|
501
|
-
usedValues.forEach((val) => options.add(val));
|
|
502
|
-
usedProps.set(propName, options);
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
getUsedProps(project, component).forEach(([propName, usedValues]) => {
|
|
506
|
-
if (validVariants.has(propName)) {
|
|
507
|
-
if (usedValues.length === 0) usedValues = Object.keys(variants[propName]);
|
|
508
|
-
const options = usedProps.get(propName) ?? /* @__PURE__ */ new Set();
|
|
509
|
-
usedValues.forEach((val) => options.add(val));
|
|
510
|
-
usedProps.set(propName, options);
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
safeList.push(...componentToTwClasses[component].replaceAll("\\", "").split(" "));
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
for (const [propName, usedValues] of usedProps) {
|
|
517
|
-
const variantGroup = variants[propName];
|
|
518
|
-
if (variantGroup) usedValues.forEach((option) => {
|
|
519
|
-
const variantClass = variantGroup[option];
|
|
520
|
-
if (variantClass) safeList.push(variantClass.replaceAll("\\", ""));
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
for (const [variant, variantOptions] of scanGetStylesReferences(project)) {
|
|
524
|
-
const variantGroup = variants[variant];
|
|
525
|
-
if (variantGroup) variantOptions.forEach((option) => {
|
|
526
|
-
const variantClass = variantGroup[option];
|
|
527
|
-
if (variantClass) safeList.push(variantClass.replaceAll("\\", ""));
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
return Array.from(new Set(safeList)).filter(Boolean);
|
|
531
|
-
};
|
|
532
|
-
/**
|
|
533
|
-
* Get the used props for a given component.
|
|
534
|
-
*
|
|
535
|
-
* @example
|
|
536
|
-
* const usedProps = getUsedProps(project, 'HStack');
|
|
537
|
-
*/
|
|
538
|
-
const getUsedProps = (project, component) => {
|
|
539
|
-
const references = [];
|
|
540
|
-
references.push(...findNamedImportReferences(project, packageJson.name, component));
|
|
541
|
-
references.push(...findNamedImportReferences(project, `${packageJson.name}/experimental`, component));
|
|
542
|
-
return references.map((reference) => getUsedPropsInReference(reference)).flat();
|
|
543
|
-
};
|
|
544
|
-
const isUDSComponent = (component) => {
|
|
545
|
-
return !!componentToVariants[component];
|
|
546
|
-
};
|
|
547
|
-
const saveToFile = (safeList, outputPath) => {
|
|
548
|
-
const fileContent = `
|
|
549
|
-
//! This file is generated by purgeCSS.ts from @yahoo/uds
|
|
550
|
-
//! Do not edit directly
|
|
551
|
-
//! If there is issue with this file please report to #ask-uds
|
|
552
|
-
export const safelist = ${JSON.stringify(safeList)};
|
|
553
|
-
`;
|
|
554
|
-
mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
555
|
-
writeFileSync(outputPath, fileContent);
|
|
556
|
-
};
|
|
557
|
-
const getComponentsToConvertToTW = (udsImport) => {
|
|
558
|
-
const components = udsImport.filter((importedItem) => !!componentToVariants[importedItem]);
|
|
559
|
-
const set = /* @__PURE__ */ new Set();
|
|
560
|
-
components.forEach((component) => {
|
|
561
|
-
if (!set.has(component)) set.add(component);
|
|
562
|
-
if (componentsDependencies[component]) componentsDependencies[component].forEach((dependent) => {
|
|
563
|
-
if (!set.has(dependent)) set.add(dependent);
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
|
-
return Array.from(set);
|
|
567
|
-
};
|
|
568
|
-
/**
|
|
569
|
-
* Get the classes that corresponds to the used modes
|
|
570
|
-
*/
|
|
571
|
-
const getClassesForEnabledThemesAndScales = () => {
|
|
572
|
-
const classes = [];
|
|
573
|
-
if (process.env.ENABLED_SCALE_AND_COLOR_MODES) process.env.ENABLED_SCALE_AND_COLOR_MODES.split(",").map((mode) => {
|
|
574
|
-
mode = mode.trim();
|
|
575
|
-
if (colorModeToClass[mode]) classes.push(colorModeToClass[mode]);
|
|
576
|
-
else if (scaleModeToClass[mode]) classes.push(scaleModeToClass[mode]);
|
|
577
|
-
});
|
|
578
|
-
else {
|
|
579
|
-
classes.push(colorModeToClass.dark);
|
|
580
|
-
classes.push(colorModeToClass.light);
|
|
581
|
-
classes.push(scaleModeToClass.large);
|
|
582
|
-
}
|
|
583
|
-
return classes;
|
|
584
|
-
};
|
|
585
|
-
/**
|
|
586
|
-
* Scan the source code for all `getStyles` references
|
|
587
|
-
*
|
|
588
|
-
* Note: This currently only works if we are passing a literal object to getStyles.
|
|
589
|
-
*
|
|
590
|
-
* Explanation: They we are able to enfer what css to include is by looking at the properties of the object passed.
|
|
591
|
-
* If something other than an object is passed, we can fallback on the Type, but that would require handling
|
|
592
|
-
* a lot of edge cases (function return type, spread operator, ternary, ...) and each one of these cases will
|
|
593
|
-
* most likely have a sub case. Falling back to the Type will complicate the code a lot is error prone as there
|
|
594
|
-
* is only so much info we can get out of the types as the Users are free to use `any` on their project which will
|
|
595
|
-
* provide no value for us. Hence why having a literal object passed is the best and probably the only sane way
|
|
596
|
-
* to go about this.
|
|
597
|
-
*/
|
|
598
|
-
const scanGetStylesReferences = (project) => {
|
|
599
|
-
const references = [];
|
|
600
|
-
for (const sourceFile of project.getSourceFiles()) for (const importDeclaration of sourceFile.getImportDeclarations()) if (importDeclaration.getModuleSpecifierValue() === packageJson.name) {
|
|
601
|
-
for (const namedImport of importDeclaration.getNamedImports()) if (namedImport.getName() === "getStyles") {
|
|
602
|
-
const identifier = namedImport.getFirstDescendantByKindOrThrow(ts.SyntaxKind.Identifier);
|
|
603
|
-
for (const reference of identifier.findReferencesAsNodes()) {
|
|
604
|
-
const node = reference.getFirstAncestor((node) => {
|
|
605
|
-
return Node.isCallExpression(node);
|
|
606
|
-
});
|
|
607
|
-
if (node) references.push(node);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
const usedProps = /* @__PURE__ */ new Map();
|
|
612
|
-
for (const reference of references) {
|
|
613
|
-
const objectLiteralExpression = reference.getFirstChildByKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
614
|
-
const propertyAssignments = objectLiteralExpression.getDescendantsOfKind(SyntaxKind.PropertyAssignment);
|
|
615
|
-
const shorthandPropertyAssignments = objectLiteralExpression.getDescendantsOfKind(SyntaxKind.ShorthandPropertyAssignment);
|
|
616
|
-
propertyAssignments.forEach((propertyAssigment) => {
|
|
617
|
-
const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();
|
|
618
|
-
const stringLiteral = propertyAssigment.getFirstChildByKind(SyntaxKind.StringLiteral)?.getLiteralText();
|
|
619
|
-
if (identifier && !stringLiteral) {
|
|
620
|
-
const fallback = !!variants[identifier] ? Object.keys(variants[identifier]) : [];
|
|
621
|
-
usedProps.set(identifier, new Set(fallback));
|
|
622
|
-
}
|
|
623
|
-
if (identifier && stringLiteral) {
|
|
624
|
-
let options;
|
|
625
|
-
if (usedProps.has(identifier)) options = usedProps.get(identifier);
|
|
626
|
-
else options = /* @__PURE__ */ new Set();
|
|
627
|
-
options.add(stringLiteral);
|
|
628
|
-
usedProps.set(identifier, options);
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
shorthandPropertyAssignments.forEach((propertyAssigment) => {
|
|
632
|
-
const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();
|
|
633
|
-
if (identifier) usedProps.set(identifier, /* @__PURE__ */ new Set());
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
return usedProps;
|
|
637
|
-
};
|
|
638
|
-
async function purge({ config: configPath = process.env.UDS_OUT_FILE ?? "./uds.config.ts", output = "dist/safelist.ts", entry = "/src/" }) {
|
|
639
|
-
const workspaceDir = process.env.PWD || process.cwd();
|
|
640
|
-
if (!workspaceDir) throw new Error("Workspace directory not found.");
|
|
641
|
-
const project = new Project({ tsConfigFilePath: path.join(workspaceDir, "/tsconfig.json") });
|
|
642
|
-
const outputFilePath = path.join(workspaceDir, output);
|
|
643
|
-
const configAbsolutePath = path.join(workspaceDir, configPath);
|
|
644
|
-
try {
|
|
645
|
-
await import(configAbsolutePath);
|
|
646
|
-
} catch {
|
|
647
|
-
throw new Error("Couldn't load the UDS config. Make sure you have uds.config.ts in the root of your project.");
|
|
648
|
-
}
|
|
649
|
-
spinStart("Getting used UDS components...");
|
|
650
|
-
print("Loading the project...");
|
|
651
|
-
const files = await getFiles(entry);
|
|
652
|
-
print("Going through the imports...");
|
|
653
|
-
const udsImports = parseFiles(project, files);
|
|
654
|
-
print("Finding all the components imported from UDS...");
|
|
655
|
-
const udsComponents = getComponentsToConvertToTW(udsImports);
|
|
656
|
-
print("🧑🍳 Cooking...");
|
|
657
|
-
const safeList = getTailwindSafelist(project, udsComponents);
|
|
658
|
-
const themesAndScalesClasses = getClassesForEnabledThemesAndScales();
|
|
659
|
-
saveToFile(safeList.concat(themesAndScalesClasses), outputFilePath);
|
|
660
|
-
spinStop("Generated your safelist!");
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
//#endregion
|
|
664
|
-
//#region cli/commands/purge.ts
|
|
665
|
-
var purge_default = {
|
|
666
|
-
name: "purge",
|
|
667
|
-
description: `Purge unused CSS`,
|
|
668
|
-
run: async (props) => {
|
|
669
|
-
spinStart("Purging css started...");
|
|
670
|
-
try {
|
|
671
|
-
await purge(props.options);
|
|
672
|
-
spinStop("✅", "Purging css done!");
|
|
673
|
-
return await trackEvent("purge");
|
|
674
|
-
} catch (error) {
|
|
675
|
-
if (error instanceof Error) spinStop("❌", error.message);
|
|
676
|
-
else spinStop("❌", "Purging css failed! Please reach out to #uds-ask channel for support.");
|
|
677
|
-
process.exitCode = 1;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
//#endregion
|
|
683
|
-
//#region cli/utils/sortKeys.ts
|
|
684
|
-
function sortKeys(unsortedObj) {
|
|
685
|
-
const sortedObj = {};
|
|
686
|
-
if (!unsortedObj || typeof unsortedObj !== "object") return unsortedObj;
|
|
687
|
-
const keys = Object.keys(unsortedObj).sort();
|
|
688
|
-
for (var index in keys) {
|
|
689
|
-
const key = keys[index];
|
|
690
|
-
const value = unsortedObj[key];
|
|
691
|
-
if (typeof value === "object") if (Array.isArray(value)) sortedObj[key] = value.map((item) => {
|
|
692
|
-
if (typeof item === "object") return sortKeys(item);
|
|
693
|
-
return item;
|
|
694
|
-
});
|
|
695
|
-
else sortedObj[key] = sortKeys(value);
|
|
696
|
-
else sortedObj[key] = value;
|
|
697
|
-
}
|
|
698
|
-
return sortedObj;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
//#endregion
|
|
702
|
-
//#region cli/commands/sync.ts
|
|
703
|
-
const PRODUCTION_ENDPOINT = "https://config.uds.build/api/config";
|
|
704
|
-
const STAGING_ENDPOINT = "https://staging.config.uds.build/api/config";
|
|
705
|
-
function getConfigEndpoint() {
|
|
706
|
-
if (process.env.DATABASE === "staging") return STAGING_ENDPOINT;
|
|
707
|
-
if (process.env.DATABASE === "local") return `http://localhost:${process.env.PORT || 4001}/api/config`;
|
|
708
|
-
return PRODUCTION_ENDPOINT;
|
|
709
|
-
}
|
|
710
|
-
var sync_default = {
|
|
711
|
-
name: "sync",
|
|
712
|
-
description: "🔄 Update to latest design config 🎨",
|
|
713
|
-
alias: ["update"],
|
|
714
|
-
run: async ({ name, commandPath, options }) => {
|
|
715
|
-
const id = options.id || process.env.UDS_ID;
|
|
716
|
-
const outFile = options.outFile || process.env.UDS_OUT_FILE;
|
|
717
|
-
if (!id || typeof id === "boolean") {
|
|
718
|
-
console.error("\nMissing config ID. Please pass an --id flag or set the UDS_ID env variable.\n");
|
|
719
|
-
print(`${magenta("Usage:")} ${name} ${commandPath} --id <config-id>\n`);
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
const outputPath = outFile ?? "./uds.config.ts";
|
|
723
|
-
const outFileExtension = outputPath.split(".").pop()?.toLowerCase();
|
|
724
|
-
if (outFileExtension !== "ts" && outFileExtension !== "js") {
|
|
725
|
-
print(red("❌ Output file must be a TypeScript or JavaScript file."));
|
|
726
|
-
process.exitCode = 1;
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
try {
|
|
730
|
-
const fetchUrl = `${getConfigEndpoint()}?id=${id}`;
|
|
731
|
-
const fullPath = path.resolve(process.cwd(), outputPath);
|
|
732
|
-
print(yellow("Fetching from configurator..."));
|
|
733
|
-
let config;
|
|
734
|
-
if (process.env.DATABASE === "test") config = defaultTokensConfig;
|
|
735
|
-
else {
|
|
736
|
-
const resp = await fetch(fetchUrl);
|
|
737
|
-
if (!resp.ok) {
|
|
738
|
-
if (resp.status === 401) throw new Error(`${resp.status} error: ${resp.statusText}\nYou're not authorized to fetch from ${fetchUrl}\nMake sure you have a valid VERCEL_PROTECTION_BYPASS token in your root .env.local`);
|
|
739
|
-
throw new Error(`Error fetching config id '${id}'. Does it exist in the Configurator?`);
|
|
740
|
-
}
|
|
741
|
-
config = (await resp.json()).config;
|
|
742
|
-
}
|
|
743
|
-
if (!config) throw new Error("Config JSON could not be parsed.");
|
|
744
|
-
const sortedConfig = sortKeys(config);
|
|
745
|
-
const importsTS = [`import type { UniversalTokensConfig } from '@yahoo/uds';`];
|
|
746
|
-
const exportsTS = [`export const config: UniversalTokensConfig = ${JSON.stringify(sortedConfig, null, 2)};`];
|
|
747
|
-
const exportsJS = [`export const config = ${JSON.stringify(sortedConfig, null, 2)};`];
|
|
748
|
-
const runtimeConfigs = {
|
|
749
|
-
breakpoints: [configToBreakpointsConfigContext(sortedConfig), "UDSBreakpointsConfigContextType"],
|
|
750
|
-
toast: [configToToastConfigContext(sortedConfig), "UDSToastConfigContextType"]
|
|
751
|
-
};
|
|
752
|
-
const runtimeTypeImports = [];
|
|
753
|
-
for (const [name, [json, type]] of Object.entries(runtimeConfigs)) {
|
|
754
|
-
const content = sortKeys(json);
|
|
755
|
-
runtimeTypeImports.push(type);
|
|
756
|
-
exportsTS.push(`export const ${name}RuntimeConfig: ${type} = ${JSON.stringify(content, null, 2)};`);
|
|
757
|
-
exportsJS.push(`export const ${name}RuntimeConfig = ${JSON.stringify(content, null, 2)};`);
|
|
758
|
-
}
|
|
759
|
-
runtimeTypeImports.push("UDSConfigContextType");
|
|
760
|
-
importsTS.push(`import type { ${runtimeTypeImports.sort().join(", ")} } from '@yahoo/uds/runtime';`);
|
|
761
|
-
exportsTS.push(`export const runtimeConfig: UDSConfigContextType = {
|
|
762
|
-
breakpoints: breakpointsRuntimeConfig,
|
|
763
|
-
toast: toastRuntimeConfig,
|
|
764
|
-
};`);
|
|
765
|
-
exportsJS.push(`export const runtimeConfig = {
|
|
766
|
-
breakpoints: breakpointsRuntimeConfig,
|
|
767
|
-
toast: toastRuntimeConfig,
|
|
768
|
-
};`);
|
|
769
|
-
const configContentTs = `${importsTS.join("\n")}\n\n${exportsTS.join("\n\n")}\n`;
|
|
770
|
-
const configContentJs = `${exportsJS.join("\n\n")}\n`;
|
|
771
|
-
writeFileSync(fullPath, outFileExtension === "js" ? configContentJs : configContentTs);
|
|
772
|
-
print(green(`✅ Synced UDS config ${id} to ${fullPath}`));
|
|
773
|
-
await trackEvent("sync", { id });
|
|
774
|
-
} catch (error) {
|
|
775
|
-
print(red(`❌ ${error.message}`));
|
|
776
|
-
print(yellow("Please reach out to #uds-ask channel for support."));
|
|
777
|
-
process.exitCode = 1;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
};
|
|
781
|
-
|
|
782
|
-
//#endregion
|
|
783
|
-
//#region cli/commands/version.ts
|
|
784
|
-
const version = packageJson.version;
|
|
785
|
-
var version_default = {
|
|
786
|
-
name: "version",
|
|
787
|
-
description: version,
|
|
788
|
-
run: async () => {
|
|
789
|
-
print(version);
|
|
790
|
-
await trackEvent("version", { version });
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
//#endregion
|
|
795
|
-
//#region cli/cli.ts
|
|
796
|
-
/**
|
|
797
|
-
* UDS CLI - Universal Design System Command Line Interface
|
|
798
|
-
*
|
|
799
|
-
* This is the main entry point for the CLI. It uses manual argument parsing
|
|
800
|
-
* (no external framework) following the packages/mobile pattern.
|
|
801
|
-
*/
|
|
802
|
-
const { positional, options } = parseArgs(process.argv.slice(2));
|
|
803
|
-
const command = positional[0];
|
|
804
|
-
const banner = `
|
|
805
|
-
█ █ █▀▄ ▄▀▀ ▄▀▀ █ █
|
|
806
|
-
▀▄█ █▄▀ ▄██ ▀▄▄ █▄▄ █
|
|
807
|
-
Universal Design System
|
|
808
|
-
`.trim();
|
|
809
|
-
const COMMANDS = [
|
|
810
|
-
{
|
|
811
|
-
name: "sync",
|
|
812
|
-
description: "🔄 Update to latest design config 🎨",
|
|
813
|
-
aliases: ["update"]
|
|
814
|
-
},
|
|
815
|
-
{
|
|
816
|
-
name: "purge",
|
|
817
|
-
description: "Purge unused CSS"
|
|
818
|
-
},
|
|
819
|
-
{
|
|
820
|
-
name: "editor-rules",
|
|
821
|
-
description: "🎯 Generate editor rules for various code editors and AI tools",
|
|
822
|
-
aliases: ["rules", "editor"]
|
|
823
|
-
},
|
|
824
|
-
{
|
|
825
|
-
name: "version",
|
|
826
|
-
description: `Display CLI version (${packageJson.version})`
|
|
827
|
-
},
|
|
828
|
-
{
|
|
829
|
-
name: "codemod",
|
|
830
|
-
description: "Apply a codemod"
|
|
831
|
-
}
|
|
832
|
-
];
|
|
833
|
-
function showHelp(notes) {
|
|
834
|
-
const widest = Math.max(...COMMANDS.map((c) => c.name.length)) + 4;
|
|
835
|
-
const subcommandWidest = Math.max(...CODEMOD_SUBCOMMANDS.map((c) => c.name.length)) + 4;
|
|
836
|
-
print(`\n${green(banner)}\n`);
|
|
837
|
-
print(`${magenta("Usage:")} ${white("uds <command> [options]")}\n`);
|
|
838
|
-
print(`${magenta("Commands:")}`);
|
|
839
|
-
for (const cmd of COMMANDS) {
|
|
840
|
-
print(` ${cyan(cmd.name.padEnd(widest))} ${gray(cmd.description)}`);
|
|
841
|
-
if (cmd.name === "codemod") for (const sub of CODEMOD_SUBCOMMANDS) print(` ${cyan(sub.name.padEnd(subcommandWidest))} ${gray(sub.description)}`);
|
|
842
|
-
}
|
|
843
|
-
print("");
|
|
844
|
-
if (notes) print(`${magenta("Notes:")} ${notes}\n`);
|
|
845
|
-
}
|
|
846
|
-
async function main() {
|
|
847
|
-
if (process.env.CI !== "1") await updateNotifier({
|
|
848
|
-
pkg: packageJson,
|
|
849
|
-
shouldNotifyInNpmScript: true
|
|
850
|
-
});
|
|
851
|
-
const props = {
|
|
852
|
-
name: "uds",
|
|
853
|
-
commandPath: positional.slice(0, 1),
|
|
854
|
-
first: positional[1],
|
|
855
|
-
second: positional[2],
|
|
856
|
-
third: positional[3],
|
|
857
|
-
options
|
|
858
|
-
};
|
|
859
|
-
switch (command) {
|
|
860
|
-
case "sync":
|
|
861
|
-
case "update":
|
|
862
|
-
await sync_default.run(props);
|
|
863
|
-
break;
|
|
864
|
-
case "purge":
|
|
865
|
-
await purge_default.run(props);
|
|
866
|
-
break;
|
|
867
|
-
case "editor-rules":
|
|
868
|
-
case "rules":
|
|
869
|
-
case "editor":
|
|
870
|
-
await editor_rules_default.run(props);
|
|
871
|
-
break;
|
|
872
|
-
case "version":
|
|
873
|
-
await version_default.run();
|
|
874
|
-
break;
|
|
875
|
-
case "codemod":
|
|
876
|
-
await codemod_default.run({
|
|
877
|
-
...props,
|
|
878
|
-
first: positional[1]
|
|
879
|
-
});
|
|
880
|
-
break;
|
|
881
|
-
case "help":
|
|
882
|
-
case "--help":
|
|
883
|
-
case "-h":
|
|
884
|
-
case void 0:
|
|
885
|
-
showHelp();
|
|
886
|
-
break;
|
|
887
|
-
default:
|
|
888
|
-
print(red(`Unknown command: ${command}`));
|
|
889
|
-
await trackEvent("unknown_cmd", { cmd: command });
|
|
890
|
-
showHelp();
|
|
891
|
-
process.exitCode = 1;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
await main();
|
|
895
|
-
|
|
896
|
-
//#endregion
|
|
897
|
-
export { };
|