@polyxd/ds-kit 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dev.js ADDED
@@ -0,0 +1,373 @@
1
+ /**
2
+ * `polyxd dev`: a local preview for people who author Polyxd documents in their editor.
3
+ *
4
+ * npx polyxd dev the documents in this folder
5
+ * npx polyxd dev ./screens --port 4310 --theme material3 --data ./sample.json --open
6
+ * npx polyxd dev ./screens --pack ./ds-acme/manifest.json --verify
7
+ *
8
+ * It watches a folder for documents, renders the selected one with the real renderer in any
9
+ * built-in pack (or one of yours), light or dark, at phone, tablet and desktop widths, and shows
10
+ * beside it what the static check finds, the document, its data, and the actions it dispatches.
11
+ * Save a file and the surface reloads in place, keeping your selection and controls.
12
+ *
13
+ * Nothing but Node here: http, fs.watch, server-sent events, and the renderer's browser bundle
14
+ * from @polyxd/react/preview.
15
+ */
16
+ import { spawn } from "node:child_process";
17
+ import { existsSync, watch } from "node:fs";
18
+ import { mkdtemp, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
19
+ import { createServer } from "node:http";
20
+ import { tmpdir } from "node:os";
21
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
22
+ import { parseArgs } from "node:util";
23
+ import { fileURLToPath } from "node:url";
24
+ import { validateDocument } from "@polyxd/spec";
25
+ import { packCss } from "./dev-pack.js";
26
+ import { devPage } from "./dev-page.js";
27
+ const SKIP_DIRS = new Set(["node_modules", "dist", "build", "coverage"]);
28
+ const THEMES = ["material3", "carbon", "antd", "fluent", "shadcn", "bootstrap", "mantine", "radix", "polaris", "primer", "spectrum", "govuk", "chakra"];
29
+ const isDocument = (v) => !!v && typeof v === "object" && typeof v.specVersion === "string" && Array.isArray(v.components);
30
+ const posix = (p) => p.split(sep).join("/");
31
+ /** The static check: schema and structure, and every binding against the data the surface will show. */
32
+ export function checkDocument(document, data) {
33
+ const doc = data !== undefined ? { ...document, data } : document;
34
+ let issues;
35
+ try {
36
+ issues = validateDocument(doc, { missingData: "warning" }).issues;
37
+ }
38
+ catch (e) {
39
+ issues = [{ severity: "error", at: "/", message: `validator failed: ${e.message}` }];
40
+ }
41
+ return { errors: issues.filter((i) => i.severity === "error").length, warnings: issues.filter((i) => i.severity === "warning").length, issues };
42
+ }
43
+ async function* jsonFiles(dir, depth = 0) {
44
+ const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
45
+ for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
46
+ if (e.name.startsWith("."))
47
+ continue;
48
+ if (e.isDirectory()) {
49
+ if (!SKIP_DIRS.has(e.name) && depth < 4)
50
+ yield* jsonFiles(join(dir, e.name), depth + 1);
51
+ }
52
+ else if (e.name.endsWith(".json"))
53
+ yield join(dir, e.name);
54
+ }
55
+ }
56
+ /**
57
+ * Every document under `dir`: a JSON file with `specVersion` and `components`, or an intent-shaped
58
+ * file whose `document` has them. Data is the document's own, else `<name>.data.json` beside it,
59
+ * else `defaultData`. Everything else (packs, reports, registries, tsconfigs) is ignored.
60
+ */
61
+ export async function discoverDocuments(dir, options = {}) {
62
+ const documents = [];
63
+ const broken = [];
64
+ for await (const path of jsonFiles(dir)) {
65
+ if (path.endsWith(".data.json"))
66
+ continue;
67
+ const file = posix(relative(dir, path));
68
+ let raw;
69
+ try {
70
+ raw = JSON.parse(await readFile(path, "utf8"));
71
+ }
72
+ catch (e) {
73
+ broken.push({ file, message: e.message });
74
+ continue;
75
+ }
76
+ const kind = isDocument(raw) ? "document" : isDocument(raw?.document) ? "intent" : undefined;
77
+ if (!kind)
78
+ continue;
79
+ const document = kind === "intent" ? raw.document : raw;
80
+ let data = document.data;
81
+ let dataFrom = data !== undefined ? "embedded" : "none";
82
+ if (data === undefined) {
83
+ const sibling = path.replace(/\.json$/, ".data.json");
84
+ if (existsSync(sibling)) {
85
+ try {
86
+ data = JSON.parse(await readFile(sibling, "utf8"));
87
+ dataFrom = "sibling";
88
+ }
89
+ catch (e) {
90
+ broken.push({ file: posix(relative(dir, sibling)), message: e.message });
91
+ }
92
+ }
93
+ }
94
+ if (data === undefined && options.defaultData !== undefined) {
95
+ data = options.defaultData;
96
+ dataFrom = "default";
97
+ }
98
+ const surface = document.surface ?? {};
99
+ documents.push({
100
+ file,
101
+ id: String(surface.id ?? (kind === "intent" ? raw.id : "") ?? ""),
102
+ title: String(surface.title ?? raw.title ?? basename(file, ".json")),
103
+ kind,
104
+ origin: surface.origin,
105
+ pattern: surface.pattern,
106
+ dataFrom,
107
+ document,
108
+ data,
109
+ check: checkDocument(document, data),
110
+ });
111
+ }
112
+ return { documents, broken };
113
+ }
114
+ /** One line per document, the way the pack command reports. */
115
+ export function describe(d) {
116
+ const status = d.check.errors ? "error" : d.check.warnings ? "warn " : "ok ";
117
+ const counts = [d.check.errors ? `${d.check.errors} error${d.check.errors === 1 ? "" : "s"}` : "", d.check.warnings ? `${d.check.warnings} warning${d.check.warnings === 1 ? "" : "s"}` : ""].filter(Boolean).join(", ");
118
+ const what = [d.kind === "intent" ? "intent" : "document", d.origin, d.dataFrom === "none" ? "no data" : d.dataFrom === "embedded" ? "" : `data: ${d.dataFrom}`].filter(Boolean).join(" · ");
119
+ return ` ${status} ${d.file.padEnd(32)} ${d.title.slice(0, 28).padEnd(28)} ${what}${counts ? ` (${counts})` : ""}`;
120
+ }
121
+ /** Where the renderer's browser bundle lives, if @polyxd/react is installed with one. */
122
+ export function findBundle() {
123
+ try {
124
+ const js = fileURLToPath(import.meta.resolve("@polyxd/react/preview/polyxd.js"));
125
+ return existsSync(js) && existsSync(js.replace(/\.js$/, ".css")) ? dirname(js) : undefined;
126
+ }
127
+ catch {
128
+ return undefined;
129
+ }
130
+ }
131
+ /** The verifier's command line, if @polyxd/verifier is installed. */
132
+ export function findVerifier() {
133
+ try {
134
+ const cli = fileURLToPath(import.meta.resolve("@polyxd/verifier/dist/cli.js"));
135
+ return existsSync(cli) ? cli : undefined;
136
+ }
137
+ catch {
138
+ return undefined;
139
+ }
140
+ }
141
+ const meta = (d) => ({ file: d.file, id: d.id, title: d.title, kind: d.kind, origin: d.origin, pattern: d.pattern, dataFrom: d.dataFrom, check: { errors: d.check.errors, warnings: d.check.warnings } });
142
+ const json = (res, status, body) => {
143
+ res.writeHead(status, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store" });
144
+ res.end(JSON.stringify(body));
145
+ };
146
+ const text = (res, status, body, type = "text/plain") => {
147
+ res.writeHead(status, { "content-type": `${type}; charset=utf-8`, "cache-control": "no-store" });
148
+ res.end(body);
149
+ };
150
+ const sse = (res) => {
151
+ res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-store", connection: "keep-alive" });
152
+ res.write(": polyxd dev\n\n");
153
+ return (event, data) => res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
154
+ };
155
+ export async function createDevServer(options) {
156
+ const dir = resolve(options.dir);
157
+ const info = await stat(dir).catch(() => null);
158
+ if (!info?.isDirectory())
159
+ throw new Error(`${options.dir} is not a folder`);
160
+ const dataFile = options.data ? resolve(options.data) : undefined;
161
+ const readDefaultData = async () => (dataFile ? JSON.parse(await readFile(dataFile, "utf8")) : undefined);
162
+ const pack = options.pack ? await packCss(resolve(options.pack)) : undefined;
163
+ const bundle = options.bundle ?? findBundle();
164
+ const theme = options.theme ?? (pack?.name ?? "material3");
165
+ let defaultData = await readDefaultData();
166
+ let found = await discoverDocuments(dir, { defaultData });
167
+ const clients = new Set();
168
+ const broadcast = (event, data) => {
169
+ for (const send of clients)
170
+ send(event, data);
171
+ };
172
+ const listing = () => ({ dir, theme, pack: pack?.name, verify: !!options.verify, bundle: !!bundle, documents: found.documents.map(meta), broken: found.broken });
173
+ const rescan = async () => {
174
+ try {
175
+ defaultData = await readDefaultData();
176
+ }
177
+ catch {
178
+ // A half-saved default data file: keep the last good one until the next save.
179
+ }
180
+ const before = new Map(found.documents.map((d) => [d.file, JSON.stringify({ d: d.document, x: d.data })]));
181
+ found = await discoverDocuments(dir, { defaultData });
182
+ const changed = found.documents.filter((d) => before.get(d.file) !== JSON.stringify({ d: d.document, x: d.data })).map((d) => d.file);
183
+ const removed = [...before.keys()].filter((f) => !found.documents.some((d) => d.file === f));
184
+ broadcast("change", { changed, removed, ...listing() });
185
+ };
186
+ let timer;
187
+ const schedule = () => {
188
+ clearTimeout(timer);
189
+ timer = setTimeout(() => void rescan(), 80);
190
+ };
191
+ const watchers = [];
192
+ try {
193
+ watchers.push(watch(dir, { recursive: true }, schedule));
194
+ }
195
+ catch {
196
+ watchers.push(watch(dir, schedule));
197
+ }
198
+ if (dataFile && !dataFile.startsWith(dir + sep))
199
+ watchers.push(watch(dataFile, schedule));
200
+ let verifying = false;
201
+ const verify = async (doc, send, done) => {
202
+ const cli = findVerifier();
203
+ if (!cli) {
204
+ send("line", { text: "The verifier isn't installed here. It renders in a real browser, so it's a separate package:" });
205
+ send("line", { text: " npm install -D @polyxd/verifier && npx playwright install chromium" });
206
+ send("done", { code: 2 });
207
+ return done();
208
+ }
209
+ if (verifying) {
210
+ send("line", { text: "A verification is already running; wait for it to finish." });
211
+ send("done", { code: 3 });
212
+ return done();
213
+ }
214
+ verifying = true;
215
+ const tmp = await mkdtemp(join(tmpdir(), "polyxd-dev-verify-"));
216
+ const file = join(tmp, `${basename(doc.file, ".json")}.json`);
217
+ await writeFile(file, JSON.stringify(doc.data !== undefined ? { ...doc.document, data: doc.data } : doc.document));
218
+ send("line", { text: `polyxd-verify ${basename(file)} --themes ${THEMES.join(",")} --modes light,dark --widths 390,1100` });
219
+ const child = spawn(process.execPath, [cli, file, "--themes", THEMES.join(","), "--modes", "light,dark", "--widths", "390,1100"], { stdio: ["ignore", "pipe", "pipe"] });
220
+ let rest = "";
221
+ const lines = (chunk, stream) => {
222
+ rest += chunk.toString();
223
+ const parts = rest.split("\n");
224
+ rest = parts.pop() ?? "";
225
+ for (const line of parts)
226
+ send("line", { text: line, stream });
227
+ };
228
+ child.stdout.on("data", (c) => lines(c, "out"));
229
+ child.stderr.on("data", (c) => lines(c, "err"));
230
+ child.on("close", async (code) => {
231
+ if (rest)
232
+ send("line", { text: rest });
233
+ send("done", { code: code ?? 1 });
234
+ verifying = false;
235
+ await rm(tmp, { recursive: true, force: true });
236
+ done();
237
+ });
238
+ };
239
+ const handle = async (req, res) => {
240
+ const url = new URL(req.url ?? "/", "http://localhost");
241
+ const path = decodeURIComponent(url.pathname);
242
+ if (path === "/")
243
+ return text(res, 200, devPage({ dir, theme, pack: pack?.name, verify: !!options.verify, bundle: !!bundle, themes: THEMES }), "text/html");
244
+ if (path === "/preview/polyxd.js" || path === "/preview/polyxd.css") {
245
+ if (!bundle)
246
+ return text(res, 404, "The renderer bundle isn't installed: npm install @polyxd/react");
247
+ const body = await readFile(join(bundle, basename(path))).catch(() => null);
248
+ if (!body)
249
+ return text(res, 404, "not found");
250
+ res.writeHead(200, { "content-type": path.endsWith(".js") ? "text/javascript; charset=utf-8" : "text/css; charset=utf-8", "cache-control": "no-store" });
251
+ return res.end(body);
252
+ }
253
+ if (path === "/pack.css")
254
+ return pack ? text(res, 200, pack.css, "text/css") : text(res, 404, "no --pack");
255
+ if (path === "/api/documents")
256
+ return json(res, 200, listing());
257
+ if (path === "/api/events") {
258
+ const send = sse(res);
259
+ clients.add(send);
260
+ send("hello", listing());
261
+ req.on("close", () => clients.delete(send));
262
+ return;
263
+ }
264
+ const doc = (prefix) => (path.startsWith(prefix) ? found.documents.find((d) => d.file === path.slice(prefix.length)) : undefined);
265
+ if (path.startsWith("/api/documents/")) {
266
+ const d = doc("/api/documents/");
267
+ return d ? json(res, 200, { ...meta(d), document: d.document, data: d.data, issues: d.check.issues }) : json(res, 404, { error: "no such document" });
268
+ }
269
+ if (path.startsWith("/api/verify/")) {
270
+ const d = doc("/api/verify/");
271
+ if (!d)
272
+ return json(res, 404, { error: "no such document" });
273
+ const send = sse(res);
274
+ return verify(d, send, () => res.end());
275
+ }
276
+ text(res, 404, "not found");
277
+ };
278
+ const server = createServer((req, res) => {
279
+ handle(req, res).catch((e) => {
280
+ if (!res.headersSent)
281
+ json(res, 500, { error: e.message });
282
+ else
283
+ res.end();
284
+ });
285
+ });
286
+ const port = await new Promise((ok, fail) => {
287
+ server.once("error", fail);
288
+ server.listen(options.port ?? 4310, "127.0.0.1", () => ok(server.address().port));
289
+ });
290
+ return {
291
+ url: `http://localhost:${port}/`,
292
+ port,
293
+ documents: () => found.documents,
294
+ broken: () => found.broken,
295
+ pack,
296
+ rescan,
297
+ close: async () => {
298
+ clearTimeout(timer);
299
+ for (const w of watchers)
300
+ w.close();
301
+ for (const send of clients)
302
+ send("bye", {});
303
+ // Event streams never end on their own; close them so the server can.
304
+ const closed = new Promise((ok) => server.close(() => ok()));
305
+ server.closeAllConnections();
306
+ await closed;
307
+ },
308
+ };
309
+ }
310
+ const USAGE = `polyxd dev [dir] [--port 4310] [--theme material3] [--data <file.json>] [--pack <manifest.json|theme.css>] [--verify] [--open]
311
+
312
+ Previews the Polyxd documents in a folder (default: this one) in the browser, rendered with the
313
+ real renderer in any built-in design system, light or dark, at phone, tablet and desktop widths,
314
+ with the static check, the document, its data and the actions it dispatches beside it. Save a
315
+ file and the surface reloads in place.`;
316
+ export async function main(argv) {
317
+ let values;
318
+ let positionals;
319
+ try {
320
+ ({ values, positionals } = parseArgs({
321
+ args: argv,
322
+ allowPositionals: true,
323
+ options: { port: { type: "string" }, theme: { type: "string" }, data: { type: "string" }, pack: { type: "string" }, verify: { type: "boolean" }, open: { type: "boolean" }, help: { type: "boolean", short: "h" } },
324
+ }));
325
+ }
326
+ catch (e) {
327
+ console.error(e.message);
328
+ console.log(USAGE);
329
+ return 2;
330
+ }
331
+ if (values.help) {
332
+ console.log(USAGE);
333
+ return 0;
334
+ }
335
+ const port = values.port === undefined ? 4310 : Number(values.port);
336
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
337
+ console.error(`--port should be a number, not ${values.port}`);
338
+ return 2;
339
+ }
340
+ if (values.theme && !THEMES.includes(String(values.theme)) && !values.pack) {
341
+ console.error(`--theme should be one of ${THEMES.join(", ")}, or the pack given with --pack`);
342
+ return 2;
343
+ }
344
+ let server;
345
+ try {
346
+ server = await createDevServer({ dir: positionals[0] ?? ".", port, theme: values.theme, data: values.data, pack: values.pack, verify: !!values.verify });
347
+ }
348
+ catch (e) {
349
+ const err = e;
350
+ console.error(err.code === "EADDRINUSE" ? `Port ${port} is taken; pass --port with another.` : err.message);
351
+ return 1;
352
+ }
353
+ const docs = server.documents();
354
+ const absolute = resolve(positionals[0] ?? ".");
355
+ const rel = relative(process.cwd(), absolute);
356
+ const dir = rel === "" ? "." : rel.startsWith("..") ? absolute : rel;
357
+ console.log(`polyxd dev ${server.url}`);
358
+ console.log(`${docs.length} document${docs.length === 1 ? "" : "s"} in ${dir}, watching for changes${server.pack ? ` · pack ${server.pack.name} from --pack` : ""}${values.verify ? findVerifier() ? " · verifier ready" : " · verifier not installed (npm install -D @polyxd/verifier)" : ""}`);
359
+ if (!findBundle())
360
+ console.log("The renderer bundle isn't installed, so the page can list and check documents but not render them: npm install @polyxd/react");
361
+ for (const d of docs)
362
+ console.log(describe(d));
363
+ for (const b of server.broken())
364
+ console.log(` error ${b.file.padEnd(32)} did not parse: ${b.message}`);
365
+ if (!docs.length)
366
+ console.log(" (no documents yet: a document is a JSON file with specVersion and components, or an intent file with a document inside)");
367
+ if (values.open) {
368
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
369
+ spawn(opener, [server.url], { stdio: "ignore", detached: true, shell: process.platform === "win32" }).on("error", () => undefined).unref();
370
+ }
371
+ return 0;
372
+ }
373
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
package/dist/polyxd.js CHANGED
@@ -2,11 +2,12 @@
2
2
  /**
3
3
  * The `polyxd` command.
4
4
  *
5
- * polyxd pack ./tokens.css make a design-system pack out of your own tokens
6
- * polyxd check ./manifest.json check a pack against the semantic token contract
5
+ * polyxd pack ./tokens.css make a design-system pack out of your own tokens
6
+ * polyxd check ./manifest.json check a pack against the semantic token contract
7
+ * polyxd studio push ./ --to … send your tokens to Polyxd Studio (from CI, with an API key)
7
8
  *
8
- * Two commands, because those are the two things a team does before anything else works: point
9
- * Polyxd at their design system, and find out what it still needs.
9
+ * Three commands, because those are the things a team does before anything else works: point
10
+ * Polyxd at their design system, find out what it still needs, and keep Studio in step with it.
10
11
  */
11
12
  const [command, ...rest] = process.argv.slice(2);
12
13
  process.argv = [process.argv[0], process.argv[1], ...rest];
@@ -29,6 +30,18 @@ switch (command) {
29
30
  console.log(issues.length ? `\n${issues.length} issue(s)` : "Design system satisfies the semantic token contract.");
30
31
  process.exit(issues.length ? 1 : 0);
31
32
  }
33
+ case "studio": {
34
+ const { main } = await import("./studio.js");
35
+ process.exit(await main(rest));
36
+ }
37
+ case "dev": {
38
+ // Stays up once it has started: the server and the watcher keep the process alive.
39
+ const { main } = await import("./dev.js");
40
+ const code = await main(rest);
41
+ if (code || rest.includes("--help") || rest.includes("-h"))
42
+ process.exit(code);
43
+ break;
44
+ }
32
45
  default:
33
46
  console.log(`polyxd <command>
34
47
 
@@ -38,7 +51,16 @@ switch (command) {
38
51
 
39
52
  check <manifest.json>
40
53
  Checks a pack against the semantic token contract: every token present and correctly
41
- typed, every contrast pair measured, every constraint met.`);
54
+ typed, every contrast pair measured, every constraint met.
55
+
56
+ studio push <package dir | tarball | token file> --to <studio>/api/w/<workspace>
57
+ Sends your tokens to Polyxd Studio as a new version of your design system, using an
58
+ API key from POLYXD_STUDIO_KEY. Made for a CI step on every release.
59
+
60
+ dev [dir] [--port 4310] [--theme material3] [--data <file.json>] [--pack <manifest.json|theme.css>] [--verify] [--open]
61
+ Previews the documents in a folder as you edit them: rendered with the real renderer in
62
+ any built-in pack or one of yours, light or dark, phone to desktop, with the static check,
63
+ the document, its data and the actions it dispatches beside it. Reloads on save.`);
42
64
  process.exit(command ? 1 : 0);
43
65
  }
44
66
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"polyxd.js","sourceRoot":"","sources":["../src/polyxd.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;AAE3D,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,MAAM;QACT,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACzB,MAAM;IACR,KAAK,OAAO,EAAE,CAAC;QACb,sFAAsF;QACtF,6BAA6B;QAC7B,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC;QACpH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD;QACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;iEAQiD,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"polyxd.js","sourceRoot":"","sources":["../src/polyxd.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;AAE3D,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,MAAM;QACT,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACzB,MAAM;IACR,KAAK,OAAO,EAAE,CAAC;QACb,sFAAsF;QACtF,6BAA6B;QAC7B,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC;QACpH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,KAAK,QAAQ,EAAE,CAAC;QACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,KAAK,EAAE,CAAC;QACX,mFAAmF;QACnF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/E,MAAM;IACR,CAAC;IACD;QACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;uFAiBuE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,45 @@
1
+ export interface PushOptions {
2
+ /** Directory, tarball or token file. */
3
+ path: string;
4
+ /** The workspace's API base, e.g. https://studio.polyxd.com/api/w/acme */
5
+ to: string;
6
+ key: string;
7
+ /** Add a version to this design system instead of matching by package name. */
8
+ into?: string;
9
+ /** Name for a new design system (defaults to the package name or the file name). */
10
+ name?: string;
11
+ /** Override fetch, for tests. */
12
+ fetch?: typeof fetch;
13
+ }
14
+ export interface PushResult {
15
+ designSystemId: string;
16
+ versionId: string;
17
+ number: number;
18
+ /** Where to review the mapping in Studio. */
19
+ url: string;
20
+ scan: {
21
+ format: string;
22
+ total: number;
23
+ byTier: Record<string, number>;
24
+ modes: {
25
+ name: string;
26
+ }[];
27
+ issues: {
28
+ kind: string;
29
+ count: number;
30
+ }[];
31
+ picked?: string[];
32
+ };
33
+ }
34
+ /** What gets uploaded: the bytes, the file name, and the package identity when there is one. */
35
+ export declare function prepare(path: string): Promise<{
36
+ bytes: Uint8Array;
37
+ fileName: string;
38
+ packageName?: string;
39
+ packageVersion?: string;
40
+ cleanup: () => Promise<void>;
41
+ }>;
42
+ export declare function push(opts: PushOptions): Promise<PushResult>;
43
+ /** One line per fact, the way the pack command reports. */
44
+ export declare function describe(r: PushResult, fileName: string): string;
45
+ export declare function main(argv: string[]): Promise<number>;
package/dist/studio.js ADDED
@@ -0,0 +1,121 @@
1
+ /**
2
+ * `polyxd studio push`: send a design system's tokens to Polyxd Studio from wherever the tokens
3
+ * live: a package directory (packed with npm, so private dependencies and registries never
4
+ * matter), a tarball, or one token file (DTCG or Tokens Studio JSON, or CSS custom properties).
5
+ *
6
+ * POLYXD_STUDIO_KEY=… npx polyxd studio push ./ --to https://studio.polyxd.com/api/w/acme
7
+ * npx polyxd studio push ./tokens.css --to … --name "Acme tokens"
8
+ * npx polyxd studio push ./dist/tokens-2.4.0.tgz --to … --into <designSystemId>
9
+ *
10
+ * Studio scans the tokens (tiers, modes, aliases, issues) and answers with a link to review the
11
+ * mapping. A push with the same package name lands as a new version of the same design system,
12
+ * so a CI step can run it on every release.
13
+ */
14
+ import { execFile } from "node:child_process";
15
+ import { mkdtemp, readFile, rm, stat } from "node:fs/promises";
16
+ import { tmpdir } from "node:os";
17
+ import { basename, join, resolve } from "node:path";
18
+ import { promisify } from "node:util";
19
+ const exec = promisify(execFile);
20
+ /** What gets uploaded: the bytes, the file name, and the package identity when there is one. */
21
+ export async function prepare(path) {
22
+ const target = resolve(path);
23
+ const info = await stat(target).catch(() => null);
24
+ if (!info)
25
+ throw new Error(`${path} does not exist`);
26
+ if (info.isDirectory()) {
27
+ const pkgFile = join(target, "package.json");
28
+ const pkg = JSON.parse(await readFile(pkgFile, "utf8").catch(() => {
29
+ throw new Error(`${path} has no package.json; point at a token file instead`);
30
+ }));
31
+ // npm pack honours "files", .npmignore and prepack, so the tarball is what a release would be.
32
+ const dir = await mkdtemp(join(tmpdir(), "polyxd-push-"));
33
+ const { stdout } = await exec("npm", ["pack", "--json", "--pack-destination", dir, "--ignore-scripts"], { cwd: target, maxBuffer: 16 * 1024 * 1024 });
34
+ const [packed] = JSON.parse(stdout);
35
+ const bytes = new Uint8Array(await readFile(join(dir, packed.filename)));
36
+ return { bytes, fileName: packed.filename, packageName: packed.name ?? pkg.name, packageVersion: packed.version ?? pkg.version, cleanup: () => rm(dir, { recursive: true, force: true }) };
37
+ }
38
+ const bytes = new Uint8Array(await readFile(target));
39
+ return { bytes, fileName: basename(target), cleanup: async () => undefined };
40
+ }
41
+ export async function push(opts) {
42
+ const to = opts.to.replace(/\/+$/, "");
43
+ if (!/^https?:\/\/.+\/api\/w\/[a-z0-9-]+$/i.test(to))
44
+ throw new Error(`--to should look like https://studio.example.com/api/w/<workspace>, not ${opts.to}`);
45
+ if (!opts.key)
46
+ throw new Error("No key: set POLYXD_STUDIO_KEY or pass --key (Team → API keys in Studio)");
47
+ const prepared = await prepare(opts.path);
48
+ try {
49
+ const form = new FormData();
50
+ form.set("file", new Blob([prepared.bytes.slice().buffer]), prepared.fileName);
51
+ if (opts.name)
52
+ form.set("name", opts.name);
53
+ if (opts.into)
54
+ form.set("designSystemId", opts.into);
55
+ if (prepared.packageName)
56
+ form.set("packageName", prepared.packageName);
57
+ if (prepared.packageVersion)
58
+ form.set("packageVersion", prepared.packageVersion);
59
+ const res = await (opts.fetch ?? fetch)(`${to}/design-systems/import`, { method: "POST", headers: { authorization: `Bearer ${opts.key}` }, body: form });
60
+ const text = await res.text();
61
+ let data = {};
62
+ try {
63
+ data = text ? JSON.parse(text) : {};
64
+ }
65
+ catch {
66
+ /* an HTML error page from a proxy: the status line says enough */
67
+ }
68
+ if (!res.ok)
69
+ throw new Error(data.error ?? `Studio answered ${res.status} ${res.statusText}`);
70
+ const app = new URL(to);
71
+ const slug = to.split("/").pop();
72
+ return { ...data, url: data.url ?? `${app.origin}/w/${slug}/design-systems/${data.designSystemId}/versions/${data.versionId}/scan` };
73
+ }
74
+ finally {
75
+ await prepared.cleanup();
76
+ }
77
+ }
78
+ /** One line per fact, the way the pack command reports. */
79
+ export function describe(r, fileName) {
80
+ const tiers = Object.entries(r.scan.byTier ?? {})
81
+ .filter(([, n]) => n)
82
+ .map(([t, n]) => `${n} ${t}`)
83
+ .join(", ");
84
+ const modes = (r.scan.modes ?? []).map((m) => m.name).join(", ");
85
+ const issues = (r.scan.issues ?? []).reduce((s, i) => s + i.count, 0);
86
+ return [
87
+ `Pushed ${fileName} as version ${r.number}.`,
88
+ `${r.scan.total} tokens (${r.scan.format}${tiers ? `; ${tiers}` : ""})${modes ? ` · modes: ${modes}` : ""}${issues ? ` · ${issues} thing${issues === 1 ? "" : "s"} to look at` : ""}`,
89
+ `Review the mapping: ${r.url}`,
90
+ ].join("\n");
91
+ }
92
+ export async function main(argv) {
93
+ const [sub, ...rest] = argv;
94
+ if (sub !== "push") {
95
+ console.log(`polyxd studio push <package dir | tarball | token file> --to <studio>/api/w/<workspace> [--into <designSystemId>] [--name <name>] [--key <key>]
96
+
97
+ Sends your tokens to Polyxd Studio. A directory is packed with npm (so it's what a release would
98
+ be); the key comes from POLYXD_STUDIO_KEY or --key (Team → API keys). The same package name lands
99
+ as a new version of the same design system each time.`);
100
+ return sub ? 1 : 0;
101
+ }
102
+ const flag = (name) => {
103
+ const i = rest.indexOf(`--${name}`);
104
+ return i > -1 ? rest[i + 1] : undefined;
105
+ };
106
+ const path = rest.find((a, i) => !a.startsWith("--") && (i === 0 || !rest[i - 1].startsWith("--")));
107
+ if (!path || !flag("to")) {
108
+ console.log("usage: polyxd studio push <path> --to <studio>/api/w/<workspace> [--into <id>] [--name <name>] [--key <key>]");
109
+ return 2;
110
+ }
111
+ try {
112
+ const r = await push({ path, to: flag("to"), key: flag("key") ?? process.env.POLYXD_STUDIO_KEY ?? "", into: flag("into"), name: flag("name") });
113
+ console.log(describe(r, basename(path)));
114
+ return 0;
115
+ }
116
+ catch (e) {
117
+ console.error(e.message);
118
+ return 1;
119
+ }
120
+ }
121
+ //# sourceMappingURL=studio.js.map