@terrazzo/cli 2.0.0-beta.1 → 2.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { BuildRunnerResult, Config, ConfigInit, Logger } from "@terrazzo/parser";
2
- import * as url0 from "url";
3
2
 
4
3
  //#region src/shared.d.ts
5
- declare const cwd: url0.URL;
6
- declare const DEFAULT_CONFIG_PATH: url0.URL;
7
- declare const DEFAULT_TOKENS_PATH: url0.URL;
4
+ declare const cwd: URL;
5
+ declare const DEFAULT_CONFIG_PATH: URL;
6
+ declare const DEFAULT_TOKENS_PATH: URL;
8
7
  type Command = 'build' | 'check' | 'help' | 'init' | 'version';
9
8
  declare const GREEN_CHECK: string;
10
9
  interface Flags {
@@ -31,7 +30,7 @@ declare function loadConfig({
31
30
  logger
32
31
  }: LoadConfigOptions): Promise<{
33
32
  config: ConfigInit;
34
- configPath: string;
33
+ configPath: string | undefined;
35
34
  }>;
36
35
  /** load tokens */
37
36
  declare function loadTokens(tokenPaths: URL[], {
@@ -53,7 +52,7 @@ declare function resolveTokenPath(filename: string, {
53
52
  logger
54
53
  }: {
55
54
  logger: Logger;
56
- }): url0.URL;
55
+ }): URL;
57
56
  /** Print time elapsed */
58
57
  declare function time(start: number): string;
59
58
  //#endregion
@@ -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"],"mappings":";;;cASa,GAAA,EAAG,GAAA;AAAA,cACH,mBAAA,EAAmB,GAAA;AAAA,cACnB,mBAAA,EAAmB,GAAA;AAAA,KAEpB,OAAA;AAAA,cAEC,WAAA;AAAA,UAEI,KAAA;EAR6C;EAU5D,MAAA;EATqE;EAWrE,GAAA;EAX8B;EAa9B,IAAA;EAZW;EAcX,KAAA;;EAEA,OAAA;AAAA;AAAA,UAGe,iBAAA;EACf,GAAA,EAAK,OAAA;EACL,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,MAAA;AAAA;AAlBV;AAAA,iBAsBsB,UAAA,CAAA;EAAa,GAAA;EAAK,KAAA;EAAO;AAAA,GAAU,iBAAA,GAAiB,OAAA;;;;AApB1E;AAAA,iBA2GsB,UAAA,CAAW,UAAA,EAAY,GAAA;EAAS;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,OAAA;;;;;iBAiGlE,UAAA,CAAW,OAAA;;iBAKX,YAAA,CAAa,OAAA,UAAiB,SAAA;AApM9C;AAAA,iBAyMgB,aAAA,CAAc,QAAA;;iBAgBd,gBAAA,CAAiB,QAAA;EAAoB;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,GAAA;;iBAWjE,IAAA,CAAK,KAAA;;;UChPJ,YAAA;EACf,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,UAAA;EACR,UAAA;EACA,MAAA,EAAQ,MAAA;AAAA;ADZV;AAAA,iBCgBsB,QAAA,CAAA;EAAW,MAAA;EAAQ,UAAA;EAAY,KAAA;EAAO;AAAA,GAAU,YAAA,GAAY,OAAA;;iBAoFlE,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;EAAQ;AAAA;EAAY,MAAA,EAAQ,UAAA;EAAY,MAAA,EAAQ,MAAA;AAAA;;;UC1GvF,YAAA;;EAEf,WAAA;EACA,MAAA,EAAQ,UAAA;EACR,MAAA,EAAQ,MAAA;AAAA;;iBAIY,QAAA,CAAA;EAAW,MAAA;EAAQ,MAAA;EAAQ;AAAA,GAAe,YAAA,GAAY,OAAA;;;;iBCX5D,OAAA,CAAA;;;UCoFC,WAAA;EACf,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAGY,OAAA,CAAA;EAAU;AAAA,GAAU,WAAA,GAAW,OAAA;;;UChFpC,eAAA;EACf,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,UAAA;EACR,UAAA;EACA,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAGY,MAAA,CAAA;EAAS,MAAA;EAAQ;AAAA,GAAU,eAAA,GAAe,OAAA;;;UCR/C,gBAAA;EACf,MAAA,EAAQ,MAAA;EACR,MAAA,EAAQ,GAAA;AAAA;AAAA,iBASY,YAAA,CAAa,QAAA;EAAoB,MAAA;EAAQ;AAAA,GAAU,gBAAA,GAAgB,OAAA;;;iBCjBzE,UAAA,CAAA;;;iBCeA,YAAA,CAAa,MAAA,EAAQ,MAAA,GAAS,UAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
3
  import { build, defineConfig as defineConfig$1, parse } from "@terrazzo/parser";
4
- import fs, { createReadStream, createWriteStream } from "node:fs";
4
+ import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import pc from "picocolors";
7
7
  import { createServer } from "vite";
@@ -10,12 +10,12 @@ import { ViteNodeServer } from "vite-node/server";
10
10
  import chokidar from "chokidar";
11
11
  import yamlToMomoa from "yaml-to-momoa";
12
12
  import { spawn } from "node:child_process";
13
+ import fs$1 from "node:fs/promises";
13
14
  import { confirm, intro, multiselect, outro, select, spinner } from "@clack/prompts";
14
15
  import { isAlias, pluralize } from "@terrazzo/token-tools";
15
16
  import { detect } from "detect-package-manager";
16
17
  import { generate } from "escodegen";
17
18
  import { parseModule } from "meriyah";
18
- import { readdir } from "node:fs/promises";
19
19
  import { Readable, Writable } from "node:stream";
20
20
  import { serve } from "@hono/node-server";
21
21
  import mime from "mime";
@@ -150,18 +150,18 @@ async function loadTokens(tokenPaths, { logger }) {
150
150
  group: "config",
151
151
  message: "FIGMA_ACCESS_TOKEN not set"
152
152
  });
153
- const res$1 = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {
153
+ const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {
154
154
  method: "GET",
155
155
  headers
156
156
  });
157
- if (res$1.ok) allTokens.push({
157
+ if (res.ok) allTokens.push({
158
158
  filename,
159
- src: await res$1.text()
159
+ src: await res.text()
160
160
  });
161
- const message = res$1.status !== 404 ? JSON.stringify(await res$1.json(), void 0, 2) : "";
161
+ const message = res.status !== 404 ? JSON.stringify(await res.json(), void 0, 2) : "";
162
162
  logger.error({
163
163
  group: "config",
164
- message: `Figma responded with ${res$1.status}${message ? `:\n${message}` : ""}`
164
+ message: `Figma responded with ${res.status}${message ? `:\n${message}` : ""}`
165
165
  });
166
166
  break;
167
167
  }
@@ -400,6 +400,12 @@ const INSTALL_COMMAND = {
400
400
  pnpm: "add -D --silent",
401
401
  bun: "install -D --silent"
402
402
  };
403
+ const SYNTAX_SETTINGS = { format: {
404
+ indent: { style: " " },
405
+ quotes: "single",
406
+ semicolons: true
407
+ } };
408
+ const EXAMPLE_TOKENS_PATH = "my-tokens.tokens.json";
403
409
  const DESIGN_SYSTEMS = {
404
410
  "adobe-spectrum": {
405
411
  name: "Spectrum",
@@ -441,19 +447,19 @@ async function initCmd({ logger }) {
441
447
  try {
442
448
  intro("⛋ Welcome to Terrazzo");
443
449
  const packageManager = await detect({ cwd: fileURLToPath(cwd) });
444
- const { config, configPath } = await loadConfig({
450
+ const { config, configPath = "terrazzo.config.ts" } = await loadConfig({
445
451
  cmd: "init",
446
452
  flags: {},
447
453
  logger
448
454
  });
449
- const relConfigPath = configPath ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath))) : void 0;
450
- let tokensPath = config.tokens[0];
455
+ const tokensPath = config.tokens[0];
456
+ const hasExistingConfig = fs.existsSync(configPath);
451
457
  let startFromDS = !(tokensPath && fs.existsSync(tokensPath));
452
458
  if (tokensPath && fs.existsSync(tokensPath)) {
453
459
  if (await confirm({ message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?` })) startFromDS = true;
454
- } else tokensPath = DEFAULT_TOKENS_PATH;
460
+ }
455
461
  if (startFromDS) {
456
- if (DESIGN_SYSTEMS[await select({
462
+ const ds = DESIGN_SYSTEMS[await select({
457
463
  message: "Start from existing design system?",
458
464
  options: [...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({
459
465
  value: id,
@@ -462,7 +468,8 @@ async function initCmd({ logger }) {
462
468
  value: "none",
463
469
  label: "None"
464
470
  }]
465
- })]) {
471
+ })];
472
+ if (ds) {
466
473
  const s = spinner();
467
474
  s.start("Downloading");
468
475
  await new Promise((resolve, reject) => {
@@ -470,8 +477,14 @@ async function initCmd({ logger }) {
470
477
  subprocess.on("error", reject);
471
478
  subprocess.on("exit", resolve);
472
479
  });
473
- await s.stop("Download complete");
474
- }
480
+ s.stop("Download complete");
481
+ if (hasExistingConfig) await updateConfigTokens(configPath, ds.tokens);
482
+ else await newConfigFile(configPath, ds.tokens);
483
+ } else startFromDS = false;
484
+ }
485
+ if (!hasExistingConfig) {
486
+ await newConfigFile(configPath, [EXAMPLE_TOKENS_PATH]);
487
+ await fs$1.writeFile(EXAMPLE_TOKENS_PATH, JSON.stringify(EXAMPLE_TOKENS, void 0, 2));
475
488
  }
476
489
  const existingPlugins = config.plugins.map((p) => p.name);
477
490
  const pluginSelection = await multiselect({
@@ -500,7 +513,7 @@ async function initCmd({ logger }) {
500
513
  if (newPlugins?.length) {
501
514
  const plugins = newPlugins.map((p) => ({
502
515
  specifier: p.replace("@terrazzo/plugin-", ""),
503
- package: p
516
+ path: p
504
517
  }));
505
518
  const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, "plugin", "plugins")}`;
506
519
  const s = spinner();
@@ -511,77 +524,27 @@ async function initCmd({ logger }) {
511
524
  subprocess.on("exit", resolve);
512
525
  });
513
526
  s.message("Updating config");
514
- if (configPath) {
515
- const ast = parseModule(fs.readFileSync(configPath, "utf8"));
516
- const astExport = ast.body.find((node) => node.type === "ExportDefaultDeclaration");
517
- ast.body.push(...plugins.map((p) => ({
518
- type: "ImportDeclaration",
519
- source: {
520
- type: "Literal",
521
- value: p.package
522
- },
523
- specifiers: [{
524
- type: "ImportDefaultSpecifier",
525
- local: {
526
- type: "Identifier",
527
- name: p.specifier
528
- }
529
- }],
530
- attributes: []
531
- })));
532
- if (!astExport) {
533
- logger.error({
534
- group: "config",
535
- message: `SyntaxError: ${relConfigPath} does not have default export.`
536
- });
537
- return;
538
- }
539
- const astConfig = astExport.declaration.type === "CallExpression" ? astExport.declaration.arguments[0] : astExport.declaration;
540
- if (astConfig.type !== "ObjectExpression") {
541
- logger.error({
542
- group: "config",
543
- message: `Config: expected object default export, received ${astConfig.type}`
544
- });
545
- return;
546
- }
547
- const pluginsArray = astConfig.properties.find((property) => property.type === "Property" && property.key.type === "Identifier" && property.key.name === "plugins")?.value;
548
- const pluginsAst = plugins.map((p) => ({
549
- type: "CallExpression",
550
- callee: {
551
- type: "Identifier",
552
- name: p.specifier
553
- },
554
- arguments: [],
555
- optional: false
556
- }));
557
- if (pluginsArray) pluginsArray.elements.push(...pluginsAst);
558
- else astConfig.properties.push({
559
- type: "Property",
560
- key: {
561
- type: "Identifier",
562
- name: "plugins"
563
- },
564
- value: {
565
- type: "ArrayExpression",
566
- elements: pluginsAst
567
- },
568
- kind: "init",
569
- computed: false,
570
- method: false,
571
- shorthand: false
572
- });
573
- fs.writeFileSync(configPath, generate(ast, { format: {
574
- indent: { style: " " },
575
- quotes: "single",
576
- semicolons: true
577
- } }));
578
- } else fs.writeFileSync(DEFAULT_CONFIG_PATH, `import { defineConfig } from '@terrazzo/cli';
579
- ${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join("\n")}
527
+ await updateConfigPlugins(configPath, plugins);
528
+ s.stop(`Installed ${pluginCount}`);
529
+ }
530
+ if (!startFromDS && !newPlugins?.length) {
531
+ outro("Nothing to do. Exiting.");
532
+ return;
533
+ }
534
+ outro("⛋ Done! 🎉");
535
+ } catch (err) {
536
+ printError(err.message);
537
+ process.exit(1);
538
+ }
539
+ }
540
+ async function newConfigFile(configPath, tokens, imports = []) {
541
+ await fs$1.writeFile(configPath, `import { defineConfig } from '@terrazzo/cli';
542
+ ${imports.map((p) => `import ${p.specifier} from '${p.path}';`).join("\n")}
580
543
 
581
544
  export default defineConfig({
582
- tokens: ['./tokens.json'],
545
+ tokens: ['${tokens.join("', '")}'],
583
546
  plugins: [
584
- ${plugins.map((p) => `${p.specifier}(),`).join("\n ")}
547
+ ${imports.length ? imports.map((p) => `${p.specifier}(),`).join("\n ") : "/** @see https://terrazzo.app/docs */"}
585
548
  ],
586
549
  outDir: './dist/',
587
550
  lint: {
@@ -610,14 +573,279 @@ export default defineConfig({
610
573
  },
611
574
  },
612
575
  });`);
613
- s.stop(`Installed ${pluginCount}`);
614
- }
615
- outro("⛋ Done! 🎉");
616
- } catch (err) {
617
- printError(err.message);
618
- process.exit(1);
576
+ }
577
+ function getConfigObjFromAst(ast, configPath) {
578
+ const astExport = ast.body.find((node) => node.type === "ExportDefaultDeclaration");
579
+ if (!astExport) {
580
+ const relConfigPath = configPath ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath))) : void 0;
581
+ throw new Error(`SyntaxError: ${relConfigPath} does not have default export.`);
619
582
  }
583
+ const astConfig = astExport.declaration.type === "CallExpression" ? astExport.declaration.arguments[0] : astExport.declaration;
584
+ if (astConfig.type !== "ObjectExpression") throw new Error(`Config: expected object default export, received ${astConfig.type}.`);
585
+ return astConfig;
620
586
  }
587
+ async function updateConfigTokens(configPath, tokens) {
588
+ const ast = parseModule(await fs$1.readFile(configPath, "utf8"));
589
+ const astConfig = getConfigObjFromAst(ast, configPath);
590
+ let tokensKey = astConfig.properties.find((p) => p.type === "Property" && p.key.type === "Identifier" && p.key.name === "tokens");
591
+ if (!tokensKey) {
592
+ tokensKey = {
593
+ type: "Property",
594
+ key: {
595
+ type: "Identifier",
596
+ name: "tokens"
597
+ },
598
+ method: false,
599
+ computed: false,
600
+ shorthand: false,
601
+ value: {
602
+ type: "ArrayExpression",
603
+ elements: tokens.map((value) => ({
604
+ type: "Literal",
605
+ value,
606
+ raw: `'${value}'`
607
+ }))
608
+ }
609
+ };
610
+ astConfig.properties.unshift(tokensKey);
611
+ }
612
+ await fs$1.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));
613
+ }
614
+ /**
615
+ * Add plugin imports
616
+ * note: this has the potential to duplicate plugins, but we tried our
617
+ * best to filter already, and this may be the user’s fault if they
618
+ * selected to install a plugin already installed. But also, this is
619
+ * easily-fixable, so let’s not waste too much time here (and possibly
620
+ * introduce bugs).
621
+ */
622
+ async function updateConfigPlugins(configPath, plugins) {
623
+ const ast = parseModule(await fs$1.readFile(configPath, "utf8"));
624
+ ast.body.push(...plugins.map((p) => ({
625
+ type: "ImportDeclaration",
626
+ source: {
627
+ type: "Literal",
628
+ value: p.path
629
+ },
630
+ specifiers: [{
631
+ type: "ImportDefaultSpecifier",
632
+ local: {
633
+ type: "Identifier",
634
+ name: p.specifier
635
+ }
636
+ }],
637
+ attributes: []
638
+ })));
639
+ const astConfig = getConfigObjFromAst(ast, configPath);
640
+ const pluginsArray = astConfig.properties.find((property) => property.type === "Property" && property.key.type === "Identifier" && property.key.name === "plugins")?.value;
641
+ const pluginsAst = plugins.map((p) => ({
642
+ type: "CallExpression",
643
+ callee: {
644
+ type: "Identifier",
645
+ name: p.specifier
646
+ },
647
+ arguments: [],
648
+ optional: false
649
+ }));
650
+ if (pluginsArray) pluginsArray.elements.push(...pluginsAst);
651
+ else astConfig.properties.push({
652
+ type: "Property",
653
+ key: {
654
+ type: "Identifier",
655
+ name: "plugins"
656
+ },
657
+ value: {
658
+ type: "ArrayExpression",
659
+ elements: pluginsAst
660
+ },
661
+ kind: "init",
662
+ computed: false,
663
+ method: false,
664
+ shorthand: false
665
+ });
666
+ await fs$1.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));
667
+ }
668
+ const EXAMPLE_TOKENS = {
669
+ color: {
670
+ $description: "Color tokens",
671
+ black: {
672
+ "100": {
673
+ $type: "color",
674
+ $value: {
675
+ colorSpace: "srgb",
676
+ components: [
677
+ .047,
678
+ .047,
679
+ .047
680
+ ],
681
+ alpha: .05,
682
+ hex: "#0c0c0d"
683
+ }
684
+ },
685
+ "200": {
686
+ $type: "color",
687
+ $value: {
688
+ colorSpace: "srgb",
689
+ components: [
690
+ .047,
691
+ .047,
692
+ .047
693
+ ],
694
+ alpha: .1,
695
+ hex: "#0c0c0d"
696
+ }
697
+ },
698
+ "300": {
699
+ $type: "color",
700
+ $value: {
701
+ colorSpace: "srgb",
702
+ components: [
703
+ .047,
704
+ .047,
705
+ .047
706
+ ],
707
+ alpha: .2,
708
+ hex: "#0c0c0d"
709
+ }
710
+ },
711
+ "400": {
712
+ $type: "color",
713
+ $value: {
714
+ colorSpace: "srgb",
715
+ components: [
716
+ .047,
717
+ .047,
718
+ .047
719
+ ],
720
+ alpha: .34,
721
+ hex: "#0c0c04"
722
+ }
723
+ },
724
+ "500": {
725
+ $type: "color",
726
+ $value: {
727
+ colorSpace: "srgb",
728
+ components: [
729
+ .047,
730
+ .047,
731
+ .047
732
+ ],
733
+ alpha: .7,
734
+ hex: "#0c0c0d"
735
+ }
736
+ },
737
+ "600": {
738
+ $type: "color",
739
+ $value: {
740
+ colorSpace: "srgb",
741
+ components: [
742
+ .047,
743
+ .047,
744
+ .047
745
+ ],
746
+ alpha: .8,
747
+ hex: "#0c0c0d"
748
+ }
749
+ },
750
+ "700": {
751
+ $type: "color",
752
+ $value: {
753
+ colorSpace: "srgb",
754
+ components: [
755
+ .047,
756
+ .047,
757
+ .047
758
+ ],
759
+ alpha: .85,
760
+ hex: "#0c0c0d"
761
+ }
762
+ },
763
+ "800": {
764
+ $type: "color",
765
+ $value: {
766
+ colorSpace: "srgb",
767
+ components: [
768
+ .047,
769
+ .047,
770
+ .047
771
+ ],
772
+ alpha: .9,
773
+ hex: "#0c0c0d"
774
+ }
775
+ },
776
+ "900": {
777
+ $type: "color",
778
+ $value: {
779
+ colorSpace: "srgb",
780
+ components: [
781
+ .047,
782
+ .047,
783
+ .047
784
+ ],
785
+ alpha: .95,
786
+ hex: "#0c0c0d"
787
+ }
788
+ },
789
+ "1000": {
790
+ $type: "color",
791
+ $value: {
792
+ colorSpace: "srgb",
793
+ components: [
794
+ .047,
795
+ .047,
796
+ .047
797
+ ],
798
+ alpha: 0,
799
+ hex: "#0c0c0d"
800
+ }
801
+ }
802
+ }
803
+ },
804
+ border: {
805
+ $description: "Border tokens",
806
+ default: {
807
+ type: "border",
808
+ $value: {
809
+ color: "{color.black.900}",
810
+ style: "solid",
811
+ width: {
812
+ value: 1,
813
+ unit: "px"
814
+ }
815
+ }
816
+ }
817
+ },
818
+ radius: {
819
+ $description: "Corner radius tokens",
820
+ "100": { $value: {
821
+ value: .25,
822
+ unit: "rem"
823
+ } }
824
+ },
825
+ space: {
826
+ $description: "Dimension tokens",
827
+ "100": { $value: {
828
+ value: .25,
829
+ unit: "rem"
830
+ } }
831
+ },
832
+ typography: {
833
+ $description: "Typography tokens",
834
+ body: {
835
+ $type: "typography",
836
+ $value: {
837
+ fontFamily: "{typography.family.sans}",
838
+ fontSize: "{typography.scale.03}",
839
+ fontWeight: "{typography.weight.regular}",
840
+ letterSpacing: {
841
+ value: 0,
842
+ unit: "em"
843
+ },
844
+ lineHeight: 1
845
+ }
846
+ }
847
+ }
848
+ };
621
849
 
622
850
  //#endregion
623
851
  //#region src/lab.ts
@@ -625,7 +853,7 @@ async function labCmd({ config, logger }) {
625
853
  /** TODO: handle multiple files */
626
854
  const [tokenFileUrl] = config.tokens;
627
855
  const staticFiles = /* @__PURE__ */ new Set();
628
- const dirEntries = await readdir(fileURLToPath(import.meta.resolve("./lab")), {
856
+ const dirEntries = await fs$1.readdir(fileURLToPath(import.meta.resolve("./lab")), {
629
857
  withFileTypes: true,
630
858
  recursive: true
631
859
  });
@@ -639,18 +867,18 @@ async function labCmd({ config, logger }) {
639
867
  overrideGlobalObjects: false,
640
868
  async fetch(request) {
641
869
  const pathname = new URL(request.url).pathname;
642
- if (pathname === "/") return new Response(Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve("./lab/index.html")))), { headers: { "Content-Type": "text/html" } });
870
+ if (pathname === "/") return new Response(Readable.toWeb(fs.createReadStream(fileURLToPath(import.meta.resolve("./lab/index.html")))), { headers: { "Content-Type": "text/html" } });
643
871
  if (pathname === "/api/tokens") {
644
- if (request.method === "GET") return new Response(Readable.toWeb(createReadStream(tokenFileUrl)), { headers: {
872
+ if (request.method === "GET") return new Response(Readable.toWeb(fs.createReadStream(tokenFileUrl)), { headers: {
645
873
  "Content-Type": "application/json",
646
874
  "Cache-Control": "no-cache"
647
875
  } });
648
876
  else if (request.method === "POST" && request.body) {
649
- await request.body.pipeTo(Writable.toWeb(createWriteStream(tokenFileUrl)));
877
+ await request.body.pipeTo(Writable.toWeb(fs.createWriteStream(tokenFileUrl)));
650
878
  return new Response(JSON.stringify({ success: true }), { headers: { "Content-Type": "application/json" } });
651
879
  }
652
880
  }
653
- if (staticFiles.has(pathname)) return new Response(Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))), { headers: { "Content-Type": mime.getType(pathname) ?? "application/octet-stream" } });
881
+ if (staticFiles.has(pathname)) return new Response(Readable.toWeb(fs.createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))), { headers: { "Content-Type": mime.getType(pathname) ?? "application/octet-stream" } });
654
882
  return new Response("Not found", { status: 404 });
655
883
  }
656
884
  }, (info) => {
@@ -721,10 +949,10 @@ async function normalizeCmd(filename, { logger, output }) {
721
949
  const mode = getObjMember($extensions, "mode");
722
950
  if (mode?.type === "Object") for (let i = 0; i < mode.members.length; i++) {
723
951
  const modeName = mode.members[i].name.value;
724
- const hex$1 = mode.members[i].value.value;
952
+ const hex = mode.members[i].value.value;
725
953
  mode.members[i].value = momoa.parse(JSON.stringify({
726
954
  ...token.mode[modeName].$value,
727
- hex: hex$1.startsWith("#") ? hex$1.slice(0, 7) : void 0
955
+ hex: hex.startsWith("#") ? hex.slice(0, 7) : void 0
728
956
  })).body;
729
957
  }
730
958
  }