@ryndesign/preview 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/dist/index.cjs ADDED
@@ -0,0 +1,691 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/utils.js
34
+ var init_utils = __esm({
35
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/utils.js"() {
36
+ "use strict";
37
+ }
38
+ });
39
+
40
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/composable-filters.js
41
+ var init_composable_filters = __esm({
42
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/composable-filters.js"() {
43
+ "use strict";
44
+ init_utils();
45
+ }
46
+ });
47
+
48
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/filter-vite-plugins.js
49
+ var init_filter_vite_plugins = __esm({
50
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/filter-vite-plugins.js"() {
51
+ "use strict";
52
+ }
53
+ });
54
+
55
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/simple-filters.js
56
+ function exactRegex(str, flags) {
57
+ return new RegExp(`^${escapeRegex(str)}$`, flags);
58
+ }
59
+ function escapeRegex(str) {
60
+ return str.replace(escapeRegexRE, "\\$&");
61
+ }
62
+ function makeIdFiltersToMatchWithQuery(input) {
63
+ if (!Array.isArray(input)) {
64
+ return makeIdFilterToMatchWithQuery(
65
+ // Array.isArray cannot narrow the type
66
+ // https://github.com/microsoft/TypeScript/issues/17002
67
+ input
68
+ );
69
+ }
70
+ return input.map((i) => makeIdFilterToMatchWithQuery(i));
71
+ }
72
+ function makeIdFilterToMatchWithQuery(input) {
73
+ if (typeof input === "string") {
74
+ return `${input}{?*,}`;
75
+ }
76
+ return makeRegexIdFilterToMatchWithQuery(input);
77
+ }
78
+ function makeRegexIdFilterToMatchWithQuery(input) {
79
+ return new RegExp(
80
+ // replace `$` with `(?:\?.*)?$` (ignore `\$`)
81
+ input.source.replace(/(?<!\\)\$/g, "(?:\\?.*)?$"),
82
+ input.flags
83
+ );
84
+ }
85
+ var escapeRegexRE;
86
+ var init_simple_filters = __esm({
87
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/simple-filters.js"() {
88
+ "use strict";
89
+ escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
90
+ }
91
+ });
92
+
93
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/index.js
94
+ var init_filter = __esm({
95
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/filter/index.js"() {
96
+ "use strict";
97
+ init_composable_filters();
98
+ init_filter_vite_plugins();
99
+ init_simple_filters();
100
+ }
101
+ });
102
+
103
+ // ../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/index.js
104
+ var init_dist = __esm({
105
+ "../../node_modules/.pnpm/@rolldown+pluginutils@1.0.0-rc.7/node_modules/@rolldown/pluginutils/dist/index.js"() {
106
+ "use strict";
107
+ init_filter();
108
+ }
109
+ });
110
+
111
+ // ../../node_modules/.pnpm/@vitejs+plugin-react@6.0.1_vite@6.4.1_@types+node@25.5.0_jiti@2.6.1_/node_modules/@vitejs/plugin-react/dist/index.js
112
+ var dist_exports = {};
113
+ __export(dist_exports, {
114
+ default: () => viteReact,
115
+ "module.exports": () => viteReactForCjs,
116
+ reactCompilerPreset: () => reactCompilerPreset
117
+ });
118
+ function virtualPreamblePlugin({ name, isEnabled }) {
119
+ return {
120
+ name: "vite:react-virtual-preamble",
121
+ resolveId: {
122
+ order: "pre",
123
+ filter: { id: exactRegex(name) },
124
+ handler(source) {
125
+ if (source === name) return "\0" + source;
126
+ }
127
+ },
128
+ load: {
129
+ filter: { id: exactRegex("\0" + name) },
130
+ handler(id) {
131
+ if (id === "\0" + name) {
132
+ if (isEnabled()) return preambleCode.replace("__BASE__", "/");
133
+ return "";
134
+ }
135
+ }
136
+ }
137
+ };
138
+ }
139
+ function viteReact(opts = {}) {
140
+ const include = opts.include ?? defaultIncludeRE;
141
+ const exclude = opts.exclude ?? defaultExcludeRE;
142
+ const jsxImportSource = opts.jsxImportSource ?? "react";
143
+ const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`;
144
+ const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`;
145
+ let runningInVite = false;
146
+ let isProduction = true;
147
+ let skipFastRefresh = true;
148
+ let base;
149
+ let isBundledDev = false;
150
+ const viteBabel = {
151
+ name: "vite:react-babel",
152
+ enforce: "pre",
153
+ config(_userConfig, { command }) {
154
+ if (opts.jsxRuntime === "classic") return { oxc: {
155
+ jsx: {
156
+ runtime: "classic",
157
+ refresh: command === "serve"
158
+ },
159
+ jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
160
+ jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
161
+ } };
162
+ else return {
163
+ oxc: {
164
+ jsx: {
165
+ runtime: "automatic",
166
+ importSource: opts.jsxImportSource,
167
+ refresh: command === "serve"
168
+ },
169
+ jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
170
+ jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
171
+ },
172
+ optimizeDeps: { rolldownOptions: { transform: { jsx: { runtime: "automatic" } } } }
173
+ };
174
+ },
175
+ configResolved(config) {
176
+ runningInVite = true;
177
+ base = config.base;
178
+ if (config.experimental.bundledDev) isBundledDev = true;
179
+ isProduction = config.isProduction;
180
+ skipFastRefresh = isProduction || config.command === "build" || config.server.hmr === false;
181
+ },
182
+ options(options) {
183
+ if (!runningInVite) {
184
+ options.transform ??= {};
185
+ options.transform.jsx = {
186
+ runtime: opts.jsxRuntime,
187
+ importSource: opts.jsxImportSource
188
+ };
189
+ return options;
190
+ }
191
+ }
192
+ };
193
+ const viteRefreshWrapper = {
194
+ name: "vite:react:refresh-wrapper",
195
+ apply: "serve",
196
+ async applyToEnvironment(env) {
197
+ if (env.config.consumer !== "client" || skipFastRefresh) return false;
198
+ return (0, import_internal.reactRefreshWrapperPlugin)({
199
+ cwd: process.cwd(),
200
+ include: makeIdFiltersToMatchWithQuery(include),
201
+ exclude: makeIdFiltersToMatchWithQuery(exclude),
202
+ jsxImportSource,
203
+ reactRefreshHost: opts.reactRefreshHost ?? ""
204
+ });
205
+ }
206
+ };
207
+ const viteConfigPost = {
208
+ name: "vite:react:config-post",
209
+ enforce: "post",
210
+ config(userConfig) {
211
+ if (userConfig.server?.hmr === false) return { oxc: { jsx: { refresh: false } } };
212
+ }
213
+ };
214
+ const viteReactRefreshBundledDevMode = {
215
+ name: "vite:react-refresh-fbm",
216
+ enforce: "pre",
217
+ transformIndexHtml: {
218
+ handler() {
219
+ if (!skipFastRefresh && isBundledDev) return [{
220
+ tag: "script",
221
+ attrs: { type: "module" },
222
+ children: getPreambleCode(base)
223
+ }];
224
+ },
225
+ order: "pre"
226
+ }
227
+ };
228
+ const dependencies = [
229
+ "react",
230
+ "react-dom",
231
+ jsxImportDevRuntime,
232
+ jsxImportRuntime
233
+ ];
234
+ return [
235
+ viteBabel,
236
+ viteRefreshWrapper,
237
+ viteConfigPost,
238
+ viteReactRefreshBundledDevMode,
239
+ {
240
+ name: "vite:react-refresh",
241
+ enforce: "pre",
242
+ config: (userConfig) => ({
243
+ build: silenceUseClientWarning(userConfig),
244
+ optimizeDeps: { include: dependencies }
245
+ }),
246
+ resolveId: {
247
+ filter: { id: exactRegex(runtimePublicPath) },
248
+ handler(id) {
249
+ if (id === "/@react-refresh") return id;
250
+ }
251
+ },
252
+ load: {
253
+ filter: { id: exactRegex(runtimePublicPath) },
254
+ handler(id) {
255
+ if (id === "/@react-refresh") return (0, import_node_fs.readFileSync)(refreshRuntimePath, "utf-8").replace(/__README_URL__/g, "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react");
256
+ }
257
+ },
258
+ transformIndexHtml() {
259
+ if (!skipFastRefresh && !isBundledDev) return [{
260
+ tag: "script",
261
+ attrs: { type: "module" },
262
+ children: getPreambleCode(base)
263
+ }];
264
+ }
265
+ },
266
+ virtualPreamblePlugin({
267
+ name: "@vitejs/plugin-react/preamble",
268
+ isEnabled: () => !skipFastRefresh && !isBundledDev
269
+ })
270
+ ];
271
+ }
272
+ function viteReactForCjs(options) {
273
+ return viteReact.call(this, options);
274
+ }
275
+ var import_node_fs, import_node_path2, import_node_url, import_internal, import_meta, runtimePublicPath, preambleCode, getPreambleCode, silenceUseClientWarning, reactCompilerPreset, refreshRuntimePath, defaultIncludeRE, defaultExcludeRE;
276
+ var init_dist2 = __esm({
277
+ "../../node_modules/.pnpm/@vitejs+plugin-react@6.0.1_vite@6.4.1_@types+node@25.5.0_jiti@2.6.1_/node_modules/@vitejs/plugin-react/dist/index.js"() {
278
+ "use strict";
279
+ import_node_fs = require("fs");
280
+ import_node_path2 = require("path");
281
+ import_node_url = require("url");
282
+ init_dist();
283
+ import_internal = require("vite/internal");
284
+ import_meta = {};
285
+ runtimePublicPath = "/@react-refresh";
286
+ preambleCode = `import { injectIntoGlobalHook } from "__BASE__${runtimePublicPath.slice(1)}";
287
+ injectIntoGlobalHook(window);
288
+ window.$RefreshReg$ = () => {};
289
+ window.$RefreshSig$ = () => (type) => type;`;
290
+ getPreambleCode = (base) => preambleCode.replace("__BASE__", base);
291
+ silenceUseClientWarning = (userConfig) => ({ rollupOptions: { onwarn(warning, defaultHandler) {
292
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE" && (warning.message.includes("use client") || warning.message.includes("use server"))) return;
293
+ if (warning.code === "SOURCEMAP_ERROR" && warning.message.includes("resolve original location") && warning.pos === 0) return;
294
+ if (userConfig.build?.rollupOptions?.onwarn) userConfig.build.rollupOptions.onwarn(warning, defaultHandler);
295
+ else defaultHandler(warning);
296
+ } } });
297
+ reactCompilerPreset = (options = {}) => ({
298
+ preset: () => ({ plugins: [["babel-plugin-react-compiler", options]] }),
299
+ rolldown: {
300
+ filter: { code: options.compilationMode === "annotation" ? /['"]use memo['"]/ : /\b[A-Z]|\buse/ },
301
+ applyToEnvironmentHook: (env) => env.config.consumer === "client",
302
+ optimizeDeps: { include: options.target === "17" || options.target === "18" ? ["react-compiler-runtime"] : ["react/compiler-runtime"] }
303
+ }
304
+ });
305
+ refreshRuntimePath = (0, import_node_path2.join)((0, import_node_path2.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "refresh-runtime.js");
306
+ defaultIncludeRE = /\.[tj]sx?$/;
307
+ defaultExcludeRE = /\/node_modules\//;
308
+ viteReact.preambleCode = preambleCode;
309
+ Object.assign(viteReactForCjs, {
310
+ default: viteReactForCjs,
311
+ reactCompilerPreset
312
+ });
313
+ }
314
+ });
315
+
316
+ // src/index.ts
317
+ var index_exports = {};
318
+ __export(index_exports, {
319
+ startPreviewServer: () => startPreviewServer
320
+ });
321
+ module.exports = __toCommonJS(index_exports);
322
+
323
+ // src/server/index.ts
324
+ var import_vite = require("vite");
325
+ var import_ws = require("ws");
326
+ var import_node_http = __toESM(require("http"), 1);
327
+ var import_node_path3 = __toESM(require("path"), 1);
328
+
329
+ // src/server/api-routes.ts
330
+ function setupApiRoutes(builder) {
331
+ return (req, res) => {
332
+ const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
333
+ const pathname = url.pathname;
334
+ res.setHeader("Access-Control-Allow-Origin", "*");
335
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
336
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
337
+ if (req.method === "OPTIONS") {
338
+ res.writeHead(204);
339
+ res.end();
340
+ return;
341
+ }
342
+ try {
343
+ if (pathname === "/api/tokens" && req.method === "GET") {
344
+ json(res, builder.getTokenSet());
345
+ } else if (pathname === "/api/themes" && req.method === "GET") {
346
+ json(res, builder.getThemes());
347
+ } else if (pathname === "/api/components" && req.method === "GET") {
348
+ json(res, builder.getComponents());
349
+ } else if (pathname === "/api/snippets" && req.method === "GET") {
350
+ const platform = url.searchParams.get("platform") ?? "react";
351
+ const component = url.searchParams.get("component") ?? void 0;
352
+ const type = url.searchParams.get("type") ?? void 0;
353
+ builder.generateSnippets(platform, component, type).then((code) => {
354
+ json(res, { code });
355
+ }).catch((err) => {
356
+ res.writeHead(500);
357
+ json(res, { error: err.message });
358
+ });
359
+ return;
360
+ } else if (pathname === "/api/tokens" && req.method === "PUT") {
361
+ let body = "";
362
+ req.on("data", (chunk) => {
363
+ body += chunk;
364
+ });
365
+ req.on("end", async () => {
366
+ const { path: path3, value, theme } = JSON.parse(body);
367
+ await builder.updateToken(path3, value, theme);
368
+ json(res, { success: true });
369
+ });
370
+ } else if (pathname === "/api/generated" && req.method === "GET") {
371
+ const platform = url.searchParams.get("platform");
372
+ json(res, builder.getGeneratedFiles(platform ?? void 0));
373
+ } else {
374
+ res.writeHead(404);
375
+ json(res, { error: "Not found" });
376
+ }
377
+ } catch (err) {
378
+ res.writeHead(500);
379
+ json(res, { error: err.message });
380
+ }
381
+ };
382
+ }
383
+ function json(res, data) {
384
+ if (!res.headersSent) {
385
+ res.setHeader("Content-Type", "application/json");
386
+ }
387
+ res.end(JSON.stringify(data));
388
+ }
389
+
390
+ // src/server/ws-handler.ts
391
+ function setupWsHandler(wss, builder) {
392
+ wss.on("connection", (ws) => {
393
+ console.log("Preview client connected");
394
+ ws.send(JSON.stringify({
395
+ type: "init",
396
+ tokenSet: builder.getTokenSet(),
397
+ themes: builder.getThemes(),
398
+ components: builder.getComponents()
399
+ }));
400
+ ws.on("message", async (data) => {
401
+ try {
402
+ const message = JSON.parse(data.toString());
403
+ switch (message.type) {
404
+ case "token-update": {
405
+ const update = message;
406
+ await builder.updateToken(update.path, update.value, update.theme);
407
+ broadcast(wss, {
408
+ type: "rebuild-complete",
409
+ changedTokens: [update.path],
410
+ timestamp: Date.now()
411
+ });
412
+ break;
413
+ }
414
+ case "theme-change": {
415
+ const themeMsg = message;
416
+ broadcast(wss, {
417
+ type: "theme-switched",
418
+ theme: themeMsg.theme,
419
+ tokens: builder.getThemeTokens(themeMsg.theme)
420
+ });
421
+ break;
422
+ }
423
+ case "request-state": {
424
+ ws.send(JSON.stringify({
425
+ type: "full-state",
426
+ tokenSet: builder.getTokenSet(),
427
+ themes: builder.getThemes(),
428
+ components: builder.getComponents()
429
+ }));
430
+ break;
431
+ }
432
+ }
433
+ } catch (err) {
434
+ ws.send(JSON.stringify({
435
+ type: "error",
436
+ message: err.message
437
+ }));
438
+ }
439
+ });
440
+ ws.on("close", () => {
441
+ console.log("Preview client disconnected");
442
+ });
443
+ });
444
+ }
445
+ function broadcast(wss, message) {
446
+ const data = JSON.stringify(message);
447
+ for (const client of wss.clients) {
448
+ if (client.readyState === 1) {
449
+ client.send(data);
450
+ }
451
+ }
452
+ }
453
+
454
+ // src/server/watcher.ts
455
+ var import_chokidar = require("chokidar");
456
+ function setupWatcher(builder, wss, cwd) {
457
+ const watcher = (0, import_chokidar.watch)(
458
+ ["tokens/**/*.tokens.json", "components/**/*.component.json"],
459
+ {
460
+ cwd,
461
+ ignoreInitial: true,
462
+ awaitWriteFinish: {
463
+ stabilityThreshold: 300,
464
+ pollInterval: 50
465
+ }
466
+ }
467
+ );
468
+ let debounceTimer = null;
469
+ const handleChange = (changedPath) => {
470
+ if (debounceTimer) clearTimeout(debounceTimer);
471
+ debounceTimer = setTimeout(async () => {
472
+ console.log(`File changed: ${changedPath}`);
473
+ try {
474
+ await builder.rebuild();
475
+ const data = JSON.stringify({
476
+ type: "rebuild-complete",
477
+ changedTokens: [],
478
+ timestamp: Date.now(),
479
+ tokenSet: builder.getTokenSet(),
480
+ components: builder.getComponents()
481
+ });
482
+ for (const client of wss.clients) {
483
+ if (client.readyState === 1) {
484
+ client.send(data);
485
+ }
486
+ }
487
+ } catch (err) {
488
+ console.error("Rebuild failed:", err.message);
489
+ }
490
+ }, 300);
491
+ };
492
+ watcher.on("change", handleChange);
493
+ watcher.on("add", handleChange);
494
+ watcher.on("unlink", handleChange);
495
+ }
496
+
497
+ // src/server/incremental-build.ts
498
+ var import_core = require("@ryndesign/core");
499
+ var import_promises = __toESM(require("fs/promises"), 1);
500
+ var import_node_path = __toESM(require("path"), 1);
501
+ var IncrementalBuilder = class {
502
+ tokenSet = null;
503
+ components = [];
504
+ generatedFiles = /* @__PURE__ */ new Map();
505
+ generators = [];
506
+ cwd;
507
+ configPath;
508
+ constructor(cwd, configPath) {
509
+ this.cwd = cwd;
510
+ this.configPath = configPath;
511
+ }
512
+ async initialBuild() {
513
+ await this.rebuild();
514
+ }
515
+ async rebuild() {
516
+ const configFile = this.configPath ?? "ryndesign.config.ts";
517
+ const tokens = ["tokens/**/*.tokens.json"];
518
+ const componentPatterns = ["components/**/*.component.json"];
519
+ let themes = void 0;
520
+ try {
521
+ const configPath = import_node_path.default.resolve(this.cwd, configFile);
522
+ const content = await import_promises.default.readFile(configPath, "utf-8");
523
+ if (content.includes("dark")) {
524
+ themes = {
525
+ default: "light",
526
+ dark: { file: import_node_path.default.resolve(this.cwd, "tokens/dark.tokens.json") }
527
+ };
528
+ }
529
+ } catch {
530
+ }
531
+ this.tokenSet = await (0, import_core.buildTokenSet)({
532
+ tokens,
533
+ basePath: this.cwd,
534
+ themes
535
+ });
536
+ try {
537
+ const componentDefs = await (0, import_core.loadComponents)(componentPatterns, this.cwd);
538
+ this.components = componentDefs.map((def) => (0, import_core.resolveComponent)(def, this.tokenSet));
539
+ } catch {
540
+ this.components = [];
541
+ }
542
+ }
543
+ getTokenSet() {
544
+ return this.tokenSet;
545
+ }
546
+ getThemes() {
547
+ if (!this.tokenSet) return {};
548
+ return {
549
+ default: this.tokenSet.themes.default,
550
+ available: Object.keys(this.tokenSet.themes.themes),
551
+ themes: this.tokenSet.themes.themes
552
+ };
553
+ }
554
+ getThemeTokens(theme) {
555
+ if (!this.tokenSet) return {};
556
+ const themeData = this.tokenSet.themes.themes[theme];
557
+ if (!themeData) return {};
558
+ return {
559
+ name: themeData.name,
560
+ tokens: themeData.tokens
561
+ };
562
+ }
563
+ getComponents() {
564
+ return this.components;
565
+ }
566
+ setGenerators(generators) {
567
+ this.generators = generators;
568
+ }
569
+ async generateSnippets(platform, componentName, type) {
570
+ if (!this.tokenSet) return "";
571
+ const generator = this.generators.find((g) => g.name === platform);
572
+ if (!generator) return `// Generator for "${platform}" not available`;
573
+ const { createGeneratorHelpers } = await import("@ryndesign/core");
574
+ const ctx = {
575
+ tokenSet: this.tokenSet,
576
+ config: { outDir: "generated" },
577
+ outputDir: import_node_path.default.resolve(this.cwd, "generated"),
578
+ helpers: createGeneratorHelpers(),
579
+ components: this.components
580
+ };
581
+ try {
582
+ if (type === "tokens") {
583
+ const files = await generator.generateTokens(ctx);
584
+ return files.map((f) => `// ${f.path}
585
+ ${f.content}`).join("\n\n");
586
+ }
587
+ if (componentName) {
588
+ const comp = this.components.find((c) => c.definition.name === componentName);
589
+ if (comp) {
590
+ const files = await generator.generateComponent(comp, ctx);
591
+ return files.map((f) => `// ${f.path}
592
+ ${f.content}`).join("\n\n");
593
+ }
594
+ return `// Component "${componentName}" not found`;
595
+ }
596
+ return "// Specify a component or type=tokens";
597
+ } catch (err) {
598
+ return `// Error: ${err.message}`;
599
+ }
600
+ }
601
+ getGeneratedFiles(platform) {
602
+ if (!platform) {
603
+ return Array.from(this.generatedFiles.values()).flat();
604
+ }
605
+ return this.generatedFiles.get(platform) ?? [];
606
+ }
607
+ async updateToken(tokenPath, value, theme) {
608
+ const filePath = theme ? import_node_path.default.resolve(this.cwd, `tokens/${theme}.tokens.json`) : import_node_path.default.resolve(this.cwd, "tokens/semantic.tokens.json");
609
+ try {
610
+ const content = await import_promises.default.readFile(filePath, "utf-8");
611
+ const tree = JSON.parse(content);
612
+ const parts = tokenPath.split(".");
613
+ let current = tree;
614
+ for (let i = 0; i < parts.length - 1; i++) {
615
+ if (!current[parts[i]]) current[parts[i]] = {};
616
+ current = current[parts[i]];
617
+ }
618
+ const lastKey = parts[parts.length - 1];
619
+ if (current[lastKey] && typeof current[lastKey] === "object" && "$value" in current[lastKey]) {
620
+ current[lastKey].$value = value;
621
+ } else {
622
+ current[lastKey] = { $type: "color", $value: value };
623
+ }
624
+ await import_promises.default.writeFile(filePath, JSON.stringify(tree, null, 2), "utf-8");
625
+ await this.rebuild();
626
+ } catch (err) {
627
+ console.error(`Failed to update token: ${err.message}`);
628
+ throw err;
629
+ }
630
+ }
631
+ };
632
+
633
+ // src/server/index.ts
634
+ async function startPreviewServer(options = {}) {
635
+ const port = options.port ?? 4400;
636
+ const cwd = process.cwd();
637
+ const builder = new IncrementalBuilder(cwd, options.configPath);
638
+ await builder.initialBuild();
639
+ const server = import_node_http.default.createServer();
640
+ const wss = new import_ws.WebSocketServer({ server });
641
+ setupWsHandler(wss, builder);
642
+ let reactPlugin;
643
+ try {
644
+ const mod = await Promise.resolve().then(() => (init_dist2(), dist_exports));
645
+ reactPlugin = (mod.default ?? mod)();
646
+ } catch {
647
+ }
648
+ const vite = await (0, import_vite.createServer)({
649
+ root: import_node_path3.default.resolve(__dirname, "../client"),
650
+ server: {
651
+ middlewareMode: true,
652
+ hmr: { server }
653
+ },
654
+ plugins: reactPlugin ? [reactPlugin] : [],
655
+ appType: "spa"
656
+ });
657
+ const apiHandler = setupApiRoutes(builder);
658
+ server.on("request", (req, res) => {
659
+ if (req.url?.startsWith("/api/")) {
660
+ apiHandler(req, res);
661
+ } else {
662
+ vite.middlewares(req, res);
663
+ }
664
+ });
665
+ setupWatcher(builder, wss, cwd);
666
+ server.listen(port, () => {
667
+ console.log(`
668
+ \u{1F3A8} RynDesign Preview`);
669
+ console.log(` \u279C Local: http://localhost:${port}/`);
670
+ console.log(` \u279C WS: ws://localhost:${port}/
671
+ `);
672
+ if (options.open) {
673
+ import("child_process").then((cp) => {
674
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
675
+ cp.exec(`${cmd} http://localhost:${port}/`);
676
+ }).catch(() => {
677
+ });
678
+ }
679
+ });
680
+ process.on("SIGINT", () => {
681
+ wss.close();
682
+ vite.close();
683
+ server.close();
684
+ process.exit(0);
685
+ });
686
+ }
687
+ // Annotate the CommonJS export names for ESM import in node:
688
+ 0 && (module.exports = {
689
+ startPreviewServer
690
+ });
691
+ //# sourceMappingURL=index.cjs.map