@terrazzo/cli 0.10.3 → 2.0.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # @terrazzo/cli
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - ⚠️ Breaking change; DTCG 2nd Editors draft format will throw errors by default. This means converting all colors and dimensions to the new object format.
8
+
9
+ Though this is a breaking change in default behavior, you can opt back into the old behavior by adjusting your config’s lint settings. See https://terrazzo.app/docs/cli/lint/.
10
+
11
+ List of changes:
12
+ - **color**: `channels` is invalid; `components` is required (“channels” was never part of the spec; this just deprecates an in-progress draft that was briefly supported)
13
+ - **dimension**: object notation (`{ value: 16, unit: 'px' }`) required.
14
+ - **dimension**: `0` is no longer automatically expanded to`{ value: 0, unit: 'px' }`.
15
+ - **duration**: object notation (`{ value: 100, unit: 'ms' }`) required.
16
+ - **dimension**: `{ $value: 0 }` no longer allowed.
17
+ - **typography**: `fontFamily`, `fontSize`, `fontWeight`, `lineHeight`, and `letterSpacing` are all required at a minimum (additional properties are still allowed).
18
+
19
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Soft deprecate core/required-typography-properties in favor of core/valid-typography
20
+
21
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - ⚠️ Minor breaking change: the transform() API now returns the Momoa node as the 1st parameter. The 2nd parameter is now an object with more context. Lastly, it requires returning a momoa node, rather than raw JSON.
22
+
23
+ ```diff
24
+ + import * as momoa from "@humanwhocodes/momoa";
25
+
26
+ transform: {
27
+ - color(json, path, node) {
28
+ + color(node, { path, filename }) {
29
+ + const json = momoa.evaluate(node);
30
+ - return json;
31
+ + return momoa.parse(json);
32
+ }
33
+ ```
34
+
35
+ This should result in a little less work overall. For example, instead of writing `if (typeof json === 'object' && !Array.isArray(json))` that could be shortened to `if (node.type === 'Object')`, among many other such advantages. You can call `evaluate()` manually if you’re more used to working with the raw JSON instead. Similarly, you can call `parse()` if you’re working with
36
+
37
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - ⚠️ Breaking change: lint on plugins no longer runs on individual files, rather, the full set once merged.
38
+
39
+ If your lint plugin is not using the `src` context value, no changes are needed. If it is, you’ll need to instead read from the `sources` array, and look up sources with a token’s `source.loc` filename manually. This change was because lint rules now run on all files in one pass, essentially.
40
+
41
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - ⚠️ [Plugin API] Minor breaking change: token.originalValue may be undefined for tokens created with $ref. This shouldn’t affect any tokens or plugins not using $refs. But going forward this value will be missing if the token was created dynamically via $ref.
42
+
43
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Minor breaking change: build() and buildEnd() plugin hooks are now executed in parallel. The other hooks are still executed sequentially.
44
+
45
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - ⚠️ Breaking change: the following token types have more strict requirements about all properties being present:
46
+ - Border
47
+ - Transition
48
+ - Typography
49
+
50
+ These behaviors may be opted out individually by adjusting the new lint rules ([see documentation](https://terrazzo.app/docs/cli/lint/)).
51
+
52
+ ### Patch Changes
53
+
54
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Fix bug where border tokens’ partial aliases would sometimes refer to themselves
55
+
56
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Fix bug of lint warning of rules turned off being unused
57
+
58
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Validation moved to lint rules, which means token validation can be individually configured, and optionally extended.
59
+
60
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Add first class support for JSON $refs, both remote and local.
61
+
62
+ Under-the-hood this transforms DTCG aliase to JSON $refs, so they’re interchangeable.
63
+
64
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Bugfix: fix strokeStyle partialAliasOf
65
+
66
+ - [#530](https://github.com/terrazzoapp/terrazzo/pull/530) [`370ed7b`](https://github.com/terrazzoapp/terrazzo/commit/370ed7b0f578a64824124145d7f4936536b37bb3) Thanks [@drwpow](https://github.com/drwpow)! - Add missing $deprecated property to group types
67
+
3
68
  ## 0.10.3
4
69
 
5
70
  ### Patch Changes
package/bin/cli.js CHANGED
@@ -138,4 +138,4 @@ export default async function main() {
138
138
  process.exit(0);
139
139
  }
140
140
 
141
- main();
141
+ await main();
package/dist/index.d.ts CHANGED
@@ -56,7 +56,6 @@ declare function resolveTokenPath(filename: string, {
56
56
  }): url0.URL;
57
57
  /** Print time elapsed */
58
58
  declare function time(start: number): string;
59
- //# sourceMappingURL=shared.d.ts.map
60
59
  //#endregion
61
60
  //#region src/build.d.ts
62
61
  interface BuildOptions {
@@ -80,7 +79,6 @@ declare function writeFiles(result: BuildRunnerResult, {
80
79
  config: ConfigInit;
81
80
  logger: Logger;
82
81
  }): void;
83
- //# sourceMappingURL=build.d.ts.map
84
82
  //#endregion
85
83
  //#region src/check.d.ts
86
84
  interface CheckOptions {
@@ -95,12 +93,10 @@ declare function checkCmd({
95
93
  logger,
96
94
  positionals
97
95
  }: CheckOptions): Promise<void>;
98
- //# sourceMappingURL=check.d.ts.map
99
96
  //#endregion
100
97
  //#region src/help.d.ts
101
98
  /** Show help */
102
99
  declare function helpCmd(): void;
103
- //# sourceMappingURL=help.d.ts.map
104
100
  //#endregion
105
101
  //#region src/init.d.ts
106
102
  interface InitOptions {
@@ -109,7 +105,6 @@ interface InitOptions {
109
105
  declare function initCmd({
110
106
  logger
111
107
  }: InitOptions): Promise<void>;
112
- //# sourceMappingURL=init.d.ts.map
113
108
  //#endregion
114
109
  //#region src/lab.d.ts
115
110
  interface LabBuildOptions {
@@ -122,7 +117,6 @@ declare function labCmd({
122
117
  config,
123
118
  logger
124
119
  }: LabBuildOptions): Promise<void>;
125
- //# sourceMappingURL=lab.d.ts.map
126
120
  //#endregion
127
121
  //#region src/normalize.d.ts
128
122
  interface NormalizeOptions {
@@ -133,17 +127,12 @@ declare function normalizeCmd(filename: string, {
133
127
  logger,
134
128
  output
135
129
  }: NormalizeOptions): Promise<void>;
136
- //# sourceMappingURL=normalize.d.ts.map
137
130
  //#endregion
138
131
  //#region src/version.d.ts
139
132
  declare function versionCmd(): void;
140
- //# sourceMappingURL=version.d.ts.map
141
-
142
133
  //#endregion
143
134
  //#region src/index.d.ts
144
135
  declare function defineConfig(config: Config): ConfigInit;
145
- //# sourceMappingURL=index.d.ts.map
146
-
147
136
  //#endregion
148
137
  export { BuildOptions, CheckOptions, Command, DEFAULT_CONFIG_PATH, DEFAULT_TOKENS_PATH, Flags, GREEN_CHECK, InitOptions, LabBuildOptions, LoadConfigOptions, NormalizeOptions, buildCmd, checkCmd, cwd, defineConfig, helpCmd, initCmd, labCmd, loadConfig, loadTokens, normalizeCmd, printError, printSuccess, resolveConfig, resolveTokenPath, time, versionCmd, writeFiles };
149
138
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import { build, defineConfig as defineConfig$1, getObjMembers, parse, traverse } from "@terrazzo/parser";
3
+ import { build, defineConfig as defineConfig$1, parse } from "@terrazzo/parser";
4
4
  import fs, { createReadStream, createWriteStream } from "node:fs";
5
5
  import path from "node:path";
6
6
  import pc from "picocolors";
@@ -16,7 +16,8 @@ import { readdir } from "node:fs/promises";
16
16
  import { Readable, Writable } from "node:stream";
17
17
  import { serve } from "@hono/node-server";
18
18
  import mime from "mime";
19
- import { parse as parse$1, print } from "@humanwhocodes/momoa";
19
+ import * as momoa from "@humanwhocodes/momoa";
20
+ import { getObjMember, getObjMembers, traverseAsync } from "@terrazzo/json-schema-tools";
20
21
 
21
22
  //#region src/shared.ts
22
23
  const cwd = new URL(`${pathToFileURL(process.cwd())}/`);
@@ -187,7 +188,7 @@ function resolveConfig(filename) {
187
188
  if (filename) {
188
189
  const configPath = new URL(filename, cwd);
189
190
  if (fs.existsSync(configPath)) return configPath.href;
190
- return void 0;
191
+ return;
191
192
  }
192
193
  return [
193
194
  ".js",
@@ -285,12 +286,10 @@ async function buildCmd({ config, configPath, flags, logger }) {
285
286
  console.error(pc.red(`✗ ${err.message || err}`));
286
287
  }
287
288
  }
288
- const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));
289
- tokenWatcher.on("change", async (filename) => {
289
+ chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename))).on("change", async (filename) => {
290
290
  await rebuild({ messageBefore: `${pc.dim(dt.format(/* @__PURE__ */ new Date()))} ${pc.green("tz")}} ${pc.yellow(filename)} updated ${GREEN_CHECK}` });
291
291
  });
292
- const configWatcher = chokidar.watch(resolveConfig(configPath));
293
- configWatcher.on("change", async () => {
292
+ chokidar.watch(resolveConfig(configPath)).on("change", async () => {
294
293
  await rebuild({ messageBefore: `${pc.dim(dt.format(/* @__PURE__ */ new Date()))} ${pc.green("tz")} ${pc.yellow("Config updated. Reloading…")}` });
295
294
  });
296
295
  await new Promise(() => {});
@@ -535,7 +534,8 @@ async function initCmd({ logger }) {
535
534
  type: "Identifier",
536
535
  name: p.specifier
537
536
  },
538
- arguments: []
537
+ arguments: [],
538
+ optional: false
539
539
  }));
540
540
  if (pluginsArray) pluginsArray.elements.push(...pluginsAst);
541
541
  else astConfig.properties.push({
@@ -560,6 +560,7 @@ async function initCmd({ logger }) {
560
560
  } }));
561
561
  } else fs.writeFileSync(DEFAULT_CONFIG_PATH, `import { defineConfig } from '@terrazzo/cli';
562
562
  ${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join("\n")}
563
+
563
564
  export default defineConfig({
564
565
  tokens: ['./tokens.json'],
565
566
  plugins: [
@@ -568,6 +569,27 @@ export default defineConfig({
568
569
  outDir: './dist/',
569
570
  lint: {
570
571
  /** @see https://terrazzo.app/docs/cli/lint */
572
+ enabled: true,
573
+ rules: {
574
+ 'core/valid-color': 'error',
575
+ 'core/valid-dimension': 'error',
576
+ 'core/valid-font-family': 'error',
577
+ 'core/valid-font-weight': 'error',
578
+ 'core/valid-duration': 'error',
579
+ 'core/valid-cubic-bezier': 'error',
580
+ 'core/valid-number': 'error',
581
+ 'core/valid-link': 'error',
582
+ 'core/valid-boolean': 'error',
583
+ 'core/valid-string': 'error',
584
+ 'core/valid-stroke-style': 'error',
585
+ 'core/valid-border': 'error',
586
+ 'core/valid-transition': 'error',
587
+ 'core/valid-shadow': 'error',
588
+ 'core/valid-gradient': 'error',
589
+ 'core/valid-typography': 'error',
590
+ 'core/consistent-naming': 'warn',
591
+ 'no-type-on-alias': 'warn',
592
+ },
571
593
  },
572
594
  });`);
573
595
  s.stop(`Installed ${pluginCount}`);
@@ -598,8 +620,7 @@ async function labCmd({ config, logger }) {
598
620
  port: 9e3,
599
621
  overrideGlobalObjects: false,
600
622
  async fetch(request) {
601
- const url = new URL(request.url);
602
- const pathname = url.pathname;
623
+ const pathname = new URL(request.url).pathname;
603
624
  if (pathname === "/") return new Response(Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve("./lab/index.html")))), { headers: { "Content-Type": "text/html" } });
604
625
  if (pathname === "/api/tokens") {
605
626
  if (request.method === "GET") return new Response(Readable.toWeb(createReadStream(tokenFileUrl)), { headers: {
@@ -651,51 +672,97 @@ async function normalizeCmd(filename, { logger, output }) {
651
672
  message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`
652
673
  });
653
674
  const sourceData = fs.readFileSync(sourceLoc, "utf8");
654
- const document = parse$1(sourceData);
675
+ const document = momoa.parse(sourceData, { mode: "jsonc" });
655
676
  const { tokens } = await parse([{
656
677
  src: sourceData,
657
678
  filename: sourceLoc
658
679
  }], {
659
- config: defineConfig$1({}, { cwd }),
680
+ config: defineConfig$1({ lint: { rules: {
681
+ "core/valid-color": "off",
682
+ "core/valid-dimension": "off",
683
+ "core/valid-duration": "off",
684
+ "core/valid-typography": "off"
685
+ } } }, { cwd }),
660
686
  logger
661
687
  });
662
- traverse(document, { enter(node, _parent, nodePath) {
688
+ await traverseAsync(document, { async enter(node, _parent, nodePath) {
663
689
  const token = tokens[nodePath.join(".")];
664
690
  if (!token || token.aliasOf || node.type !== "Member" || node.value.type !== "Object") return;
665
691
  const $valueI = node.value.members.findIndex(findMember("$value"));
666
692
  switch (token.$type) {
667
693
  case "color":
668
- case "dimension":
669
- case "duration": {
670
694
  if (node.value.members[$valueI].value.type === "String") {
671
- const newValueContainer = parse$1(JSON.stringify({ $value: token.$value })).body;
672
- const newValueNode = newValueContainer.members.find(findMember("$value"));
673
- node.value.members[$valueI] = newValueNode;
674
- const { $extensions } = getObjMembers(node.value);
695
+ if (isAlias(node.value.members[$valueI].value.value)) return;
696
+ const hex = node.value.members[$valueI].value.value;
697
+ node.value.members[$valueI].value = momoa.parse(JSON.stringify({
698
+ ...token.$value,
699
+ hex: hex.startsWith("#") ? hex.slice(0, 7) : void 0
700
+ })).body;
701
+ const $extensions = getObjMember(node.value, "$extensions");
675
702
  if ($extensions?.type === "Object") {
676
- const { mode } = getObjMembers($extensions);
703
+ const mode = getObjMember($extensions, "mode");
677
704
  if (mode?.type === "Object") for (let i = 0; i < mode.members.length; i++) {
678
705
  const modeName = mode.members[i].name.value;
679
- const modeValue = token.mode[modeName];
680
- if (typeof modeValue === "string" && isAlias(modeValue)) continue;
681
- const newModeValueContainer = parse$1(JSON.stringify({ [modeName]: token.mode[modeName].$value })).body;
682
- const newModeValueNode = newModeValueContainer.members.find(findMember(modeName));
683
- mode.members[i] = newModeValueNode;
706
+ const hex$1 = mode.members[i].value.value;
707
+ mode.members[i].value = momoa.parse(JSON.stringify({
708
+ ...token.mode[modeName].$value,
709
+ hex: hex$1.startsWith("#") ? hex$1.slice(0, 7) : void 0
710
+ })).body;
684
711
  }
685
712
  }
686
713
  }
687
714
  break;
715
+ case "dimension":
716
+ case "duration":
717
+ if (node.value.members[$valueI].value.type === "String") {
718
+ if (isAlias(node.value.members[$valueI].value.value)) return;
719
+ node.value.members[$valueI].value = normalizeDurationDimension(node.value.members[$valueI].value);
720
+ const $extensions = getObjMember(node.value, "$extensions");
721
+ if ($extensions?.type === "Object") {
722
+ const mode = getObjMember($extensions, "mode");
723
+ if (mode?.type === "Object") for (let i = 0; i < mode.members.length; i++) mode.members[i].value = normalizeDurationDimension(node.value.members[$valueI].value);
724
+ }
725
+ }
726
+ break;
727
+ case "typography": {
728
+ if (node.value.members[$valueI]?.value.type !== "Object") return;
729
+ node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);
730
+ const $extensions = getObjMember(node.value, "$extensions");
731
+ if ($extensions?.type === "Object") {
732
+ const mode = getObjMember($extensions, "mode");
733
+ if (mode?.type === "Object") for (let i = 0; i < mode.members.length; i++) mode.members[i].value = normalizeTypography(mode.members[i].value);
734
+ }
688
735
  }
689
736
  }
690
737
  } });
691
738
  const outputLoc = new URL(output, cwd);
692
739
  fs.mkdirSync(new URL(".", outputLoc), { recursive: true });
693
- fs.writeFileSync(outputLoc, print(document, { indent: 2 }));
740
+ fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));
694
741
  } catch (err) {
695
742
  printError(err.message);
696
743
  process.exit(1);
697
744
  }
698
745
  }
746
+ function normalizeDurationDimension(node) {
747
+ const value = Number.parseFloat(node.value);
748
+ if (!Number.isFinite(value)) return node;
749
+ node.type = "Object";
750
+ node.members = momoa.parse(JSON.stringify({
751
+ value,
752
+ unit: node.value.replace(String(value), "")
753
+ })).body.members;
754
+ delete node.value;
755
+ return node;
756
+ }
757
+ function normalizeTypography(node) {
758
+ const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);
759
+ if (!fontFamily) node.members.push(momoa.parse("{\"fontFamily\":[\"inherit\"]}").body.members[0]);
760
+ if (!fontSize) node.members.push(momoa.parse("{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}").body.members[0]);
761
+ if (!fontWeight) node.members.push(momoa.parse("{\"fontWeight\":400}").body.members[0]);
762
+ if (!letterSpacing) node.members.push(momoa.parse("{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}").body.members[0]);
763
+ if (!lineHeight) node.members.push(momoa.parse("{\"lineHeight\":1}").body.members[0]);
764
+ return node;
765
+ }
699
766
 
700
767
  //#endregion
701
768
  //#region src/version.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["config: ConfigInit","configPath: string | undefined","tokenPaths: URL[]","res","message: string","startTime?: number","filename?: string","filename: string","start: number","result: BuildRunnerResult","DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }>","name: string","member: MemberNode","filename: string","config: Config","normalizedConfig: Config"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.mjs', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: { build: { enabled: true }, rules: {} },\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n const mod = await import(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${path.relative(cwd.href, resolvedConfigPath)}. See https://terrazzo.dev/docs/cli for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n return { config, configPath: resolvedConfigPath! };\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string) {\n // --config [configpath]\n if (filename) {\n const configPath = new URL(filename, cwd);\n if (fs.existsSync(configPath)) {\n return configPath.href; // ⚠️ ESM wants \"file://...\" URLs on Windows & Unix.\n }\n return undefined;\n }\n\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple files differing only by file extension, behavior is\n // unpredictable and that’s on them.\n return ['.js', '.mjs', '.cjs']\n .map((ext) => new URL(`./terrazzo.config${ext}`, cwd))\n .find((configPath) => fs.existsSync(configPath))?.href; // ⚠️ ESM wants \"file://...\" URLs on Windows & Unix.;\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.js'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n result = await build(tokens, { sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.js)\n --quiet Suppress warnings\n`);\n}\n","import { exec } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, DEFAULT_CONFIG_PATH, DEFAULT_TOKENS_PATH, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'radix'\n | 'salesforce-lightning'\n | 'shopify-polaris';\n\nconst DTCG_ROOT_URL = 'https://raw.githubusercontent.com/terrazzoapp/dtcg-examples/refs/heads/main/';\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['adobe-spectrum.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['apple-hig.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['figma-sds.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['github-primer.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['ibm-carbon.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['microsoft-fluent.json'],\n },\n radix: {\n name: 'Radix',\n author: 'Radix',\n tokens: ['radix.json'],\n },\n 'salesforce-lightning': {\n name: 'Lightning',\n author: 'Salesforce',\n tokens: ['salesforce-lightning.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['shopify-polaris.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n\n let tokensPath = config.tokens[0]!;\n let startFromDS = !(tokensPath && fs.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fs.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n } else {\n tokensPath = DEFAULT_TOKENS_PATH;\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n if (ds) {\n // TODO: support multiple tokens files?\n const s = spinner();\n s.start('Downloading');\n const tokenSource = await fetch(new URL(ds.tokens[0]!, DTCG_ROOT_URL)).then((res) => res.text());\n fs.writeFileSync(tokensPath, tokenSource);\n s.stop('Download complete');\n }\n }\n\n // 2. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), package: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: thi sis async to show the spinner\n await new Promise((resolve, reject) => {\n const subprocess = exec([packageManager, INSTALL_COMMAND[packageManager], newPlugins.join(' ')].join(' '), {\n cwd,\n });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n if (configPath) {\n const ast = parseModule(fs.readFileSync(configPath, 'utf8'));\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n\n // 2a. add plugin imports\n // note: this has the potential to duplicate plugins, but we tried our\n // best to filter already, and this may be the user’s fault if they\n // selected to install a plugin already installed. But also, this is\n // easily-fixable, so let’s not waste too much time here (and possibly\n // introduce bugs).\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration',\n source: { type: 'Literal', value: p.package },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // 2b. add plugins to config.plugins\n if (!astExport) {\n logger.error({ group: 'config', message: `SyntaxError: ${relConfigPath} does not have default export.` });\n return;\n }\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n if (astConfig.type !== 'ObjectExpression') {\n logger.error({\n group: 'config',\n message: `Config: expected object default export, received ${astConfig.type}`,\n });\n return;\n }\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression',\n callee: {\n type: 'Identifier',\n name: p.specifier,\n },\n arguments: [],\n }) as ESTree.CallExpression,\n );\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n // 2c. update new file (and we’ll probably format it wrong but hey)\n fs.writeFileSync(\n configPath,\n generate(ast, {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n }),\n );\n } else {\n // 2a. write new config file (easy)\n fs.writeFileSync(\n DEFAULT_CONFIG_PATH,\n `import { defineConfig } from '@terrazzo/cli';\n${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join('\\n')}\nexport default defineConfig({\n tokens: ['./tokens.json'],\n plugins: [\n ${plugins.map((p) => `${p.specifier}(),`).join('\\n ')}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/cli/lint */\n },\n});`,\n );\n }\n s.stop(`Installed ${pluginCount}`);\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","import { createReadStream, createWriteStream, type PathLike } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html')))) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(Readable.toWeb(createReadStream(tokenFileUrl as PathLike)) as ReadableStream, {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n });\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(createWriteStream(tokenFileUrl as PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { type MemberNode, type ObjectNode, parse as parseJSON, print, type StringNode } from '@humanwhocodes/momoa';\nimport { defineConfig, getObjMembers, type Logger, parse, traverse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = parseJSON(sourceData);\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig({}, { cwd }),\n logger,\n });\n\n traverse(document, {\n enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color':\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n const newValueContainer = parseJSON(JSON.stringify({ $value: token.$value })).body as ObjectNode;\n const newValueNode = newValueContainer.members.find(findMember('$value'))!;\n node.value.members[$valueI] = newValueNode;\n\n const { $extensions } = getObjMembers(node.value);\n if ($extensions?.type === 'Object') {\n const { mode } = getObjMembers($extensions);\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as StringNode).value;\n const modeValue = token.mode[modeName]!;\n if (typeof modeValue === 'string' && isAlias(modeValue)) {\n continue;\n }\n const newModeValueContainer = parseJSON(\n JSON.stringify({ [modeName]: token.mode[modeName]!.$value }),\n ).body as ObjectNode;\n const newModeValueNode = newModeValueContainer.members.find(findMember(modeName))!;\n mode.members[i] = newModeValueNode;\n }\n }\n }\n }\n break;\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["config: ConfigInit","configPath: string | undefined","defineConfig","res","DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }>","defineConfig","hex","normalizedConfig: Config","defineConfigCore"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.mjs', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: {\n build: { enabled: true },\n rules: {},\n },\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n const mod = await import(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${path.relative(cwd.href, resolvedConfigPath)}. See https://terrazzo.dev/docs/cli for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n return {\n config,\n configPath: resolvedConfigPath!,\n };\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string) {\n // --config [configpath]\n if (filename) {\n const configPath = new URL(filename, cwd);\n if (fs.existsSync(configPath)) {\n return configPath.href; // ⚠️ ESM wants \"file://...\" URLs on Windows & Unix.\n }\n return undefined;\n }\n\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple files differing only by file extension, behavior is\n // unpredictable and that’s on them.\n return ['.js', '.mjs', '.cjs']\n .map((ext) => new URL(`./terrazzo.config${ext}`, cwd))\n .find((configPath) => fs.existsSync(configPath))?.href; // ⚠️ ESM wants \"file://...\" URLs on Windows & Unix.;\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.js'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n result = await build(tokens, { sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.js)\n --quiet Suppress warnings\n`);\n}\n","import { exec } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, DEFAULT_CONFIG_PATH, DEFAULT_TOKENS_PATH, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'radix'\n | 'salesforce-lightning'\n | 'shopify-polaris';\n\nconst DTCG_ROOT_URL = 'https://raw.githubusercontent.com/terrazzoapp/dtcg-examples/refs/heads/main/';\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['adobe-spectrum.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['apple-hig.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['figma-sds.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['github-primer.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['ibm-carbon.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['microsoft-fluent.json'],\n },\n radix: {\n name: 'Radix',\n author: 'Radix',\n tokens: ['radix.json'],\n },\n 'salesforce-lightning': {\n name: 'Lightning',\n author: 'Salesforce',\n tokens: ['salesforce-lightning.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['shopify-polaris.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n\n let tokensPath = config.tokens[0]!;\n let startFromDS = !(tokensPath && fs.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fs.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n } else {\n tokensPath = DEFAULT_TOKENS_PATH;\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n if (ds) {\n // TODO: support multiple tokens files?\n const s = spinner();\n s.start('Downloading');\n const tokenSource = await fetch(new URL(ds.tokens[0]!, DTCG_ROOT_URL)).then((res) => res.text());\n fs.writeFileSync(tokensPath, tokenSource);\n s.stop('Download complete');\n }\n }\n\n // 2. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), package: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: thi sis async to show the spinner\n await new Promise((resolve, reject) => {\n const subprocess = exec([packageManager, INSTALL_COMMAND[packageManager], newPlugins.join(' ')].join(' '), {\n cwd,\n });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n if (configPath) {\n const ast = parseModule(fs.readFileSync(configPath, 'utf8'));\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n\n // 2a. add plugin imports\n // note: this has the potential to duplicate plugins, but we tried our\n // best to filter already, and this may be the user’s fault if they\n // selected to install a plugin already installed. But also, this is\n // easily-fixable, so let’s not waste too much time here (and possibly\n // introduce bugs).\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration',\n source: { type: 'Literal', value: p.package },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // 2b. add plugins to config.plugins\n if (!astExport) {\n logger.error({ group: 'config', message: `SyntaxError: ${relConfigPath} does not have default export.` });\n return;\n }\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n if (astConfig.type !== 'ObjectExpression') {\n logger.error({\n group: 'config',\n message: `Config: expected object default export, received ${astConfig.type}`,\n });\n return;\n }\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression' as const,\n callee: {\n type: 'Identifier' as const,\n name: p.specifier,\n },\n arguments: [],\n optional: false,\n }) as ESTree.CallExpression,\n );\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n // 2c. update new file (and we’ll probably format it wrong but hey)\n fs.writeFileSync(\n configPath,\n generate(ast, {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n }),\n );\n } else {\n // 2a. write new config file (easy)\n fs.writeFileSync(\n DEFAULT_CONFIG_PATH,\n `import { defineConfig } from '@terrazzo/cli';\n${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join('\\n')}\n\nexport default defineConfig({\n tokens: ['./tokens.json'],\n plugins: [\n ${plugins.map((p) => `${p.specifier}(),`).join('\\n ')}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/cli/lint */\n enabled: true,\n rules: {\n 'core/valid-color': 'error',\n 'core/valid-dimension': 'error',\n 'core/valid-font-family': 'error',\n 'core/valid-font-weight': 'error',\n 'core/valid-duration': 'error',\n 'core/valid-cubic-bezier': 'error',\n 'core/valid-number': 'error',\n 'core/valid-link': 'error',\n 'core/valid-boolean': 'error',\n 'core/valid-string': 'error',\n 'core/valid-stroke-style': 'error',\n 'core/valid-border': 'error',\n 'core/valid-transition': 'error',\n 'core/valid-shadow': 'error',\n 'core/valid-gradient': 'error',\n 'core/valid-typography': 'error',\n 'core/consistent-naming': 'warn',\n 'no-type-on-alias': 'warn',\n },\n },\n});`,\n );\n }\n s.stop(`Installed ${pluginCount}`);\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","import { createReadStream, createWriteStream, type PathLike } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html')))) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(Readable.toWeb(createReadStream(tokenFileUrl as PathLike)) as ReadableStream, {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n });\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(createWriteStream(tokenFileUrl as PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport * as momoa from '@humanwhocodes/momoa';\nimport { getObjMember, getObjMembers, traverseAsync } from '@terrazzo/json-schema-tools';\nimport { defineConfig, type Logger, parse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: momoa.MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = momoa.parse(sourceData, { mode: 'jsonc' });\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig(\n {\n lint: {\n rules: {\n 'core/valid-color': 'off',\n 'core/valid-dimension': 'off',\n 'core/valid-duration': 'off',\n 'core/valid-typography': 'off',\n },\n },\n },\n { cwd },\n ),\n logger,\n });\n\n await traverseAsync(document, {\n async enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n const hex = (node.value.members[$valueI]!.value as momoa.StringNode).value;\n node.value.members[$valueI]!.value = momoa.parse(\n JSON.stringify({\n ...token.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as momoa.StringNode).value;\n const hex = (mode.members[i]!.value as momoa.StringNode).value;\n mode.members[i]!.value = momoa.parse(\n JSON.stringify({\n ...token.mode[modeName]!.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n }\n }\n }\n }\n break;\n }\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n node.value.members[$valueI]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n }\n }\n }\n }\n break;\n }\n case 'typography': {\n if (node.value.members[$valueI]?.value.type !== 'Object') {\n return;\n }\n node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeTypography(mode.members[i]!.value as momoa.ObjectNode);\n }\n }\n }\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nfunction normalizeDurationDimension(node: momoa.StringNode) {\n const value = Number.parseFloat(node.value);\n if (!Number.isFinite(value)) {\n return node;\n }\n (node as any).type = 'Object';\n (node as any).members = (\n momoa.parse(JSON.stringify({ value, unit: node.value.replace(String(value), '') })).body as momoa.ObjectNode\n ).members;\n delete (node as any).value;\n return node;\n}\n\nfunction normalizeTypography(node: momoa.ObjectNode) {\n const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);\n if (!fontFamily) {\n node.members.push((momoa.parse('{\"fontFamily\":[\"inherit\"]}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontSize) {\n node.members.push((momoa.parse('{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontWeight) {\n node.members.push((momoa.parse('{\"fontWeight\":400}').body as momoa.ObjectNode).members[0]!);\n }\n if (!letterSpacing) {\n node.members.push((momoa.parse('{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!lineHeight) {\n node.members.push((momoa.parse('{\"lineHeight\":1}').body as momoa.ObjectNode).members[0]!);\n }\n return node;\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}