@takazudo/zdtp 0.4.4 → 0.4.5

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.
@@ -0,0 +1,421 @@
1
+ import { promises as y, readFileSync as I } from "node:fs";
2
+ import { relative as T, isAbsolute as q, sep as L, resolve as _, dirname as j, join as x } from "node:path";
3
+ import { randomBytes as A } from "node:crypto";
4
+ import { r as D } from "./route-tokens-to-files-1DvmWBdj.js";
5
+ const b = /* @__PURE__ */ new Map();
6
+ async function B(t, r) {
7
+ const e = (b.get(t) ?? Promise.resolve()).then(r, r), o = e.then(
8
+ () => {
9
+ },
10
+ () => {
11
+ }
12
+ );
13
+ b.set(t, o);
14
+ try {
15
+ return await e;
16
+ } finally {
17
+ b.get(t) === o && b.delete(t);
18
+ }
19
+ }
20
+ function Z(t) {
21
+ return t.replace(/[\r\n\\;{}]/g, "");
22
+ }
23
+ const H = /^--[a-zA-Z0-9_-]+$/;
24
+ function U(t) {
25
+ return typeof t == "string" && H.test(t);
26
+ }
27
+ function G(t, r) {
28
+ if (!r.endsWith(".css")) return !1;
29
+ const n = T(t, r);
30
+ return !(n === "" || n === "." || q(n) || n === ".." || n.startsWith(`..${L}`) || n.startsWith("../"));
31
+ }
32
+ function K(t) {
33
+ const r = {};
34
+ for (const [n, e] of Object.entries(t)) {
35
+ if (!U(n))
36
+ return { error: `Invalid cssVar name: ${JSON.stringify(n)}` };
37
+ if (typeof e != "string")
38
+ return { error: `Value for ${n} must be a string` };
39
+ r[n] = Z(e);
40
+ }
41
+ return { sanitized: r };
42
+ }
43
+ class F extends Error {
44
+ constructor(r = 'No top-level ":root { ... }" or "@theme { ... }" block found in source.') {
45
+ super(r), this.name = "NoTokenBlockError", Object.setPrototypeOf(this, F.prototype);
46
+ }
47
+ }
48
+ function E(t, r, n) {
49
+ const e = t.length, o = r.length, s = r[0];
50
+ let i = 0, f = 0;
51
+ for (; i < e; ) {
52
+ const d = t[i];
53
+ if (d === "/" && t[i + 1] === "*") {
54
+ const c = t.indexOf("*/", i + 2);
55
+ if (c === -1) return null;
56
+ i = c + 2;
57
+ continue;
58
+ }
59
+ if (d === '"' || d === "'") {
60
+ const c = d;
61
+ for (i++; i < e && t[i] !== c; )
62
+ t[i] === "\\" && i + 1 < e && i++, i++;
63
+ i++;
64
+ continue;
65
+ }
66
+ if (d === "{") {
67
+ f++, i++;
68
+ continue;
69
+ }
70
+ if (d === "}") {
71
+ f > 0 && f--, i++;
72
+ continue;
73
+ }
74
+ if (f === 0 && d === s && t.startsWith(r, i)) {
75
+ const c = i + o, p = t[c] ?? "";
76
+ if (!S(p)) {
77
+ const k = n ? X(t, c) : Q(t, c);
78
+ if (k !== -1) {
79
+ const g = k + 1, l = Y(t, g);
80
+ return l !== -1 ? { contentStart: g, contentEnd: l } : null;
81
+ }
82
+ }
83
+ }
84
+ i++;
85
+ }
86
+ return null;
87
+ }
88
+ function C(t) {
89
+ return E(t, ":root", !1);
90
+ }
91
+ function N(t) {
92
+ return E(t, "@theme", !0);
93
+ }
94
+ function S(t) {
95
+ return /[A-Za-z0-9_-]/.test(t);
96
+ }
97
+ function Q(t, r) {
98
+ const n = t.length;
99
+ let e = r;
100
+ for (; e < n; ) {
101
+ const o = t[e];
102
+ if (o === " " || o === " " || o === `
103
+ ` || o === "\r" || o === "\f") {
104
+ e++;
105
+ continue;
106
+ }
107
+ if (o === "/" && t[e + 1] === "*") {
108
+ const s = t.indexOf("*/", e + 2);
109
+ if (s === -1) return -1;
110
+ e = s + 2;
111
+ continue;
112
+ }
113
+ return o === "{" ? e : -1;
114
+ }
115
+ return -1;
116
+ }
117
+ function X(t, r) {
118
+ const n = t.length;
119
+ let e = r;
120
+ for (; e < n; ) {
121
+ const o = t[e];
122
+ if (o === " " || o === " " || o === `
123
+ ` || o === "\r" || o === "\f") {
124
+ e++;
125
+ continue;
126
+ }
127
+ if (o === "/" && t[e + 1] === "*") {
128
+ const s = t.indexOf("*/", e + 2);
129
+ if (s === -1) return -1;
130
+ e = s + 2;
131
+ continue;
132
+ }
133
+ if (o === "{") return e;
134
+ if (S(o)) {
135
+ for (e++; e < n && S(t[e]); ) e++;
136
+ continue;
137
+ }
138
+ return -1;
139
+ }
140
+ return -1;
141
+ }
142
+ function Y(t, r) {
143
+ const n = t.length;
144
+ let e = r, o = 1;
145
+ for (; e < n; ) {
146
+ const s = t[e];
147
+ if (s === "/" && t[e + 1] === "*") {
148
+ const i = t.indexOf("*/", e + 2);
149
+ if (i === -1) return -1;
150
+ e = i + 2;
151
+ continue;
152
+ }
153
+ if (s === '"' || s === "'") {
154
+ const i = s;
155
+ for (e++; e < n && t[e] !== i; )
156
+ t[e] === "\\" && e + 1 < n && e++, e++;
157
+ e++;
158
+ continue;
159
+ }
160
+ if (s === "{") {
161
+ o++, e++;
162
+ continue;
163
+ }
164
+ if (s === "}") {
165
+ if (o--, o === 0) return e;
166
+ e++;
167
+ continue;
168
+ }
169
+ e++;
170
+ }
171
+ return -1;
172
+ }
173
+ function tt(t) {
174
+ return t.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
175
+ }
176
+ function V(t) {
177
+ return t.replace(/\/\*[\s\S]*?\*\//g, (r) => " ".repeat(r.length));
178
+ }
179
+ function M(t) {
180
+ const r = t.startsWith("--") ? t.slice(2) : t, n = tt(r);
181
+ return new RegExp("(?<![\\w-])(--" + n + ":)(\\s*)([\\s\\S]+?);");
182
+ }
183
+ function R(t, r) {
184
+ return M(r).test(V(t));
185
+ }
186
+ function P(t, r, n) {
187
+ const e = M(r), o = V(t), s = e.exec(o);
188
+ if (!s) return { content: t, status: "unknown" };
189
+ const [i, f, d] = s, c = s.index, p = c + i.length, k = c + f.length + d.length, g = p - 1, u = t.slice(k, g).trim(), v = n.trim();
190
+ return u === v ? { content: t, status: "unchanged" } : { content: t.slice(0, c) + f + d + n + ";" + t.slice(p), status: "changed" };
191
+ }
192
+ function et(t, r) {
193
+ const n = Object.keys(r), e = C(t), o = N(t);
194
+ if (!e && !o)
195
+ return {
196
+ updated: t,
197
+ changed: [],
198
+ unchanged: [],
199
+ unknown: [...n],
200
+ unknownOutsideBlock: n.filter((l) => R(t, l))
201
+ };
202
+ let s = e ? t.slice(e.contentStart, e.contentEnd) : null, i = o ? t.slice(o.contentStart, o.contentEnd) : null;
203
+ const f = [], d = [], c = [];
204
+ for (const l of n) {
205
+ if (s !== null) {
206
+ const u = P(s, l, r[l]);
207
+ if (u.status !== "unknown") {
208
+ s = u.content, u.status === "changed" ? f.push(l) : d.push(l);
209
+ continue;
210
+ }
211
+ }
212
+ if (i !== null) {
213
+ const u = P(i, l, r[l]);
214
+ if (u.status !== "unknown") {
215
+ i = u.content, u.status === "changed" ? f.push(l) : d.push(l);
216
+ continue;
217
+ }
218
+ }
219
+ c.push(l);
220
+ }
221
+ const p = [];
222
+ e && s !== null && p.push({ start: e.contentStart, end: e.contentEnd, content: s }), o && i !== null && p.push({
223
+ start: o.contentStart,
224
+ end: o.contentEnd,
225
+ content: i
226
+ }), p.sort((l, u) => u.start - l.start);
227
+ let k = t;
228
+ for (const l of p)
229
+ k = k.slice(0, l.start) + l.content + k.slice(l.end);
230
+ const g = c.filter((l) => R(t, l));
231
+ return { updated: k, changed: f, unchanged: d, unknown: c, unknownOutsideBlock: g };
232
+ }
233
+ function nt(t, r) {
234
+ if (!rt(t))
235
+ throw new F();
236
+ return et(t, r);
237
+ }
238
+ function rt(t) {
239
+ return C(t) !== null || N(t) !== null;
240
+ }
241
+ function h(t, r = 200) {
242
+ return new Response(JSON.stringify(t), {
243
+ status: r,
244
+ headers: { "Content-Type": "application/json" }
245
+ });
246
+ }
247
+ async function ot(t, r, n) {
248
+ const e = await y.readFile(t, "utf-8"), o = nt(e, n);
249
+ return {
250
+ absPath: t,
251
+ relPath: r,
252
+ original: e,
253
+ updated: o.updated,
254
+ changed: o.changed,
255
+ unchanged: o.unchanged,
256
+ unknown: o.unknown,
257
+ unknownOutsideBlock: o.unknownOutsideBlock
258
+ };
259
+ }
260
+ async function it(t) {
261
+ if (t.changed.length !== 0)
262
+ return B(t.absPath, async () => {
263
+ const r = j(t.absPath), n = x(r, `.tmp-${A(8).toString("hex")}.css`);
264
+ try {
265
+ await y.writeFile(n, t.updated, "utf-8"), await y.rename(n, t.absPath);
266
+ } catch (e) {
267
+ try {
268
+ await y.unlink(n);
269
+ } catch {
270
+ }
271
+ throw e;
272
+ }
273
+ });
274
+ }
275
+ async function st(t) {
276
+ return B(t.absPath, async () => {
277
+ const r = j(t.absPath), n = x(r, `.tmp-${A(8).toString("hex")}.css`);
278
+ try {
279
+ return await y.writeFile(n, t.original, "utf-8"), await y.rename(n, t.absPath), { ok: !0 };
280
+ } catch (e) {
281
+ console.error("[design-token-panel/server] Restore failed for", t.relPath, e);
282
+ try {
283
+ await y.unlink(n);
284
+ } catch {
285
+ }
286
+ return { ok: !1, error: e };
287
+ }
288
+ });
289
+ }
290
+ function dt(t) {
291
+ const { rootDir: r, writeRoot: n, routing: e } = t;
292
+ return async function(s) {
293
+ let i;
294
+ try {
295
+ i = await s.json();
296
+ } catch {
297
+ return h({ ok: !1, error: "Invalid JSON in request body" }, 400);
298
+ }
299
+ if (typeof i != "object" || i === null || Array.isArray(i))
300
+ return h({ ok: !1, error: "Request body must be a JSON object" }, 400);
301
+ const { tokens: f } = i;
302
+ if (typeof f != "object" || f === null || Array.isArray(f))
303
+ return h({ ok: !1, error: "tokens must be a JSON object" }, 400);
304
+ if (Object.entries(f).length === 0)
305
+ return h({ ok: !1, error: "tokens must contain at least one entry" }, 400);
306
+ const { sanitized: c, error: p } = K(f);
307
+ if (p || !c)
308
+ return h({ ok: !1, error: p ?? "Invalid tokens" }, 400);
309
+ const { groups: k, rejected: g } = D(c, e);
310
+ if (g.length > 0)
311
+ return h({ ok: !1, error: "Unsupported cssVar prefix", rejected: g }, 400);
312
+ if (k.length === 0)
313
+ return h({ ok: !1, error: "No routable tokens supplied" }, 400);
314
+ const l = [];
315
+ for (const a of k) {
316
+ const m = _(r, a.relativePath);
317
+ if (!G(n, m))
318
+ return h({ ok: !1, error: `Path not allowed: ${a.relativePath}` }, 400);
319
+ l.push({ absPath: m, relPath: a.relativePath, groupTokens: a.tokens });
320
+ }
321
+ const u = [];
322
+ for (const { absPath: a, relPath: m, groupTokens: O } of l)
323
+ try {
324
+ u.push(await ot(a, m, O));
325
+ } catch (w) {
326
+ return w instanceof F ? (console.error("[design-token-panel/server] No :root or @theme block in", m), h(
327
+ {
328
+ ok: !1,
329
+ error: `No top-level :root { ... } or @theme { ... } block in ${m}`
330
+ },
331
+ 409
332
+ )) : (console.error(`[design-token-panel/server] Error computing ${m}:`, w), h({ ok: !1, error: "Failed to read or parse source file" }, 500));
333
+ }
334
+ const v = [];
335
+ for (const a of u)
336
+ try {
337
+ await it(a), v.push(a);
338
+ } catch (m) {
339
+ console.error(`[design-token-panel/server] Write failed for ${a.relPath}:`, m);
340
+ const O = [];
341
+ for (let w = v.length - 1; w >= 0; w--)
342
+ (await st(v[w])).ok || O.push(v[w].relPath);
343
+ return O.length > 0 ? h(
344
+ {
345
+ ok: !1,
346
+ error: `Failed to write file ${a.relPath}; rollback also failed for ${O.length} file(s) — disk state is inconsistent. Inspect the listed files manually.`,
347
+ failedFile: a.relPath,
348
+ restoreFailures: O
349
+ },
350
+ 500
351
+ ) : h(
352
+ {
353
+ ok: !1,
354
+ error: `Failed to write file ${a.relPath}; previously-written files were restored.`,
355
+ failedFile: a.relPath
356
+ },
357
+ 500
358
+ );
359
+ }
360
+ const $ = u.flatMap((a) => a.unknown), J = u.flatMap((a) => a.unchanged), W = u.flatMap((a) => a.unknownOutsideBlock), z = u.map((a) => ({
361
+ file: a.relPath.startsWith("/") ? T(r, a.relPath) : a.relPath,
362
+ changed: a.changed,
363
+ unchanged: a.unchanged,
364
+ unknown: a.unknown,
365
+ unknownOutsideBlock: a.unknownOutsideBlock
366
+ }));
367
+ return h({
368
+ ok: !0,
369
+ updated: z,
370
+ unknownCssVars: $,
371
+ unchangedCssVars: J,
372
+ unknownOutsideBlockCssVars: W
373
+ });
374
+ };
375
+ }
376
+ function ht(t) {
377
+ let r;
378
+ try {
379
+ r = I(t, "utf-8");
380
+ } catch (s) {
381
+ throw new Error(
382
+ `[design-token-panel] loadRoutingFromFile: cannot read file at ${t}
383
+ Cause: ${s.message}`
384
+ );
385
+ }
386
+ let n;
387
+ try {
388
+ n = JSON.parse(r);
389
+ } catch (s) {
390
+ throw new Error(
391
+ `[design-token-panel] loadRoutingFromFile: invalid JSON in ${t}
392
+ Cause: ${s.message}`
393
+ );
394
+ }
395
+ if (n === null || typeof n != "object" || Array.isArray(n))
396
+ throw new Error(
397
+ `[design-token-panel] loadRoutingFromFile: root value must be a plain object, got ${n === null ? "null" : Array.isArray(n) ? "array" : typeof n} (in ${t})`
398
+ );
399
+ const e = n, o = Object.keys(e);
400
+ if (o.length === 0)
401
+ throw new Error(
402
+ `[design-token-panel] loadRoutingFromFile: routing map must not be empty (in ${t})`
403
+ );
404
+ for (const s of o) {
405
+ const i = e[s];
406
+ if (typeof i != "string" || i.trim() === "")
407
+ throw new Error(
408
+ `[design-token-panel] loadRoutingFromFile: every value must be a non-empty string, but key "${s}" has value ${JSON.stringify(i)} (in ${t})`
409
+ );
410
+ }
411
+ return e;
412
+ }
413
+ export {
414
+ H as C,
415
+ U as a,
416
+ dt as c,
417
+ G as i,
418
+ ht as l,
419
+ B as s,
420
+ K as v
421
+ };