@ryndesign/cli 0.1.1
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/LICENSE +21 -0
- package/dist/add-ZYIVP5Z5.js +111 -0
- package/dist/add-ZYIVP5Z5.js.map +1 -0
- package/dist/bin.cjs +1332 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +28 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-TU5AB45W.js +76 -0
- package/dist/chunk-TU5AB45W.js.map +1 -0
- package/dist/eject-WIEISNL6.js +143 -0
- package/dist/eject-WIEISNL6.js.map +1 -0
- package/dist/figma-VTZWLYWQ.js +23 -0
- package/dist/figma-VTZWLYWQ.js.map +1 -0
- package/dist/figma-diff-SNSMOAZX.js +97 -0
- package/dist/figma-diff-SNSMOAZX.js.map +1 -0
- package/dist/figma-pull-RCRG6D5G.js +130 -0
- package/dist/figma-pull-RCRG6D5G.js.map +1 -0
- package/dist/figma-push-X4PSMN62.js +71 -0
- package/dist/figma-push-X4PSMN62.js.map +1 -0
- package/dist/generate-LES4SXIM.js +199 -0
- package/dist/generate-LES4SXIM.js.map +1 -0
- package/dist/index.cjs +115 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/init-AIT7XEQS.js +254 -0
- package/dist/init-AIT7XEQS.js.map +1 -0
- package/dist/preview-AXCPYQ53.js +40 -0
- package/dist/preview-AXCPYQ53.js.map +1 -0
- package/dist/validate-RGTQQSUE.js +87 -0
- package/dist/validate-RGTQQSUE.js.map +1 -0
- package/package.json +55 -0
package/dist/bin.cjs
ADDED
|
@@ -0,0 +1,1332 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
// src/commands/init.ts
|
|
34
|
+
var init_exports = {};
|
|
35
|
+
__export(init_exports, {
|
|
36
|
+
default: () => init_default
|
|
37
|
+
});
|
|
38
|
+
function generateConfig(platforms, darkMode) {
|
|
39
|
+
const imports = [];
|
|
40
|
+
const generators = [];
|
|
41
|
+
for (const platform of platforms) {
|
|
42
|
+
const pkgName = `@ryndesign/generator-${platform}`;
|
|
43
|
+
const varName = platform.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
44
|
+
imports.push(`import ${varName} from '${pkgName}';`);
|
|
45
|
+
if (["react", "vue", "svelte"].includes(platform)) {
|
|
46
|
+
generators.push(` ${varName}({
|
|
47
|
+
outDir: 'generated/${platform}',
|
|
48
|
+
cssStrategy: 'css-variables',
|
|
49
|
+
typescript: true,${darkMode ? "\n darkMode: 'media+class'," : ""}
|
|
50
|
+
})`);
|
|
51
|
+
} else {
|
|
52
|
+
generators.push(` ${varName}({
|
|
53
|
+
outDir: 'generated/${platform}',
|
|
54
|
+
})`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return `import { defineConfig } from '@ryndesign/cli';
|
|
58
|
+
${imports.join("\n")}
|
|
59
|
+
|
|
60
|
+
export default defineConfig({
|
|
61
|
+
tokens: ['tokens/**/*.tokens.json'],
|
|
62
|
+
components: ['components/**/*.component.json'],
|
|
63
|
+
outDir: 'generated',
|
|
64
|
+
${darkMode ? `
|
|
65
|
+
themes: {
|
|
66
|
+
default: 'light',
|
|
67
|
+
dark: { file: 'tokens/dark.tokens.json' },
|
|
68
|
+
},
|
|
69
|
+
` : ""}
|
|
70
|
+
generators: [
|
|
71
|
+
${generators.join(",\n")}
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
preview: { port: 4400, open: true },
|
|
75
|
+
});
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
function getDefaultTokens() {
|
|
79
|
+
return {
|
|
80
|
+
color: {
|
|
81
|
+
$type: "color",
|
|
82
|
+
primary: { $value: "#3B82F6" },
|
|
83
|
+
white: { $value: "#FFFFFF" },
|
|
84
|
+
black: { $value: "#000000" },
|
|
85
|
+
gray: {
|
|
86
|
+
50: { $value: "#F9FAFB" },
|
|
87
|
+
900: { $value: "#111827" }
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
spacing: {
|
|
91
|
+
$type: "dimension",
|
|
92
|
+
sm: { $value: "8px" },
|
|
93
|
+
md: { $value: "16px" },
|
|
94
|
+
lg: { $value: "24px" }
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function getSemanticTokens() {
|
|
99
|
+
return {
|
|
100
|
+
color: {
|
|
101
|
+
$type: "color",
|
|
102
|
+
background: {
|
|
103
|
+
primary: { $value: "{color.white}" },
|
|
104
|
+
secondary: { $value: "{color.gray.50}" }
|
|
105
|
+
},
|
|
106
|
+
text: {
|
|
107
|
+
primary: { $value: "{color.gray.900}" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function getDarkTokens() {
|
|
113
|
+
return {
|
|
114
|
+
$description: "Dark theme overrides",
|
|
115
|
+
$extensions: { "com.ryndesign.theme": { name: "dark", extends: "default" } },
|
|
116
|
+
color: {
|
|
117
|
+
$type: "color",
|
|
118
|
+
background: {
|
|
119
|
+
primary: { $value: "{color.gray.900}" },
|
|
120
|
+
secondary: { $value: "{color.gray.800}" }
|
|
121
|
+
},
|
|
122
|
+
text: {
|
|
123
|
+
primary: { $value: "{color.gray.50}" }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
var import_citty, p, import_picocolors, import_promises, import_node_path, import_meta, init_default;
|
|
129
|
+
var init_init = __esm({
|
|
130
|
+
"src/commands/init.ts"() {
|
|
131
|
+
"use strict";
|
|
132
|
+
import_citty = require("citty");
|
|
133
|
+
p = __toESM(require("@clack/prompts"), 1);
|
|
134
|
+
import_picocolors = __toESM(require("picocolors"), 1);
|
|
135
|
+
import_promises = __toESM(require("fs/promises"), 1);
|
|
136
|
+
import_node_path = __toESM(require("path"), 1);
|
|
137
|
+
import_meta = {};
|
|
138
|
+
init_default = (0, import_citty.defineCommand)({
|
|
139
|
+
meta: {
|
|
140
|
+
name: "init",
|
|
141
|
+
description: "Initialize a new RynDesign project"
|
|
142
|
+
},
|
|
143
|
+
args: {
|
|
144
|
+
template: {
|
|
145
|
+
type: "string",
|
|
146
|
+
description: "Template to use (minimal or full)",
|
|
147
|
+
default: "minimal"
|
|
148
|
+
},
|
|
149
|
+
platforms: {
|
|
150
|
+
type: "string",
|
|
151
|
+
description: "Comma-separated list of target platforms"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
async run({ args }) {
|
|
155
|
+
p.intro(import_picocolors.default.bgCyan(import_picocolors.default.black(" RynDesign Init ")));
|
|
156
|
+
const template = args.template || await p.select({
|
|
157
|
+
message: "Choose a template:",
|
|
158
|
+
options: [
|
|
159
|
+
{ value: "minimal", label: "Minimal", hint: "Basic color, spacing, typography tokens" },
|
|
160
|
+
{ value: "full", label: "Full", hint: "Complete token set with shadows, borders, gradients" }
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
if (p.isCancel(template)) {
|
|
164
|
+
p.cancel("Operation cancelled.");
|
|
165
|
+
process.exit(0);
|
|
166
|
+
}
|
|
167
|
+
const platformsInput = args.platforms || await p.multiselect({
|
|
168
|
+
message: "Select target platforms:",
|
|
169
|
+
initialValues: ["react", "swiftui"],
|
|
170
|
+
options: [
|
|
171
|
+
{ value: "react", label: "React", hint: "recommended" },
|
|
172
|
+
{ value: "swiftui", label: "SwiftUI", hint: "recommended" },
|
|
173
|
+
{ value: "vue", label: "Vue" },
|
|
174
|
+
{ value: "svelte", label: "Svelte" },
|
|
175
|
+
{ value: "rails", label: "Rails" },
|
|
176
|
+
{ value: "uikit", label: "UIKit" },
|
|
177
|
+
{ value: "compose", label: "Jetpack Compose" },
|
|
178
|
+
{ value: "android-view", label: "Android View" }
|
|
179
|
+
],
|
|
180
|
+
required: true
|
|
181
|
+
});
|
|
182
|
+
if (p.isCancel(platformsInput)) {
|
|
183
|
+
p.cancel("Operation cancelled.");
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
const platforms = Array.isArray(platformsInput) ? platformsInput : platformsInput.split(",").map((s2) => s2.trim());
|
|
187
|
+
const darkMode = await p.confirm({
|
|
188
|
+
message: "Enable dark mode support?",
|
|
189
|
+
initialValue: true
|
|
190
|
+
});
|
|
191
|
+
if (p.isCancel(darkMode)) {
|
|
192
|
+
p.cancel("Operation cancelled.");
|
|
193
|
+
process.exit(0);
|
|
194
|
+
}
|
|
195
|
+
const s = p.spinner();
|
|
196
|
+
s.start("Creating project files...");
|
|
197
|
+
const cwd = process.cwd();
|
|
198
|
+
await import_promises.default.mkdir(import_node_path.default.join(cwd, "tokens"), { recursive: true });
|
|
199
|
+
await import_promises.default.mkdir(import_node_path.default.join(cwd, "components"), { recursive: true });
|
|
200
|
+
await import_promises.default.mkdir(import_node_path.default.join(cwd, "generated"), { recursive: true });
|
|
201
|
+
const templateDir = import_node_path.default.resolve(
|
|
202
|
+
typeof __dirname !== "undefined" ? import_node_path.default.resolve(__dirname, "../../templates") : import_node_path.default.resolve(new URL(".", import_meta.url).pathname, "../../templates")
|
|
203
|
+
);
|
|
204
|
+
const templateFile = template === "full" ? "full.tokens.json" : "minimal.tokens.json";
|
|
205
|
+
try {
|
|
206
|
+
const templateContent = await import_promises.default.readFile(
|
|
207
|
+
import_node_path.default.join(templateDir, templateFile),
|
|
208
|
+
"utf-8"
|
|
209
|
+
);
|
|
210
|
+
await import_promises.default.writeFile(
|
|
211
|
+
import_node_path.default.join(cwd, "tokens", "base.tokens.json"),
|
|
212
|
+
templateContent
|
|
213
|
+
);
|
|
214
|
+
} catch {
|
|
215
|
+
await import_promises.default.writeFile(
|
|
216
|
+
import_node_path.default.join(cwd, "tokens", "base.tokens.json"),
|
|
217
|
+
JSON.stringify(getDefaultTokens(), null, 2)
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
await import_promises.default.writeFile(
|
|
221
|
+
import_node_path.default.join(cwd, "tokens", "semantic.tokens.json"),
|
|
222
|
+
JSON.stringify(getSemanticTokens(), null, 2)
|
|
223
|
+
);
|
|
224
|
+
if (darkMode) {
|
|
225
|
+
try {
|
|
226
|
+
const darkContent = await import_promises.default.readFile(
|
|
227
|
+
import_node_path.default.join(templateDir, "dark.tokens.json"),
|
|
228
|
+
"utf-8"
|
|
229
|
+
);
|
|
230
|
+
await import_promises.default.writeFile(
|
|
231
|
+
import_node_path.default.join(cwd, "tokens", "dark.tokens.json"),
|
|
232
|
+
darkContent
|
|
233
|
+
);
|
|
234
|
+
} catch {
|
|
235
|
+
await import_promises.default.writeFile(
|
|
236
|
+
import_node_path.default.join(cwd, "tokens", "dark.tokens.json"),
|
|
237
|
+
JSON.stringify(getDarkTokens(), null, 2)
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const configContent = generateConfig(platforms, darkMode);
|
|
242
|
+
await import_promises.default.writeFile(import_node_path.default.join(cwd, "ryndesign.config.ts"), configContent);
|
|
243
|
+
try {
|
|
244
|
+
const buttonComp = await import_promises.default.readFile(
|
|
245
|
+
import_node_path.default.join(templateDir, "../components/button.component.json"),
|
|
246
|
+
"utf-8"
|
|
247
|
+
);
|
|
248
|
+
await import_promises.default.writeFile(
|
|
249
|
+
import_node_path.default.join(cwd, "components", "button.component.json"),
|
|
250
|
+
buttonComp
|
|
251
|
+
);
|
|
252
|
+
} catch {
|
|
253
|
+
}
|
|
254
|
+
const gitignorePath = import_node_path.default.join(cwd, ".gitignore");
|
|
255
|
+
try {
|
|
256
|
+
let gitignore = "";
|
|
257
|
+
try {
|
|
258
|
+
gitignore = await import_promises.default.readFile(gitignorePath, "utf-8");
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
if (!gitignore.includes("generated/")) {
|
|
262
|
+
gitignore += (gitignore.endsWith("\n") || gitignore === "" ? "" : "\n") + "generated/\n";
|
|
263
|
+
await import_promises.default.writeFile(gitignorePath, gitignore);
|
|
264
|
+
}
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const pkgJsonPath = import_node_path.default.join(cwd, "package.json");
|
|
269
|
+
const pkgContent = await import_promises.default.readFile(pkgJsonPath, "utf-8");
|
|
270
|
+
const pkg = JSON.parse(pkgContent);
|
|
271
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
272
|
+
if (!pkg.scripts["generate"]) pkg.scripts["generate"] = "ryndesign generate";
|
|
273
|
+
if (!pkg.scripts["preview"]) pkg.scripts["preview"] = "ryndesign preview";
|
|
274
|
+
await import_promises.default.writeFile(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
s.stop("Project files created!");
|
|
278
|
+
p.note(
|
|
279
|
+
[
|
|
280
|
+
`${import_picocolors.default.green("tokens/")} - Your design tokens`,
|
|
281
|
+
`${import_picocolors.default.green("components/")} - Component definitions`,
|
|
282
|
+
`${import_picocolors.default.green("generated/")} - Generated output (gitignored)`,
|
|
283
|
+
`${import_picocolors.default.green("ryndesign.config.ts")} - Configuration`
|
|
284
|
+
].join("\n"),
|
|
285
|
+
"Project structure"
|
|
286
|
+
);
|
|
287
|
+
p.outro(import_picocolors.default.green("Run `ryndesign generate` to generate your design system!"));
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// src/config.ts
|
|
294
|
+
async function loadConfig(configPath) {
|
|
295
|
+
const cwd = process.cwd();
|
|
296
|
+
if (configPath) {
|
|
297
|
+
return loadConfigFile(import_node_path2.default.resolve(cwd, configPath));
|
|
298
|
+
}
|
|
299
|
+
for (const name of CONFIG_NAMES) {
|
|
300
|
+
const absolutePath = import_node_path2.default.resolve(cwd, name);
|
|
301
|
+
try {
|
|
302
|
+
await import_promises2.default.access(absolutePath);
|
|
303
|
+
return loadConfigFile(absolutePath);
|
|
304
|
+
} catch {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
async function loadConfigFile(absolutePath) {
|
|
311
|
+
try {
|
|
312
|
+
await import_promises2.default.access(absolutePath);
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
if (absolutePath.endsWith(".json")) {
|
|
317
|
+
try {
|
|
318
|
+
const content = await import_promises2.default.readFile(absolutePath, "utf-8");
|
|
319
|
+
const config = JSON.parse(content);
|
|
320
|
+
return validateConfig(config, absolutePath);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
throw new Error(`Failed to parse config ${absolutePath}: ${err.message}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const { createJiti } = await import("jiti");
|
|
327
|
+
const loader = createJiti(absolutePath, {
|
|
328
|
+
interopDefault: true
|
|
329
|
+
});
|
|
330
|
+
const config = await loader.import(absolutePath);
|
|
331
|
+
const resolved = config.default ?? config;
|
|
332
|
+
return validateConfig(resolved, absolutePath);
|
|
333
|
+
} catch (err) {
|
|
334
|
+
try {
|
|
335
|
+
const mod = await import(absolutePath);
|
|
336
|
+
const resolved = mod.default ?? mod;
|
|
337
|
+
return validateConfig(resolved, absolutePath);
|
|
338
|
+
} catch {
|
|
339
|
+
throw new Error(`Failed to load config ${absolutePath}: ${err.message}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function validateConfig(config, filePath) {
|
|
344
|
+
if (!config.tokens || !Array.isArray(config.tokens) || config.tokens.length === 0) {
|
|
345
|
+
throw new Error(`Invalid config in ${filePath}: "tokens" must be a non-empty array of glob patterns`);
|
|
346
|
+
}
|
|
347
|
+
if (config.components && !Array.isArray(config.components)) {
|
|
348
|
+
throw new Error(`Invalid config in ${filePath}: "components" must be an array of glob patterns`);
|
|
349
|
+
}
|
|
350
|
+
if (config.generators && !Array.isArray(config.generators)) {
|
|
351
|
+
throw new Error(`Invalid config in ${filePath}: "generators" must be an array`);
|
|
352
|
+
}
|
|
353
|
+
return config;
|
|
354
|
+
}
|
|
355
|
+
var import_node_path2, import_promises2, import_plugin_api, CONFIG_NAMES;
|
|
356
|
+
var init_config = __esm({
|
|
357
|
+
"src/config.ts"() {
|
|
358
|
+
"use strict";
|
|
359
|
+
import_node_path2 = __toESM(require("path"), 1);
|
|
360
|
+
import_promises2 = __toESM(require("fs/promises"), 1);
|
|
361
|
+
import_plugin_api = require("@ryndesign/plugin-api");
|
|
362
|
+
CONFIG_NAMES = [
|
|
363
|
+
"ryndesign.config.ts",
|
|
364
|
+
"ryndesign.config.js",
|
|
365
|
+
"ryndesign.config.mjs",
|
|
366
|
+
"ryndesign.config.json"
|
|
367
|
+
];
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// src/commands/generate.ts
|
|
372
|
+
var generate_exports = {};
|
|
373
|
+
__export(generate_exports, {
|
|
374
|
+
default: () => generate_default
|
|
375
|
+
});
|
|
376
|
+
var import_citty2, import_picocolors2, import_node_path3, import_promises3, import_core, generate_default;
|
|
377
|
+
var init_generate = __esm({
|
|
378
|
+
"src/commands/generate.ts"() {
|
|
379
|
+
"use strict";
|
|
380
|
+
import_citty2 = require("citty");
|
|
381
|
+
import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
382
|
+
import_node_path3 = __toESM(require("path"), 1);
|
|
383
|
+
import_promises3 = __toESM(require("fs/promises"), 1);
|
|
384
|
+
import_core = require("@ryndesign/core");
|
|
385
|
+
init_config();
|
|
386
|
+
generate_default = (0, import_citty2.defineCommand)({
|
|
387
|
+
meta: {
|
|
388
|
+
name: "generate",
|
|
389
|
+
description: "Generate design system files for target platforms"
|
|
390
|
+
},
|
|
391
|
+
args: {
|
|
392
|
+
platforms: {
|
|
393
|
+
type: "string",
|
|
394
|
+
description: "Comma-separated list of platforms to generate"
|
|
395
|
+
},
|
|
396
|
+
watch: {
|
|
397
|
+
type: "boolean",
|
|
398
|
+
description: "Watch for changes and regenerate",
|
|
399
|
+
default: false
|
|
400
|
+
},
|
|
401
|
+
clean: {
|
|
402
|
+
type: "boolean",
|
|
403
|
+
description: "Clean output directory before generating",
|
|
404
|
+
default: false
|
|
405
|
+
},
|
|
406
|
+
"dry-run": {
|
|
407
|
+
type: "boolean",
|
|
408
|
+
description: "Show what would be generated without writing files",
|
|
409
|
+
default: false
|
|
410
|
+
},
|
|
411
|
+
config: {
|
|
412
|
+
type: "string",
|
|
413
|
+
description: "Path to config file",
|
|
414
|
+
default: "ryndesign.config.ts"
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
async run({ args }) {
|
|
418
|
+
const dryRun = args["dry-run"];
|
|
419
|
+
console.log(import_picocolors2.default.cyan(`\u26A1 RynDesign Generate${dryRun ? " (dry run)" : ""}
|
|
420
|
+
`));
|
|
421
|
+
const config = await loadConfig(args.config);
|
|
422
|
+
if (!config) {
|
|
423
|
+
console.error(import_picocolors2.default.red("Config file not found. Run `ryndesign init` first."));
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
const cwd = process.cwd();
|
|
427
|
+
if (args.clean && config.outDir) {
|
|
428
|
+
const outDir = import_node_path3.default.resolve(cwd, config.outDir);
|
|
429
|
+
await import_promises3.default.rm(outDir, { recursive: true, force: true });
|
|
430
|
+
await import_promises3.default.mkdir(outDir, { recursive: true });
|
|
431
|
+
console.log(import_picocolors2.default.yellow(`Cleaned ${config.outDir}/`));
|
|
432
|
+
}
|
|
433
|
+
console.log(import_picocolors2.default.gray("Building token set..."));
|
|
434
|
+
const tokenSet = await (0, import_core.buildTokenSet)({
|
|
435
|
+
tokens: config.tokens,
|
|
436
|
+
basePath: cwd,
|
|
437
|
+
themes: config.themes,
|
|
438
|
+
name: "design-system"
|
|
439
|
+
});
|
|
440
|
+
console.log(import_picocolors2.default.green(`\u2713 Resolved ${tokenSet.tokens.length} tokens`));
|
|
441
|
+
if (Object.keys(tokenSet.themes.themes).length > 0) {
|
|
442
|
+
console.log(import_picocolors2.default.green(`\u2713 Resolved themes: ${Object.keys(tokenSet.themes.themes).join(", ")}`));
|
|
443
|
+
}
|
|
444
|
+
let generators = config.generators ?? [];
|
|
445
|
+
if (args.platforms) {
|
|
446
|
+
const targetPlatforms = args.platforms.split(",").map((s) => s.trim());
|
|
447
|
+
generators = generators.filter((g) => targetPlatforms.includes(g.name));
|
|
448
|
+
}
|
|
449
|
+
if (generators.length === 0) {
|
|
450
|
+
console.log(import_picocolors2.default.yellow("No generators configured. Add generators to your ryndesign.config.ts"));
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const components = config.components ? await (0, import_core.loadComponents)(config.components, cwd) : [];
|
|
454
|
+
if (components.length > 0) {
|
|
455
|
+
console.log(import_picocolors2.default.green(`\u2713 Loaded ${components.length} component(s)`));
|
|
456
|
+
}
|
|
457
|
+
const resolvedComponents = components.map((compDef) => (0, import_core.resolveComponent)(compDef, tokenSet));
|
|
458
|
+
const allFiles = [];
|
|
459
|
+
const summary = [];
|
|
460
|
+
for (const generator of generators) {
|
|
461
|
+
console.log(import_picocolors2.default.gray(`
|
|
462
|
+
Generating ${generator.displayName}...`));
|
|
463
|
+
let genFiles = 0;
|
|
464
|
+
let genBytes = 0;
|
|
465
|
+
const ctx = {
|
|
466
|
+
tokenSet,
|
|
467
|
+
config: { outDir: config.outDir ?? "generated", ...generator },
|
|
468
|
+
outputDir: import_node_path3.default.resolve(cwd, config.outDir ?? "generated"),
|
|
469
|
+
helpers: (0, import_core.createGeneratorHelpers)(),
|
|
470
|
+
components: resolvedComponents
|
|
471
|
+
};
|
|
472
|
+
try {
|
|
473
|
+
const tokenFiles = await generator.generateTokens(ctx);
|
|
474
|
+
allFiles.push(...tokenFiles);
|
|
475
|
+
for (const file of tokenFiles) {
|
|
476
|
+
genFiles++;
|
|
477
|
+
genBytes += Buffer.byteLength(file.content, "utf-8");
|
|
478
|
+
if (!dryRun) {
|
|
479
|
+
const filePath = import_node_path3.default.resolve(ctx.outputDir, file.path);
|
|
480
|
+
await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
|
|
481
|
+
await import_promises3.default.writeFile(filePath, file.content, "utf-8");
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
for (const resolvedComp of resolvedComponents) {
|
|
485
|
+
const compFiles = await generator.generateComponent(resolvedComp, ctx);
|
|
486
|
+
allFiles.push(...compFiles);
|
|
487
|
+
for (const file of compFiles) {
|
|
488
|
+
genFiles++;
|
|
489
|
+
genBytes += Buffer.byteLength(file.content, "utf-8");
|
|
490
|
+
if (!dryRun) {
|
|
491
|
+
const filePath = import_node_path3.default.resolve(ctx.outputDir, file.path);
|
|
492
|
+
await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
|
|
493
|
+
await import_promises3.default.writeFile(filePath, file.content, "utf-8");
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
console.log(import_picocolors2.default.green(` \u2713 ${genFiles} files generated for ${generator.displayName}`));
|
|
498
|
+
summary.push({ name: generator.displayName, files: genFiles, bytes: genBytes });
|
|
499
|
+
} catch (err) {
|
|
500
|
+
console.error(import_picocolors2.default.red(` \u2717 ${generator.displayName} failed: ${err.message}`));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (summary.length > 0) {
|
|
504
|
+
console.log(import_picocolors2.default.gray("\n Platform Files Size"));
|
|
505
|
+
console.log(import_picocolors2.default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
506
|
+
for (const s of summary) {
|
|
507
|
+
const sizeStr = s.bytes < 1024 ? `${s.bytes} B` : `${(s.bytes / 1024).toFixed(1)} KB`;
|
|
508
|
+
console.log(` ${s.name.padEnd(18)} ${String(s.files).padStart(5)} ${sizeStr}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (config.hooks?.["generate:complete"]) {
|
|
512
|
+
await config.hooks["generate:complete"](allFiles);
|
|
513
|
+
}
|
|
514
|
+
console.log(import_picocolors2.default.green(`
|
|
515
|
+
\u2713 Generation complete! ${allFiles.length} files ${dryRun ? "would be written" : "written"}.`));
|
|
516
|
+
if (args.watch) {
|
|
517
|
+
console.log(import_picocolors2.default.cyan("\nWatching for changes..."));
|
|
518
|
+
const { watch } = await import("chokidar");
|
|
519
|
+
const watchPatterns = [...config.tokens, ...config.components ?? []];
|
|
520
|
+
const watcher = watch(watchPatterns, {
|
|
521
|
+
cwd,
|
|
522
|
+
ignoreInitial: true
|
|
523
|
+
});
|
|
524
|
+
watcher.on("change", async (changedPath) => {
|
|
525
|
+
console.log(import_picocolors2.default.gray(`
|
|
526
|
+
File changed: ${changedPath}`));
|
|
527
|
+
try {
|
|
528
|
+
const newTokenSet = await (0, import_core.buildTokenSet)({
|
|
529
|
+
tokens: config.tokens,
|
|
530
|
+
basePath: cwd,
|
|
531
|
+
themes: config.themes
|
|
532
|
+
});
|
|
533
|
+
const newComponents = config.components ? await (0, import_core.loadComponents)(config.components, cwd) : [];
|
|
534
|
+
const newResolvedComponents = newComponents.map((c) => (0, import_core.resolveComponent)(c, newTokenSet));
|
|
535
|
+
for (const generator of generators) {
|
|
536
|
+
try {
|
|
537
|
+
const ctx = {
|
|
538
|
+
tokenSet: newTokenSet,
|
|
539
|
+
config: { outDir: config.outDir ?? "generated", ...generator },
|
|
540
|
+
outputDir: import_node_path3.default.resolve(cwd, config.outDir ?? "generated"),
|
|
541
|
+
helpers: (0, import_core.createGeneratorHelpers)(),
|
|
542
|
+
components: newResolvedComponents
|
|
543
|
+
};
|
|
544
|
+
const tokenFiles = await generator.generateTokens(ctx);
|
|
545
|
+
for (const file of tokenFiles) {
|
|
546
|
+
const filePath = import_node_path3.default.resolve(ctx.outputDir, file.path);
|
|
547
|
+
await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
|
|
548
|
+
await import_promises3.default.writeFile(filePath, file.content, "utf-8");
|
|
549
|
+
}
|
|
550
|
+
for (const resolvedComp of newResolvedComponents) {
|
|
551
|
+
const compFiles = await generator.generateComponent(resolvedComp, ctx);
|
|
552
|
+
for (const file of compFiles) {
|
|
553
|
+
const filePath = import_node_path3.default.resolve(ctx.outputDir, file.path);
|
|
554
|
+
await import_promises3.default.mkdir(import_node_path3.default.dirname(filePath), { recursive: true });
|
|
555
|
+
await import_promises3.default.writeFile(filePath, file.content, "utf-8");
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
} catch (err) {
|
|
559
|
+
console.error(import_picocolors2.default.red(` \u2717 ${generator.displayName}: ${err.message}`));
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
console.log(import_picocolors2.default.green("\u2713 Rebuilt and regenerated"));
|
|
563
|
+
} catch (err) {
|
|
564
|
+
console.error(import_picocolors2.default.red(`Error: ${err.message}`));
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// src/commands/validate.ts
|
|
574
|
+
var validate_exports = {};
|
|
575
|
+
__export(validate_exports, {
|
|
576
|
+
default: () => validate_default
|
|
577
|
+
});
|
|
578
|
+
var import_citty3, import_picocolors3, import_core2, validate_default;
|
|
579
|
+
var init_validate = __esm({
|
|
580
|
+
"src/commands/validate.ts"() {
|
|
581
|
+
"use strict";
|
|
582
|
+
import_citty3 = require("citty");
|
|
583
|
+
import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
584
|
+
import_core2 = require("@ryndesign/core");
|
|
585
|
+
validate_default = (0, import_citty3.defineCommand)({
|
|
586
|
+
meta: {
|
|
587
|
+
name: "validate",
|
|
588
|
+
description: "Validate design token files"
|
|
589
|
+
},
|
|
590
|
+
args: {
|
|
591
|
+
path: {
|
|
592
|
+
type: "positional",
|
|
593
|
+
description: "Path to token file(s)",
|
|
594
|
+
required: false
|
|
595
|
+
},
|
|
596
|
+
strict: {
|
|
597
|
+
type: "boolean",
|
|
598
|
+
description: "Treat warnings as errors",
|
|
599
|
+
default: false
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
async run({ args }) {
|
|
603
|
+
console.log(import_picocolors3.default.cyan(" RynDesign Validate\n"));
|
|
604
|
+
const patterns = args.path ? [args.path] : ["tokens/**/*.tokens.json"];
|
|
605
|
+
try {
|
|
606
|
+
const tree = await (0, import_core2.readAndMergeTokenFiles)(patterns);
|
|
607
|
+
(0, import_core2.validateTree)(tree);
|
|
608
|
+
const tokenSet = await (0, import_core2.buildTokenSet)({
|
|
609
|
+
tokens: patterns,
|
|
610
|
+
basePath: process.cwd()
|
|
611
|
+
});
|
|
612
|
+
const issues = (0, import_core2.postValidate)(tokenSet.tokens, tokenSet.themes);
|
|
613
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
614
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
615
|
+
console.log(import_picocolors3.default.green(` ${tokenSet.tokens.length} tokens resolved`));
|
|
616
|
+
console.log(import_picocolors3.default.green(` ${tokenSet.groups.length} groups`));
|
|
617
|
+
const themeCount = Object.keys(tokenSet.themes.themes).length;
|
|
618
|
+
if (themeCount > 0) {
|
|
619
|
+
console.log(import_picocolors3.default.green(` ${themeCount} theme(s): ${Object.keys(tokenSet.themes.themes).join(", ")}`));
|
|
620
|
+
}
|
|
621
|
+
if (errors.length > 0) {
|
|
622
|
+
console.error(import_picocolors3.default.red(`
|
|
623
|
+
${errors.length} error(s):
|
|
624
|
+
`));
|
|
625
|
+
for (const issue of errors) {
|
|
626
|
+
console.error(` ${import_picocolors3.default.red("x")} ${issue.path}: ${issue.message}`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (warnings.length > 0) {
|
|
630
|
+
console.log(import_picocolors3.default.yellow(`
|
|
631
|
+
${warnings.length} warning(s):
|
|
632
|
+
`));
|
|
633
|
+
for (const issue of warnings) {
|
|
634
|
+
console.log(` ${import_picocolors3.default.yellow("!")} ${issue.path}: ${issue.message}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (errors.length === 0 && warnings.length === 0) {
|
|
638
|
+
console.log(import_picocolors3.default.green("\n All tokens are valid!"));
|
|
639
|
+
} else if (errors.length === 0) {
|
|
640
|
+
console.log(import_picocolors3.default.green("\n Tokens are valid (with warnings)"));
|
|
641
|
+
}
|
|
642
|
+
if (args.strict && (errors.length > 0 || warnings.length > 0)) {
|
|
643
|
+
process.exit(1);
|
|
644
|
+
}
|
|
645
|
+
if (errors.length > 0) {
|
|
646
|
+
process.exit(1);
|
|
647
|
+
}
|
|
648
|
+
} catch (err) {
|
|
649
|
+
if (err instanceof import_core2.TokenValidationError) {
|
|
650
|
+
console.error(import_picocolors3.default.red(` Validation failed with ${err.errors.length} issue(s):
|
|
651
|
+
`));
|
|
652
|
+
for (const issue of err.errors) {
|
|
653
|
+
const icon = issue.severity === "error" ? import_picocolors3.default.red("x") : import_picocolors3.default.yellow("!");
|
|
654
|
+
console.error(` ${icon} ${issue.path.join(".")}: ${issue.message}`);
|
|
655
|
+
}
|
|
656
|
+
process.exit(1);
|
|
657
|
+
}
|
|
658
|
+
throw err;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
// src/commands/preview.ts
|
|
666
|
+
var preview_exports = {};
|
|
667
|
+
__export(preview_exports, {
|
|
668
|
+
default: () => preview_default
|
|
669
|
+
});
|
|
670
|
+
var import_citty4, import_picocolors4, preview_default;
|
|
671
|
+
var init_preview = __esm({
|
|
672
|
+
"src/commands/preview.ts"() {
|
|
673
|
+
"use strict";
|
|
674
|
+
import_citty4 = require("citty");
|
|
675
|
+
import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
676
|
+
preview_default = (0, import_citty4.defineCommand)({
|
|
677
|
+
meta: {
|
|
678
|
+
name: "preview",
|
|
679
|
+
description: "Start the design system preview server"
|
|
680
|
+
},
|
|
681
|
+
args: {
|
|
682
|
+
port: {
|
|
683
|
+
type: "string",
|
|
684
|
+
description: "Port to run the preview server on",
|
|
685
|
+
default: "4400"
|
|
686
|
+
},
|
|
687
|
+
open: {
|
|
688
|
+
type: "boolean",
|
|
689
|
+
description: "Open browser automatically",
|
|
690
|
+
default: true
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
async run({ args }) {
|
|
694
|
+
console.log(import_picocolors4.default.cyan("\u{1F5A5} RynDesign Preview\n"));
|
|
695
|
+
try {
|
|
696
|
+
const { startPreviewServer } = await import("@ryndesign/preview");
|
|
697
|
+
await startPreviewServer({
|
|
698
|
+
port: parseInt(args.port, 10),
|
|
699
|
+
open: args.open
|
|
700
|
+
});
|
|
701
|
+
} catch {
|
|
702
|
+
console.log(import_picocolors4.default.yellow("Preview package not found. Install @ryndesign/preview"));
|
|
703
|
+
console.log(import_picocolors4.default.gray(" pnpm add @ryndesign/preview"));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
// src/commands/add.ts
|
|
711
|
+
var add_exports = {};
|
|
712
|
+
__export(add_exports, {
|
|
713
|
+
default: () => add_default
|
|
714
|
+
});
|
|
715
|
+
var import_citty5, p2, import_picocolors5, import_promises4, import_node_path4, import_meta2, AVAILABLE_COMPONENTS, COMPONENT_TOKENS, add_default;
|
|
716
|
+
var init_add = __esm({
|
|
717
|
+
"src/commands/add.ts"() {
|
|
718
|
+
"use strict";
|
|
719
|
+
import_citty5 = require("citty");
|
|
720
|
+
p2 = __toESM(require("@clack/prompts"), 1);
|
|
721
|
+
import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
722
|
+
import_promises4 = __toESM(require("fs/promises"), 1);
|
|
723
|
+
import_node_path4 = __toESM(require("path"), 1);
|
|
724
|
+
import_meta2 = {};
|
|
725
|
+
AVAILABLE_COMPONENTS = ["button", "input", "card", "checkbox", "toggle", "badge", "avatar"];
|
|
726
|
+
COMPONENT_TOKENS = {
|
|
727
|
+
button: {
|
|
728
|
+
"component.button": {
|
|
729
|
+
$type: "color",
|
|
730
|
+
primary: {
|
|
731
|
+
background: { $value: "{color.primary}" },
|
|
732
|
+
text: { $value: "{color.white}" },
|
|
733
|
+
hover: { background: { $value: "{color.primary}" } },
|
|
734
|
+
pressed: { background: { $value: "{color.primary}" } }
|
|
735
|
+
},
|
|
736
|
+
secondary: {
|
|
737
|
+
background: { $value: "{color.secondary}" },
|
|
738
|
+
text: { $value: "{color.white}" }
|
|
739
|
+
},
|
|
740
|
+
borderRadius: { $type: "dimension", $value: "8px" },
|
|
741
|
+
sm: { paddingX: { $type: "dimension", $value: "12px" }, paddingY: { $type: "dimension", $value: "6px" }, fontSize: { $type: "dimension", $value: "14px" } },
|
|
742
|
+
md: { paddingX: { $type: "dimension", $value: "16px" }, paddingY: { $type: "dimension", $value: "10px" }, fontSize: { $type: "dimension", $value: "16px" } },
|
|
743
|
+
lg: { paddingX: { $type: "dimension", $value: "24px" }, paddingY: { $type: "dimension", $value: "14px" }, fontSize: { $type: "dimension", $value: "18px" } },
|
|
744
|
+
disabled: { background: { $value: "{color.gray.300}" } }
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
add_default = (0, import_citty5.defineCommand)({
|
|
749
|
+
meta: {
|
|
750
|
+
name: "add",
|
|
751
|
+
description: "Add a component definition"
|
|
752
|
+
},
|
|
753
|
+
args: {
|
|
754
|
+
name: {
|
|
755
|
+
type: "positional",
|
|
756
|
+
description: "Component name to add",
|
|
757
|
+
required: false
|
|
758
|
+
},
|
|
759
|
+
"with-tokens": {
|
|
760
|
+
type: "boolean",
|
|
761
|
+
description: "Also scaffold component tokens",
|
|
762
|
+
default: false
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
async run({ args }) {
|
|
766
|
+
const name = args.name || await p2.select({
|
|
767
|
+
message: "Choose a component to add:",
|
|
768
|
+
options: AVAILABLE_COMPONENTS.map((c) => ({
|
|
769
|
+
value: c,
|
|
770
|
+
label: c.charAt(0).toUpperCase() + c.slice(1)
|
|
771
|
+
}))
|
|
772
|
+
});
|
|
773
|
+
if (p2.isCancel(name)) {
|
|
774
|
+
p2.cancel("Operation cancelled.");
|
|
775
|
+
process.exit(0);
|
|
776
|
+
}
|
|
777
|
+
const cwd = process.cwd();
|
|
778
|
+
const componentsDir = import_node_path4.default.join(cwd, "components");
|
|
779
|
+
await import_promises4.default.mkdir(componentsDir, { recursive: true });
|
|
780
|
+
const destPath = import_node_path4.default.join(componentsDir, `${name}.component.json`);
|
|
781
|
+
try {
|
|
782
|
+
await import_promises4.default.access(destPath);
|
|
783
|
+
console.log(import_picocolors5.default.yellow(`Component ${name} already exists at ${destPath}`));
|
|
784
|
+
return;
|
|
785
|
+
} catch {
|
|
786
|
+
}
|
|
787
|
+
let copied = false;
|
|
788
|
+
const searchPaths = [
|
|
789
|
+
import_node_path4.default.resolve(__dirname, `../../components/${name}.component.json`),
|
|
790
|
+
// ESM fallback
|
|
791
|
+
typeof __dirname !== "undefined" ? import_node_path4.default.resolve(__dirname, `../../components/${name}.component.json`) : import_node_path4.default.resolve(new URL(".", import_meta2.url).pathname, `../../components/${name}.component.json`)
|
|
792
|
+
];
|
|
793
|
+
for (const srcPath of searchPaths) {
|
|
794
|
+
try {
|
|
795
|
+
const content = await import_promises4.default.readFile(srcPath, "utf-8");
|
|
796
|
+
await import_promises4.default.writeFile(destPath, content);
|
|
797
|
+
console.log(import_picocolors5.default.green(` Added ${name} component to ${destPath}`));
|
|
798
|
+
copied = true;
|
|
799
|
+
break;
|
|
800
|
+
} catch {
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
if (!copied) {
|
|
805
|
+
console.error(import_picocolors5.default.red(`Component "${name}" not found in available components.`));
|
|
806
|
+
console.log(import_picocolors5.default.gray(`Available: ${AVAILABLE_COMPONENTS.join(", ")}`));
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
const withTokens = args["with-tokens"];
|
|
810
|
+
if (withTokens && COMPONENT_TOKENS[name]) {
|
|
811
|
+
const tokensDir = import_node_path4.default.join(cwd, "tokens");
|
|
812
|
+
await import_promises4.default.mkdir(tokensDir, { recursive: true });
|
|
813
|
+
const tokenFile = import_node_path4.default.join(tokensDir, `${name}.tokens.json`);
|
|
814
|
+
try {
|
|
815
|
+
await import_promises4.default.access(tokenFile);
|
|
816
|
+
console.log(import_picocolors5.default.yellow(` Token file already exists: ${tokenFile}`));
|
|
817
|
+
} catch {
|
|
818
|
+
await import_promises4.default.writeFile(tokenFile, JSON.stringify(COMPONENT_TOKENS[name], null, 2));
|
|
819
|
+
console.log(import_picocolors5.default.green(` Created component tokens: ${tokenFile}`));
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
// src/commands/figma-pull.ts
|
|
828
|
+
var figma_pull_exports = {};
|
|
829
|
+
__export(figma_pull_exports, {
|
|
830
|
+
default: () => figma_pull_default
|
|
831
|
+
});
|
|
832
|
+
async function readJsonSafe(absolutePath) {
|
|
833
|
+
try {
|
|
834
|
+
const content = await import_promises5.default.readFile(absolutePath, "utf-8");
|
|
835
|
+
return JSON.parse(content);
|
|
836
|
+
} catch {
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
var import_citty6, import_picocolors6, import_promises5, import_node_path5, figma_pull_default;
|
|
841
|
+
var init_figma_pull = __esm({
|
|
842
|
+
"src/commands/figma-pull.ts"() {
|
|
843
|
+
"use strict";
|
|
844
|
+
import_citty6 = require("citty");
|
|
845
|
+
import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
846
|
+
import_promises5 = __toESM(require("fs/promises"), 1);
|
|
847
|
+
import_node_path5 = __toESM(require("path"), 1);
|
|
848
|
+
init_config();
|
|
849
|
+
figma_pull_default = (0, import_citty6.defineCommand)({
|
|
850
|
+
meta: {
|
|
851
|
+
name: "pull",
|
|
852
|
+
description: "Pull design tokens from Figma"
|
|
853
|
+
},
|
|
854
|
+
args: {
|
|
855
|
+
"file-key": {
|
|
856
|
+
type: "string",
|
|
857
|
+
description: "Figma file key"
|
|
858
|
+
},
|
|
859
|
+
token: {
|
|
860
|
+
type: "string",
|
|
861
|
+
description: "Figma personal access token"
|
|
862
|
+
},
|
|
863
|
+
config: {
|
|
864
|
+
type: "string",
|
|
865
|
+
description: "Path to config file",
|
|
866
|
+
default: "ryndesign.config.ts"
|
|
867
|
+
},
|
|
868
|
+
merge: {
|
|
869
|
+
type: "boolean",
|
|
870
|
+
description: "Merge with existing local tokens instead of overwriting",
|
|
871
|
+
default: false
|
|
872
|
+
},
|
|
873
|
+
strategy: {
|
|
874
|
+
type: "string",
|
|
875
|
+
description: "Merge strategy: prefer-remote, prefer-local, remote-only-new",
|
|
876
|
+
default: "prefer-remote"
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
async run({ args }) {
|
|
880
|
+
console.log(import_picocolors6.default.cyan("\u{1F4E5} Figma Pull\n"));
|
|
881
|
+
const config = await loadConfig(args.config);
|
|
882
|
+
const fileKey = args["file-key"] || config?.figma?.fileKey;
|
|
883
|
+
const pat = args.token || config?.figma?.personalAccessToken || process.env.FIGMA_TOKEN;
|
|
884
|
+
if (!fileKey) {
|
|
885
|
+
console.error(import_picocolors6.default.red("Missing Figma file key. Use --file-key or set in config."));
|
|
886
|
+
process.exit(1);
|
|
887
|
+
}
|
|
888
|
+
if (!pat) {
|
|
889
|
+
console.error(import_picocolors6.default.red("Missing Figma token. Use --token, set FIGMA_TOKEN env var, or configure in ryndesign.config.ts"));
|
|
890
|
+
process.exit(1);
|
|
891
|
+
}
|
|
892
|
+
const shouldMerge = args.merge;
|
|
893
|
+
const strategy = args.strategy;
|
|
894
|
+
const validStrategies = ["prefer-remote", "prefer-local", "remote-only-new"];
|
|
895
|
+
if (shouldMerge && !validStrategies.includes(strategy)) {
|
|
896
|
+
console.error(import_picocolors6.default.red(`Invalid merge strategy "${strategy}". Use: ${validStrategies.join(", ")}`));
|
|
897
|
+
process.exit(1);
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
const { fetchFigmaVariables, mapFigmaToTokens, resolveFigmaModes, mergeTokens } = await import("@ryndesign/figma");
|
|
901
|
+
console.log(import_picocolors6.default.gray("Fetching variables from Figma..."));
|
|
902
|
+
const variables = await fetchFigmaVariables({
|
|
903
|
+
fileKey,
|
|
904
|
+
personalAccessToken: pat
|
|
905
|
+
});
|
|
906
|
+
console.log(import_picocolors6.default.green(`\u2713 Fetched ${variables.length} variables`));
|
|
907
|
+
const cwd = process.cwd();
|
|
908
|
+
const modeMapping = config?.figma?.modeMapping;
|
|
909
|
+
if (modeMapping) {
|
|
910
|
+
const modeFiles = resolveFigmaModes(variables, modeMapping);
|
|
911
|
+
for (const [filePath, tree] of Object.entries(modeFiles)) {
|
|
912
|
+
const absolutePath = import_node_path5.default.resolve(cwd, filePath);
|
|
913
|
+
await import_promises5.default.mkdir(import_node_path5.default.dirname(absolutePath), { recursive: true });
|
|
914
|
+
if (shouldMerge) {
|
|
915
|
+
const existing = await readJsonSafe(absolutePath);
|
|
916
|
+
if (existing) {
|
|
917
|
+
const modeTokens = variables.filter((t) => {
|
|
918
|
+
const modeName = Object.keys(modeMapping).find((m) => modeMapping[m] === filePath);
|
|
919
|
+
return modeName && t.modes[modeName] !== void 0;
|
|
920
|
+
});
|
|
921
|
+
const result = mergeTokens(existing, modeTokens, { strategy });
|
|
922
|
+
await import_promises5.default.writeFile(absolutePath, JSON.stringify(result.merged, null, 2), "utf-8");
|
|
923
|
+
console.log(import_picocolors6.default.green(` \u2713 Merged ${filePath}`) + import_picocolors6.default.gray(` (+${result.stats.added} new, ${result.stats.updated} updated, ${result.stats.kept} kept)`));
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
await import_promises5.default.writeFile(absolutePath, JSON.stringify(tree, null, 2), "utf-8");
|
|
928
|
+
console.log(import_picocolors6.default.green(` \u2713 Written ${filePath}`));
|
|
929
|
+
}
|
|
930
|
+
} else {
|
|
931
|
+
const outPath = import_node_path5.default.resolve(cwd, "tokens/figma.tokens.json");
|
|
932
|
+
await import_promises5.default.mkdir(import_node_path5.default.dirname(outPath), { recursive: true });
|
|
933
|
+
if (shouldMerge) {
|
|
934
|
+
const existing = await readJsonSafe(outPath);
|
|
935
|
+
if (existing) {
|
|
936
|
+
const result = mergeTokens(existing, variables, { strategy });
|
|
937
|
+
await import_promises5.default.writeFile(outPath, JSON.stringify(result.merged, null, 2), "utf-8");
|
|
938
|
+
console.log(import_picocolors6.default.green(` \u2713 Merged tokens/figma.tokens.json`) + import_picocolors6.default.gray(` (+${result.stats.added} new, ${result.stats.updated} updated, ${result.stats.kept} kept)`));
|
|
939
|
+
} else {
|
|
940
|
+
const tree = mapFigmaToTokens(variables);
|
|
941
|
+
await import_promises5.default.writeFile(outPath, JSON.stringify(tree, null, 2), "utf-8");
|
|
942
|
+
console.log(import_picocolors6.default.green(` \u2713 Written tokens/figma.tokens.json`));
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
const tree = mapFigmaToTokens(variables);
|
|
946
|
+
await import_promises5.default.writeFile(outPath, JSON.stringify(tree, null, 2), "utf-8");
|
|
947
|
+
console.log(import_picocolors6.default.green(` \u2713 Written tokens/figma.tokens.json`));
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
console.log(import_picocolors6.default.green("\n\u2713 Figma pull complete!"));
|
|
951
|
+
} catch (err) {
|
|
952
|
+
console.error(import_picocolors6.default.red(`Error: ${err.message}`));
|
|
953
|
+
process.exit(1);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
// src/commands/figma-push.ts
|
|
961
|
+
var figma_push_exports = {};
|
|
962
|
+
__export(figma_push_exports, {
|
|
963
|
+
default: () => figma_push_default
|
|
964
|
+
});
|
|
965
|
+
var import_citty7, import_picocolors7, import_core3, figma_push_default;
|
|
966
|
+
var init_figma_push = __esm({
|
|
967
|
+
"src/commands/figma-push.ts"() {
|
|
968
|
+
"use strict";
|
|
969
|
+
import_citty7 = require("citty");
|
|
970
|
+
import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
971
|
+
import_core3 = require("@ryndesign/core");
|
|
972
|
+
init_config();
|
|
973
|
+
figma_push_default = (0, import_citty7.defineCommand)({
|
|
974
|
+
meta: {
|
|
975
|
+
name: "push",
|
|
976
|
+
description: "Push design tokens to Figma"
|
|
977
|
+
},
|
|
978
|
+
args: {
|
|
979
|
+
"file-key": {
|
|
980
|
+
type: "string",
|
|
981
|
+
description: "Figma file key"
|
|
982
|
+
},
|
|
983
|
+
token: {
|
|
984
|
+
type: "string",
|
|
985
|
+
description: "Figma personal access token"
|
|
986
|
+
},
|
|
987
|
+
config: {
|
|
988
|
+
type: "string",
|
|
989
|
+
description: "Path to config file",
|
|
990
|
+
default: "ryndesign.config.ts"
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
async run({ args }) {
|
|
994
|
+
console.log(import_picocolors7.default.cyan("\u{1F4E4} Figma Push\n"));
|
|
995
|
+
const config = await loadConfig(args.config);
|
|
996
|
+
const fileKey = args["file-key"] || config?.figma?.fileKey;
|
|
997
|
+
const pat = args.token || config?.figma?.personalAccessToken || process.env.FIGMA_TOKEN;
|
|
998
|
+
if (!fileKey) {
|
|
999
|
+
console.error(import_picocolors7.default.red("Missing Figma file key. Use --file-key or set in config."));
|
|
1000
|
+
process.exit(1);
|
|
1001
|
+
}
|
|
1002
|
+
if (!pat) {
|
|
1003
|
+
console.error(import_picocolors7.default.red("Missing Figma token. Use --token, set FIGMA_TOKEN env var, or configure in ryndesign.config.ts"));
|
|
1004
|
+
process.exit(1);
|
|
1005
|
+
}
|
|
1006
|
+
try {
|
|
1007
|
+
const { pushVariablesToFigma } = await import("@ryndesign/figma");
|
|
1008
|
+
const cwd = process.cwd();
|
|
1009
|
+
console.log(import_picocolors7.default.gray("Building token set..."));
|
|
1010
|
+
const tokenSet = await (0, import_core3.buildTokenSet)({
|
|
1011
|
+
tokens: config?.tokens ?? ["tokens/**/*.tokens.json"],
|
|
1012
|
+
basePath: cwd,
|
|
1013
|
+
themes: config?.themes
|
|
1014
|
+
});
|
|
1015
|
+
console.log(import_picocolors7.default.green(`\u2713 Resolved ${tokenSet.tokens.length} tokens`));
|
|
1016
|
+
console.log(import_picocolors7.default.gray("Pushing to Figma..."));
|
|
1017
|
+
const darkTokens = tokenSet.themes.themes["dark"]?.tokens;
|
|
1018
|
+
await pushVariablesToFigma({
|
|
1019
|
+
fileKey,
|
|
1020
|
+
personalAccessToken: pat,
|
|
1021
|
+
tokens: tokenSet.tokens,
|
|
1022
|
+
darkTokens
|
|
1023
|
+
});
|
|
1024
|
+
console.log(import_picocolors7.default.green("\n\u2713 Figma push complete!"));
|
|
1025
|
+
} catch (err) {
|
|
1026
|
+
console.error(import_picocolors7.default.red(`Error: ${err.message}`));
|
|
1027
|
+
process.exit(1);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
// src/commands/figma-diff.ts
|
|
1035
|
+
var figma_diff_exports = {};
|
|
1036
|
+
__export(figma_diff_exports, {
|
|
1037
|
+
default: () => figma_diff_default
|
|
1038
|
+
});
|
|
1039
|
+
var import_citty8, import_picocolors8, import_core4, figma_diff_default;
|
|
1040
|
+
var init_figma_diff = __esm({
|
|
1041
|
+
"src/commands/figma-diff.ts"() {
|
|
1042
|
+
"use strict";
|
|
1043
|
+
import_citty8 = require("citty");
|
|
1044
|
+
import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
1045
|
+
import_core4 = require("@ryndesign/core");
|
|
1046
|
+
init_config();
|
|
1047
|
+
figma_diff_default = (0, import_citty8.defineCommand)({
|
|
1048
|
+
meta: {
|
|
1049
|
+
name: "diff",
|
|
1050
|
+
description: "Compare local tokens with Figma"
|
|
1051
|
+
},
|
|
1052
|
+
args: {
|
|
1053
|
+
"file-key": {
|
|
1054
|
+
type: "string",
|
|
1055
|
+
description: "Figma file key"
|
|
1056
|
+
},
|
|
1057
|
+
token: {
|
|
1058
|
+
type: "string",
|
|
1059
|
+
description: "Figma personal access token"
|
|
1060
|
+
},
|
|
1061
|
+
config: {
|
|
1062
|
+
type: "string",
|
|
1063
|
+
description: "Path to config file",
|
|
1064
|
+
default: "ryndesign.config.ts"
|
|
1065
|
+
}
|
|
1066
|
+
},
|
|
1067
|
+
async run({ args }) {
|
|
1068
|
+
console.log(import_picocolors8.default.cyan("\u{1F50D} Figma Diff\n"));
|
|
1069
|
+
const config = await loadConfig(args.config);
|
|
1070
|
+
const fileKey = args["file-key"] || config?.figma?.fileKey;
|
|
1071
|
+
const pat = args.token || config?.figma?.personalAccessToken || process.env.FIGMA_TOKEN;
|
|
1072
|
+
if (!fileKey) {
|
|
1073
|
+
console.error(import_picocolors8.default.red("Missing Figma file key. Use --file-key or set in config."));
|
|
1074
|
+
process.exit(1);
|
|
1075
|
+
}
|
|
1076
|
+
if (!pat) {
|
|
1077
|
+
console.error(import_picocolors8.default.red("Missing Figma token. Use --token, set FIGMA_TOKEN env var, or configure in ryndesign.config.ts"));
|
|
1078
|
+
process.exit(1);
|
|
1079
|
+
}
|
|
1080
|
+
try {
|
|
1081
|
+
const { fetchFigmaVariables, diffFigmaTokens } = await import("@ryndesign/figma");
|
|
1082
|
+
const cwd = process.cwd();
|
|
1083
|
+
console.log(import_picocolors8.default.gray("Building local token set..."));
|
|
1084
|
+
const tokenSet = await (0, import_core4.buildTokenSet)({
|
|
1085
|
+
tokens: config?.tokens ?? ["tokens/**/*.tokens.json"],
|
|
1086
|
+
basePath: cwd,
|
|
1087
|
+
themes: config?.themes
|
|
1088
|
+
});
|
|
1089
|
+
console.log(import_picocolors8.default.gray("Fetching Figma variables..."));
|
|
1090
|
+
const remoteTokens = await fetchFigmaVariables({
|
|
1091
|
+
fileKey,
|
|
1092
|
+
personalAccessToken: pat
|
|
1093
|
+
});
|
|
1094
|
+
const result = diffFigmaTokens(tokenSet.tokens, remoteTokens);
|
|
1095
|
+
if (result.added.length > 0) {
|
|
1096
|
+
console.log(import_picocolors8.default.green(`
|
|
1097
|
+
+ Added (local only): ${result.added.length}`));
|
|
1098
|
+
for (const entry of result.added) {
|
|
1099
|
+
console.log(import_picocolors8.default.green(` + ${entry.path}: ${JSON.stringify(entry.local)}`));
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
if (result.removed.length > 0) {
|
|
1103
|
+
console.log(import_picocolors8.default.red(`
|
|
1104
|
+
- Removed (Figma only): ${result.removed.length}`));
|
|
1105
|
+
for (const entry of result.removed) {
|
|
1106
|
+
console.log(import_picocolors8.default.red(` - ${entry.path}: ${JSON.stringify(entry.remote)}`));
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (result.modified.length > 0) {
|
|
1110
|
+
console.log(import_picocolors8.default.yellow(`
|
|
1111
|
+
~ Modified: ${result.modified.length}`));
|
|
1112
|
+
for (const entry of result.modified) {
|
|
1113
|
+
console.log(import_picocolors8.default.yellow(` ~ ${entry.path}: ${JSON.stringify(entry.local)} \u2190 ${JSON.stringify(entry.remote)}`));
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
console.log(import_picocolors8.default.gray(`
|
|
1117
|
+
Unchanged: ${result.unchanged}`));
|
|
1118
|
+
const total = result.added.length + result.removed.length + result.modified.length;
|
|
1119
|
+
if (total === 0) {
|
|
1120
|
+
console.log(import_picocolors8.default.green("\n\u2713 Local and Figma tokens are in sync!"));
|
|
1121
|
+
} else {
|
|
1122
|
+
console.log(import_picocolors8.default.yellow(`
|
|
1123
|
+
${total} difference(s) found.`));
|
|
1124
|
+
}
|
|
1125
|
+
} catch (err) {
|
|
1126
|
+
console.error(import_picocolors8.default.red(`Error: ${err.message}`));
|
|
1127
|
+
process.exit(1);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
// src/commands/figma.ts
|
|
1135
|
+
var figma_exports = {};
|
|
1136
|
+
__export(figma_exports, {
|
|
1137
|
+
default: () => figma_default
|
|
1138
|
+
});
|
|
1139
|
+
var import_citty9, import_picocolors9, import_node_path6, import_promises6, figma_default;
|
|
1140
|
+
var init_figma = __esm({
|
|
1141
|
+
"src/commands/figma.ts"() {
|
|
1142
|
+
"use strict";
|
|
1143
|
+
import_citty9 = require("citty");
|
|
1144
|
+
import_picocolors9 = require("picocolors");
|
|
1145
|
+
import_node_path6 = require("path");
|
|
1146
|
+
import_promises6 = require("fs/promises");
|
|
1147
|
+
init_config();
|
|
1148
|
+
figma_default = (0, import_citty9.defineCommand)({
|
|
1149
|
+
meta: {
|
|
1150
|
+
name: "figma",
|
|
1151
|
+
description: "Figma integration commands"
|
|
1152
|
+
},
|
|
1153
|
+
subCommands: {
|
|
1154
|
+
pull: () => Promise.resolve().then(() => (init_figma_pull(), figma_pull_exports)).then((m) => m.default),
|
|
1155
|
+
push: () => Promise.resolve().then(() => (init_figma_push(), figma_push_exports)).then((m) => m.default),
|
|
1156
|
+
diff: () => Promise.resolve().then(() => (init_figma_diff(), figma_diff_exports)).then((m) => m.default)
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
// src/commands/eject.ts
|
|
1163
|
+
var eject_exports = {};
|
|
1164
|
+
__export(eject_exports, {
|
|
1165
|
+
default: () => eject_default
|
|
1166
|
+
});
|
|
1167
|
+
async function copyDir(src, dest) {
|
|
1168
|
+
await import_promises7.default.mkdir(dest, { recursive: true });
|
|
1169
|
+
const entries = await import_promises7.default.readdir(src, { withFileTypes: true });
|
|
1170
|
+
for (const entry of entries) {
|
|
1171
|
+
const srcPath = import_node_path7.default.join(src, entry.name);
|
|
1172
|
+
const destPath = import_node_path7.default.join(dest, entry.name);
|
|
1173
|
+
if (entry.isDirectory()) {
|
|
1174
|
+
await copyDir(srcPath, destPath);
|
|
1175
|
+
} else {
|
|
1176
|
+
await import_promises7.default.copyFile(srcPath, destPath);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
async function createSkeletonGenerator(dir, name) {
|
|
1181
|
+
const pascalName = name.charAt(0).toUpperCase() + name.slice(1).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
1182
|
+
const indexContent = `import type { GeneratorPlugin, GeneratorContext, GeneratedFile, ResolvedComponent } from '@ryndesign/plugin-api';
|
|
1183
|
+
|
|
1184
|
+
export default function ${name.replace(/-/g, "")}Generator(options = {}): GeneratorPlugin {
|
|
1185
|
+
return {
|
|
1186
|
+
name: '${name}',
|
|
1187
|
+
displayName: '${pascalName}',
|
|
1188
|
+
platform: 'web',
|
|
1189
|
+
outputExtensions: ['.ts', '.css'],
|
|
1190
|
+
|
|
1191
|
+
async generateTokens(ctx: GeneratorContext): Promise<GeneratedFile[]> {
|
|
1192
|
+
// TODO: Implement token generation
|
|
1193
|
+
return [];
|
|
1194
|
+
},
|
|
1195
|
+
|
|
1196
|
+
async generateComponent(comp: ResolvedComponent, ctx: GeneratorContext): Promise<GeneratedFile[]> {
|
|
1197
|
+
// TODO: Implement component generation
|
|
1198
|
+
return [];
|
|
1199
|
+
},
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
`;
|
|
1203
|
+
await import_promises7.default.writeFile(import_node_path7.default.join(dir, "index.ts"), indexContent, "utf-8");
|
|
1204
|
+
}
|
|
1205
|
+
var import_citty10, p3, import_picocolors10, import_promises7, import_node_path7, GENERATORS, eject_default;
|
|
1206
|
+
var init_eject = __esm({
|
|
1207
|
+
"src/commands/eject.ts"() {
|
|
1208
|
+
"use strict";
|
|
1209
|
+
import_citty10 = require("citty");
|
|
1210
|
+
p3 = __toESM(require("@clack/prompts"), 1);
|
|
1211
|
+
import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
1212
|
+
import_promises7 = __toESM(require("fs/promises"), 1);
|
|
1213
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
1214
|
+
GENERATORS = ["react", "vue", "svelte", "rails", "swiftui", "uikit", "compose", "android-view"];
|
|
1215
|
+
eject_default = (0, import_citty10.defineCommand)({
|
|
1216
|
+
meta: {
|
|
1217
|
+
name: "eject",
|
|
1218
|
+
description: "Eject a generator for customization"
|
|
1219
|
+
},
|
|
1220
|
+
args: {
|
|
1221
|
+
name: {
|
|
1222
|
+
type: "positional",
|
|
1223
|
+
description: "Generator name to eject",
|
|
1224
|
+
required: false
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
async run({ args }) {
|
|
1228
|
+
p3.intro(import_picocolors10.default.bgYellow(import_picocolors10.default.black(" RynDesign Eject ")));
|
|
1229
|
+
const name = args.name || await p3.select({
|
|
1230
|
+
message: "Select a generator to eject:",
|
|
1231
|
+
options: GENERATORS.map((g) => ({ value: g, label: `@ryndesign/generator-${g}` }))
|
|
1232
|
+
});
|
|
1233
|
+
if (p3.isCancel(name)) {
|
|
1234
|
+
p3.cancel("Operation cancelled.");
|
|
1235
|
+
process.exit(0);
|
|
1236
|
+
}
|
|
1237
|
+
if (!GENERATORS.includes(name)) {
|
|
1238
|
+
console.error(import_picocolors10.default.red(`Unknown generator: ${name}`));
|
|
1239
|
+
console.log(import_picocolors10.default.gray(`Available: ${GENERATORS.join(", ")}`));
|
|
1240
|
+
process.exit(1);
|
|
1241
|
+
}
|
|
1242
|
+
const cwd = process.cwd();
|
|
1243
|
+
const destDir = import_node_path7.default.join(cwd, "generators", name);
|
|
1244
|
+
try {
|
|
1245
|
+
await import_promises7.default.access(destDir);
|
|
1246
|
+
console.error(import_picocolors10.default.yellow(`Generator "${name}" already ejected at generators/${name}/`));
|
|
1247
|
+
process.exit(0);
|
|
1248
|
+
} catch {
|
|
1249
|
+
}
|
|
1250
|
+
const confirm3 = await p3.confirm({
|
|
1251
|
+
message: `Eject @ryndesign/generator-${name} to generators/${name}/?`,
|
|
1252
|
+
initialValue: true
|
|
1253
|
+
});
|
|
1254
|
+
if (p3.isCancel(confirm3) || !confirm3) {
|
|
1255
|
+
p3.cancel("Operation cancelled.");
|
|
1256
|
+
process.exit(0);
|
|
1257
|
+
}
|
|
1258
|
+
const s = p3.spinner();
|
|
1259
|
+
s.start(`Ejecting generator-${name}...`);
|
|
1260
|
+
try {
|
|
1261
|
+
const pkgPath = require.resolve(`@ryndesign/generator-${name}/package.json`, {
|
|
1262
|
+
paths: [cwd]
|
|
1263
|
+
});
|
|
1264
|
+
const pkgDir = import_node_path7.default.dirname(pkgPath);
|
|
1265
|
+
const srcDir = import_node_path7.default.join(pkgDir, "src");
|
|
1266
|
+
let sourceDir;
|
|
1267
|
+
try {
|
|
1268
|
+
await import_promises7.default.access(srcDir);
|
|
1269
|
+
sourceDir = srcDir;
|
|
1270
|
+
} catch {
|
|
1271
|
+
sourceDir = import_node_path7.default.join(pkgDir, "dist");
|
|
1272
|
+
}
|
|
1273
|
+
await import_promises7.default.mkdir(destDir, { recursive: true });
|
|
1274
|
+
await copyDir(sourceDir, destDir);
|
|
1275
|
+
s.stop(`Generator ejected!`);
|
|
1276
|
+
p3.note(
|
|
1277
|
+
[
|
|
1278
|
+
`Files copied to: ${import_picocolors10.default.green(`generators/${name}/`)}`,
|
|
1279
|
+
"",
|
|
1280
|
+
"Update your ryndesign.config.ts:",
|
|
1281
|
+
import_picocolors10.default.gray(` import customGenerator from './generators/${name}/index.js';`),
|
|
1282
|
+
"",
|
|
1283
|
+
"Replace the original generator with your custom one."
|
|
1284
|
+
].join("\n"),
|
|
1285
|
+
"Next steps"
|
|
1286
|
+
);
|
|
1287
|
+
} catch (err) {
|
|
1288
|
+
s.stop("Eject failed");
|
|
1289
|
+
console.error(import_picocolors10.default.red(`Error: ${err.message}`));
|
|
1290
|
+
s.start("Creating skeleton generator...");
|
|
1291
|
+
await createSkeletonGenerator(destDir, name);
|
|
1292
|
+
s.stop("Skeleton generator created!");
|
|
1293
|
+
p3.note(
|
|
1294
|
+
[
|
|
1295
|
+
`Skeleton created at: ${import_picocolors10.default.green(`generators/${name}/`)}`,
|
|
1296
|
+
"",
|
|
1297
|
+
"Customize the generator files and update your config."
|
|
1298
|
+
].join("\n"),
|
|
1299
|
+
"Next steps"
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
p3.outro(import_picocolors10.default.green("Done!"));
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
});
|
|
1307
|
+
|
|
1308
|
+
// src/bin.ts
|
|
1309
|
+
var import_citty12 = require("citty");
|
|
1310
|
+
|
|
1311
|
+
// src/commands/main.ts
|
|
1312
|
+
var import_citty11 = require("citty");
|
|
1313
|
+
var main = (0, import_citty11.defineCommand)({
|
|
1314
|
+
meta: {
|
|
1315
|
+
name: "ryndesign",
|
|
1316
|
+
version: "0.1.0",
|
|
1317
|
+
description: "Multi-platform design system generator"
|
|
1318
|
+
},
|
|
1319
|
+
subCommands: {
|
|
1320
|
+
init: () => Promise.resolve().then(() => (init_init(), init_exports)).then((m) => m.default),
|
|
1321
|
+
generate: () => Promise.resolve().then(() => (init_generate(), generate_exports)).then((m) => m.default),
|
|
1322
|
+
validate: () => Promise.resolve().then(() => (init_validate(), validate_exports)).then((m) => m.default),
|
|
1323
|
+
preview: () => Promise.resolve().then(() => (init_preview(), preview_exports)).then((m) => m.default),
|
|
1324
|
+
add: () => Promise.resolve().then(() => (init_add(), add_exports)).then((m) => m.default),
|
|
1325
|
+
figma: () => Promise.resolve().then(() => (init_figma(), figma_exports)).then((m) => m.default),
|
|
1326
|
+
eject: () => Promise.resolve().then(() => (init_eject(), eject_exports)).then((m) => m.default)
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
// src/bin.ts
|
|
1331
|
+
(0, import_citty12.runMain)(main);
|
|
1332
|
+
//# sourceMappingURL=bin.cjs.map
|