@parity-app/cli 0.7.4 → 0.7.6

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/bin.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { c as CodedError, d as errorDetails, f as readErrorDetails, i as jsonText, l as closest, s as plainObject, t as checkData, u as errorCodes } from "./schema-CemdtCeF.mjs";
3
- import { _ as requests, a as describeExec, c as describeProps, f as setCaller, g as requestJsonSchema, h as replies, i as describeConsole, l as describeStatus, m as readRequest, n as describeAccessibility, o as describeModes, p as mcpCallerName, r as describeComponents, s as describeProblems, t as call, u as describeTokens, v as skillRequest } from "./client-D6bpjpy-.mjs";
2
+ import { c as CodedError, d as errorDetails, f as readErrorDetails, i as jsonText, l as closest, s as plainObject, t as checkData, u as errorCodes } from "./schema-Dp5Jhloe.mjs";
3
+ import { _ as requests, a as describeExec, c as describeProps, f as setCaller, g as requestJsonSchema, h as replies, i as describeConsole, l as describeStatus, m as readRequest, n as describeAccessibility, o as describeModes, p as mcpCallerName, r as describeComponents, s as describeProblems, t as call, u as describeTokens, v as skillRequest } from "./client-BkLeG26A.mjs";
4
4
  import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
5
5
  import { dirname, join, normalize, relative, resolve, sep } from "node:path";
6
6
  import { parseArgs } from "node:util";
@@ -160,8 +160,8 @@ const appErrorsFile = jsonText(z.record(z.string(), z.string()));
160
160
  */
161
161
  async function runCheck(library, options) {
162
162
  if (!library) throw new Error("parity lib check <library> [--tab t] [--mode m]");
163
- const { componentNode, generateId, librarySource, withLibraryContext } = await import("./src-Btr2eWdT.mjs");
164
- const { newestEntries, registryDir } = await import("./src-Q382DbAK.mjs");
163
+ const { componentNode, generateId, librarySource, withLibraryContext } = await import("./src-CbLrA8BA.mjs");
164
+ const { newestEntries, registryDir } = await import("./src-DHuMBGiB.mjs");
165
165
  const entry = (await newestEntries()).find((item) => item.manifest.id === library);
166
166
  if (!entry) throw new Error(`The registry has no library "${library}"`);
167
167
  const list = entry.manifest.components?.list ?? {};
@@ -295,8 +295,8 @@ function describeCheck(report) {
295
295
  * because it reads the project's files and its own copy of TypeScript.
296
296
  */
297
297
  async function runLib(packageName, options) {
298
- const { appManifestPath, generateLibrary, manifestText, mergeManifest, reviseLibrary } = await import("./src-Bf12xdm5.mjs");
299
- const { covers, registryDir, registryEntries } = await import("./src-Q382DbAK.mjs");
298
+ const { appManifestPath, generateLibrary, manifestText, mergeManifest, reviseLibrary } = await import("./src-CMPL5C8p.mjs");
299
+ const { covers, registryDir, registryEntries } = await import("./src-DHuMBGiB.mjs");
300
300
  const spec = packageName === void 0 ? void 0 : packageSpec(packageName);
301
301
  let root = resolve(options.root ?? ".");
302
302
  if (spec && (spec.version !== void 0 || options.registry && !options.root)) {
@@ -307,7 +307,7 @@ async function runLib(packageName, options) {
307
307
  console.error(`Installing ${spec.name} ${version} on its own…`);
308
308
  root = await installedVersion(spec.name, version);
309
309
  }
310
- const { parseLibraryEdits } = await import("./src-Bf12xdm5.mjs");
310
+ const { parseLibraryEdits } = await import("./src-CMPL5C8p.mjs");
311
311
  const trialEdits = options.edits ? parseLibraryEdits(JSON.parse(await readFile(resolve(options.edits), "utf8"))) : void 0;
312
312
  const recordedId = options.registry && spec ? options.id ?? (await registryEntries()).find((entry) => entry.manifest.package?.name === spec.name)?.manifest.id : void 0;
313
313
  const appErrors = recordedId ? await readAppErrors(registryDir(), recordedId) : void 0;
@@ -1,4 +1,4 @@
1
- import { a as nonBlankString, c as CodedError, f as readErrorDetails, i as jsonText, p as unknownReference, s as plainObject, t as checkData } from "./schema-CemdtCeF.mjs";
1
+ import { a as nonBlankString, c as CodedError, f as readErrorDetails, i as jsonText, p as unknownReference, s as plainObject, t as checkData } from "./schema-Dp5Jhloe.mjs";
2
2
  import { join } from "node:path";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export { t as call, n as describeAccessibility, r as describeComponents, i as describeConsole, a as describeExec, o as describeModes, s as describeProblems, c as describeProps, l as describeStatus, u as describeTokens, d as registry, f as setCaller } from "./client-D6bpjpy-.mjs";
1
+ export { t as call, n as describeAccessibility, r as describeComponents, i as describeConsole, a as describeExec, o as describeModes, s as describeProblems, c as describeProps, l as describeStatus, u as describeTokens, d as registry, f as setCaller } from "./client-BkLeG26A.mjs";
@@ -95,7 +95,7 @@ function readErrorDetails(value) {
95
95
  // ../core/src/schema.ts
96
96
  /**
97
97
  * Checks for data Parity didn't make (PAR-578): files, agent input, environment variables, other programs' JSON. A zod
98
- * schema is both the check and the type. A failed check reads as core's hand-written ones in `validate.ts` do: a JSON
98
+ * schema is both the check and the type. A failed check reads as core's hand-written ones in `validate.ts` did: a JSON
99
99
  * pointer to the value at fault, then what was expected there, as in `/containers/0/name: expected a string`.
100
100
  */
101
101
  /** An object with string keys, and not an array or null. */
@@ -204,7 +204,7 @@ function expectation(issue) {
204
204
  if (issue.code === "invalid_type") return typeName(issue.expected);
205
205
  if (issue.code === "invalid_value") return issue.values.map(literal).join(" or ");
206
206
  }
207
- /** Zod's issues in `validate.ts`'s words. Messages a schema gives itself win, and anything else keeps zod's own. */
207
+ /** Zod's issues in the words of core's old `validate.ts`. Messages a schema gives itself win, and anything else keeps zod's own. */
208
208
  function issueText(issue) {
209
209
  switch (issue.code) {
210
210
  case "invalid_type": return `expected ${typeName(issue.expected)}`;
@@ -1,4 +1,4 @@
1
- import { n as fileObject, o as parseData, r as finiteNumber, s as plainObject } from "./schema-CemdtCeF.mjs";
1
+ import { n as fileObject, o as parseData, r as finiteNumber, s as plainObject } from "./schema-Dp5Jhloe.mjs";
2
2
  import { z } from "zod";
3
3
  // ../core/src/adapters.ts
4
4
  const packageVersions = z.record(z.string(), z.string());
@@ -341,6 +341,7 @@ const detectionCorrections = fileObject({
341
341
  include: z.array(componentRef).optional(),
342
342
  exclude: z.unknown().optional()
343
343
  }).transform(({ exclude: _dropped, ...corrections }) => corrections);
344
+ /** Text on the canvas outside any design, as a project file or the clipboard holds it. */
344
345
  const noteSpec = fileObject({
345
346
  id: z.string(),
346
347
  text: z.string(),
@@ -535,6 +536,7 @@ const imageFits = [
535
536
  "contain",
536
537
  "fill"
537
538
  ];
539
+ /** Who made a stock image and where it came from, as an image node or a dragged image holds it. */
538
540
  const imageCredit = fileObject({
539
541
  name: z.string(),
540
542
  url: z.string(),
@@ -652,6 +654,7 @@ const stateSpec = fileObject({
652
654
  */
653
655
  overrides: nodePatches.optional()
654
656
  });
657
+ /** One design, as a project file or the clipboard holds it (see `ContainerSpec`). */
655
658
  const containerSpec = fileObject({
656
659
  id: z.string(),
657
660
  name: z.string(),
@@ -750,42 +753,22 @@ const canvasDocument = fileObject({
750
753
  /** The source each lens reads, where the person switched from the one Parity picked. */
751
754
  sources: lensSources.optional()
752
755
  });
753
- /** Reads a project file, or throws `TypeError` with the first problem as `/json/pointer: message`. */
754
- function parseCanvasDocument(value) {
755
- return parseData(canvasDocument, value);
756
- }
757
- // ../core/src/validate.ts
758
- function expectObject(value, path) {
759
- if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError(`${path || "/"}: expected an object`);
760
- return value;
761
- }
762
- function expectString(value, path) {
763
- if (typeof value !== "string") throw new TypeError(`${path}: expected a string`);
764
- return value;
765
- }
766
- function expectNumber(value, path) {
767
- if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(`${path}: expected a number`);
768
- return value;
769
- }
770
- function expectArray(value, path) {
771
- if (!Array.isArray(value)) throw new TypeError(`${path}: expected an array`);
772
- return value;
773
- }
774
- function expectOneOf(value, options, path) {
775
- if (typeof value !== "string" || !options.includes(value)) throw new TypeError(`${path}: expected one of ${options.map((option) => `"${option}"`).join(", ")}`);
776
- return value;
777
- }
778
- function optional(value, parse) {
779
- return value === void 0 ? void 0 : parse(value);
780
- }
781
- /** Drops `undefined` entries, so parsed patches can be spread over defaults without erasing them. */
782
- function compact(value) {
783
- return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
784
- }
785
- function expectKnownKeys(value, keys, path) {
786
- for (const key of Object.keys(value)) if (!keys.includes(key)) throw new TypeError(`${path}/${key}: unknown property`);
787
- }
788
756
  // ../core/src/library.ts
757
+ const libraryBreakpoint = fileObject({
758
+ id: z.string(),
759
+ name: z.string(),
760
+ /** The width where it starts, in CSS pixels. */
761
+ width: finiteNumber
762
+ });
763
+ /** The package a manifest describes. */
764
+ const libraryPackage = fileObject({
765
+ /** Its name on npm, as in `@mui/material`. */
766
+ name: z.string(),
767
+ /** The version it was generated from. */
768
+ version: z.string().optional(),
769
+ /** The versions it describes, as a semver range such as `^9.0.0`. Unset means any. */
770
+ range: z.string().optional()
771
+ });
789
772
  /** How a component was recognised, which is also why it's believed to be one. */
790
773
  const componentEvidence = [
791
774
  "function",
@@ -809,6 +792,41 @@ const parentSignals = [
809
792
  "edit",
810
793
  "app"
811
794
  ];
795
+ /**
796
+ * A function returning these children. With `spread`, the object it's called with is spread onto the one element it
797
+ * returns, as MUI's `renderInput={(params) => <TextField {...params} />}`; `pass` names props of that element that take
798
+ * it whole, as React Aria's `{(segment) => <DateSegment segment={segment} />}`.
799
+ */
800
+ const sampleRender = fileObject({
801
+ get $render() {
802
+ return z.array(sampleChild);
803
+ },
804
+ spread: z.literal(true).optional(),
805
+ pass: z.array(z.string()).optional()
806
+ });
807
+ /** A component of the same library, by its name in `components.list`, with its props and children. */
808
+ const sampleComponent = fileObject({
809
+ component: z.string(),
810
+ props: plainObject.optional(),
811
+ get children() {
812
+ return z.array(sampleChild).optional();
813
+ }
814
+ });
815
+ /**
816
+ * Text, a component of the same library by its name in `components.list`, or a render function: what a part calls to
817
+ * draw, as children (`Field.Validity`) or as a prop's value (`renderInput`).
818
+ */
819
+ const sampleChild = z.union([
820
+ z.string(),
821
+ sampleRender,
822
+ sampleComponent
823
+ ]);
824
+ z.object({ $element: z.array(sampleChild) });
825
+ /** What a component needs to draw something: props with sample values, and children, as for a collection's items. */
826
+ const componentSample = fileObject({
827
+ props: plainObject.optional(),
828
+ children: z.array(sampleChild).optional()
829
+ });
812
830
  /** Whether a sample's prop value is elements. */
813
831
  function isSampleElement(value) {
814
832
  return typeof value === "object" && value !== null && Array.isArray(value.$element);
@@ -838,204 +856,316 @@ function renderSlotOf(sample) {
838
856
  render: entry[1]
839
857
  } : void 0;
840
858
  }
841
- const decoratorKeys = [
842
- "when",
859
+ /** A regular expression's source, checked by compiling it. */
860
+ const pattern = z.string().refine((source) => {
861
+ try {
862
+ new RegExp(source);
863
+ return true;
864
+ } catch {
865
+ return false;
866
+ }
867
+ }, "expected a regular expression");
868
+ const flag = z.boolean("expected a boolean");
869
+ /** What a component says about itself that a hand edit can change too. */
870
+ const componentFields = {
871
+ /** The type declarations that define it, relative to the package, for reading its props. */
872
+ declaration: z.string().optional(),
873
+ /** The family it belongs to in the Components panel, as Card, CardHeader and CardTitle share `Card`. */
874
+ group: z.string().optional(),
875
+ /**
876
+ * The components a part is placed inside, outermost first, as `["Accordion", "AccordionItem"]` for
877
+ * `AccordionTrigger`, and what said so.
878
+ */
879
+ parents: z.array(z.string()).optional(),
880
+ parentsFrom: z.enum(parentSignals).optional(),
881
+ /**
882
+ * Parents most examples show but it renders without (`DropdownMenuGroup`), a subset of `parents`: inserting it
883
+ * where the parents outside them are already leaves them out.
884
+ */
885
+ optionalParents: z.array(z.string()).optional(),
886
+ /**
887
+ * `true` when its parents need the other parts their samples hold around it to draw (a table's header beside the
888
+ * body a row is in): inserting it alone puts it in its outermost parent's whole sample, in place of the first like it.
889
+ */
890
+ parentParts: flag.optional(),
891
+ /** `false` for exports that draw nothing of their own, such as a context's consumer or a `RootProvider`. */
892
+ visual: flag.optional(),
893
+ /**
894
+ * `true` for a part the package renders inside its own components and that no example or docs page places
895
+ * (`ChartStyle` in `ChartContainer`, a Select's scroll buttons). It can still be placed; the Components panel lists
896
+ * it apart.
897
+ */
898
+ internal: flag.optional(),
899
+ /** What it needs to draw something: props with sample values, and children, as for a collection's items. */
900
+ sample: componentSample.optional()
901
+ };
902
+ const libraryComponent = fileObject({
903
+ as: z.enum(componentEvidence),
904
+ ...componentFields,
905
+ /** A hash of what it was found as and its own props, to tell what changed when the file is regenerated. */
906
+ fingerprint: z.string().optional(),
907
+ /** Its own props (not the HTML attributes it passes on), each with a hash of its type; `?` marks an optional one. */
908
+ props: z.record(z.string(), z.string()).optional()
909
+ });
910
+ const libraryComponentEdit = fileObject({
911
+ as: z.enum(componentEvidence).optional(),
912
+ ...componentFields
913
+ });
914
+ const libraryComponents = fileObject({
915
+ /** The module components are imported from. Defaults to the package name. */
916
+ import: z.string().optional(),
917
+ /**
918
+ * Components by the name they're imported by: an export, or `Namespace.Member` for libraries that group a
919
+ * component's parts, as Base UI's `Dialog.Root` does.
920
+ */
921
+ list: z.record(z.string(), libraryComponent)
922
+ });
923
+ /** One React component that draws an icon given as data, as Hugeicons' `HugeiconsIcon` does with its `icon` prop. */
924
+ const iconRenderer = fileObject({
925
+ import: z.string(),
926
+ component: z.string(),
927
+ prop: z.string()
928
+ });
929
+ const iconVariants = fileObject({
930
+ /**
931
+ * Splits an export name into named groups: `name`, and optionally `size` and `style`, for sets that write them into
932
+ * names (Fluent's `Add24Regular`). A name without a style has the default style.
933
+ */
934
+ pattern: pattern.optional(),
935
+ /** The prop that picks a style, for sets that take it as a prop (Phosphor's `weight`). */
936
+ prop: z.string().optional(),
937
+ /**
938
+ * The module each style's icons are imported from, for sets that keep each style in a module of its own, as
939
+ * Heroicons does in `@heroicons/react/16/solid`. The default style's is the set's `import`.
940
+ */
941
+ modules: z.record(z.string(), z.string()).optional(),
942
+ styles: z.array(z.string()).optional(),
943
+ sizes: z.array(finiteNumber).optional(),
944
+ /** What the picker shows first. An icon without a size in its name scales with the text. */
945
+ default: fileObject({
946
+ style: z.string().optional(),
947
+ size: finiteNumber.optional()
948
+ }).optional()
949
+ });
950
+ const libraryIcons = fileObject({
951
+ /** The module icons are imported from. Defaults to the package name. */
952
+ import: z.string().optional(),
953
+ /**
954
+ * `export` when every icon is a component of its own; otherwise the component that draws icons from data. A string
955
+ * is checked as one, so a renderer with a mistake in it reports the mistake rather than `expected "export"`.
956
+ */
957
+ render: z.union([z.string().pipe(z.literal("export")), iconRenderer]),
958
+ /** A regular expression for the export names that are icons. Defaults to every export that can be one. */
959
+ match: pattern.optional(),
960
+ /** Exports that look like icons but aren't, such as Lucide's generic `Icon` and its provider. */
961
+ exclude: z.array(z.string()).optional(),
962
+ /**
963
+ * For icons exported under several names, the one to insert where it isn't the shortest: the name the set's types
964
+ * don't mark deprecated (Phosphor's `GearIcon`, not `Gear`), or the one an icon is declared under rather than an
965
+ * alias. Read from the types when the file is generated.
966
+ */
967
+ prefer: z.array(z.string()).optional(),
968
+ /** Styles and sizes written into icon names, as in Fluent's `Add24Regular`. */
969
+ variants: iconVariants.optional(),
970
+ /** How many icons it had when it was generated. */
971
+ count: finiteNumber.optional(),
972
+ /**
973
+ * Words to find each icon by, from the set's own published metadata: its tags and categories, by the icon's name
974
+ * without a style or size (`Add` for Fluent's `Add24Regular`). Read when the file is generated, never typed by hand.
975
+ */
976
+ tags: z.record(z.string(), z.array(z.string())).optional(),
977
+ /** Where `tags` were read from, as `package@version/path`. */
978
+ tagSource: z.string().optional()
979
+ });
980
+ /**
981
+ * A decorator's value: JSON, or one of five forms that the guest works out for each frame. An object with one of the
982
+ * forms' keys must be that form; any other object is plain JSON, its values decorator values too.
983
+ *
984
+ * - `{ "$import": "pkg", "export": "name" }`: something the package exports, such as a theme object. `export` defaults
985
+ * to `default`.
986
+ * - `{ "$call": { "import": "pkg", "export": "name" }, "args": [...], "methods": [...] }`: what calling it returns.
987
+ * - `{ "$global": "theme", "values": { "dark": ... }, "default": ... }`: picked by the frame's global, which is the
988
+ * mode's option for that variable.
989
+ * - `{ "$frame": "root" | "host" | "body" }`: the frame's shadow root, the element it hangs from (which `:root[...]`
990
+ * rules match, as `:host(...)`), or the element standing in for its `<body>`. Also `document`, `dir`, `lang`, and
991
+ * `selector`, a CSS selector for the body alone.
992
+ * - `{ "$function": ... }`: a function returning the value it holds.
993
+ *
994
+ * Values are checked once, when their library file loads. The guest evaluates them on every frame without zod.
995
+ */
996
+ const decoratorValue = z.lazy(() => z.union([
997
+ z.string(),
998
+ finiteNumber,
999
+ z.boolean(),
1000
+ z.null(),
1001
+ z.array(decoratorValue),
1002
+ form("$import", importedValue),
1003
+ form("$call", madeValue),
1004
+ form("$global", globalValue),
1005
+ form("$frame", frameValue),
1006
+ form("$function", functionValue),
1007
+ plainValue
1008
+ ]));
1009
+ const valueForms = [
1010
+ "$import",
1011
+ "$call",
1012
+ "$global",
1013
+ "$frame",
1014
+ "$function"
1015
+ ];
1016
+ /** Something the package exports, such as a theme object. */
1017
+ const importedValue = fileObject({
1018
+ $import: z.string(),
1019
+ export: z.string().optional()
1020
+ });
1021
+ /**
1022
+ * A value the package makes by calling one of its own functions, as an example does (Chakra's
1023
+ * `collection={createTreeCollection({ rootNode })}`): the canvas calls it with `args`, once per frame.
1024
+ */
1025
+ const madeValue = fileObject({
1026
+ $call: fileObject({
1027
+ import: z.string(),
1028
+ export: z.string()
1029
+ }),
1030
+ args: z.array(decoratorValue).optional(),
1031
+ /**
1032
+ * Methods called on what it makes, in order, as the examples call them (Chakra's `toaster.create({ title })`), so a
1033
+ * toaster is drawn with a toast in it.
1034
+ */
1035
+ methods: z.array(fileObject({
1036
+ method: z.string(),
1037
+ args: z.array(decoratorValue).optional()
1038
+ })).optional()
1039
+ });
1040
+ /** Picked by the frame's global, which is the mode's option for that variable, else `default`. */
1041
+ const globalValue = fileObject({
1042
+ $global: z.string(),
1043
+ values: z.record(z.string(), decoratorValue),
1044
+ default: decoratorValue.optional()
1045
+ });
1046
+ /** Part of the frame itself. */
1047
+ const frameValue = fileObject({ $frame: z.enum([
1048
+ "root",
1049
+ "host",
1050
+ "body",
1051
+ "document",
1052
+ "dir",
1053
+ "lang",
1054
+ "selector"
1055
+ ]) });
1056
+ /** A function returning the value it holds. */
1057
+ const functionValue = fileObject({ $function: decoratorValue });
1058
+ /**
1059
+ * An object with a form's key is that form. Any other object is refused as another type of value would be, which
1060
+ * `parseData` passes over, so a broken form reports its own mistake and not the closest of the other forms.
1061
+ */
1062
+ function form(key, schema) {
1063
+ return z.unknown().superRefine((value, context) => {
1064
+ if (!(typeof value === "object" && value !== null && key in value)) context.addIssue({
1065
+ code: "invalid_type",
1066
+ expected: "object",
1067
+ input: value
1068
+ });
1069
+ }).pipe(schema);
1070
+ }
1071
+ /** Plain JSON, its values decorator values too. An object with a form's key is refused, for the form to report. */
1072
+ const plainValue = plainObject.superRefine((record, context) => {
1073
+ if (valueForms.some((key) => key in record)) context.addIssue({
1074
+ code: "invalid_type",
1075
+ expected: "object",
1076
+ input: record
1077
+ });
1078
+ }).pipe(z.record(z.string(), decoratorValue));
1079
+ const decoratorElement = fileObject({
1080
+ import: z.string(),
1081
+ /** The export to render; `default` for a default export. */
1082
+ component: z.string(),
1083
+ props: z.record(z.string(), decoratorValue).optional()
1084
+ });
1085
+ const decoratorEffects = [
843
1086
  "wrap",
844
1087
  "add",
845
1088
  "class",
846
1089
  "attributes",
847
1090
  "style"
848
1091
  ];
1092
+ /**
1093
+ * A decorator written as data, so it runs no code of its own: a component wrapped around the design, one rendered
1094
+ * beside it (a toast host), or a class, attributes or styles on the frame's body. A manifest lists them outermost
1095
+ * first, as the JSX they make reads. That is Parity's order, the reverse of Storybook's, where the first decorator in a
1096
+ * list is innermost, so a list compiled into Storybook's decorators is reversed first.
1097
+ */
1098
+ const libraryDecorator = fileObject({
1099
+ /** Applies only when the frame's globals have these values, as in `{ "theme": "dark" }`. */
1100
+ when: z.record(z.string(), z.string()).optional(),
1101
+ wrap: decoratorElement.optional(),
1102
+ add: decoratorElement.optional(),
1103
+ class: decoratorValue.optional(),
1104
+ attributes: z.record(z.string(), decoratorValue).optional(),
1105
+ style: z.record(z.string(), decoratorValue).optional()
1106
+ }).superRefine((decorator, context) => {
1107
+ if (decoratorEffects.filter((key) => decorator[key] !== void 0).length !== 1) context.addIssue({
1108
+ code: "custom",
1109
+ message: "expected one of wrap, add, class, attributes or style"
1110
+ });
1111
+ });
1112
+ /**
1113
+ * Hand edits to a library file, kept apart from what `parity lib` generates so regenerating keeps them. Components are
1114
+ * keyed by export name and merged over the generated entry; `false` leaves a component out. Decorators, when given,
1115
+ * replace the generated ones. A manifest can name a shared file of edits instead, relative to itself.
1116
+ */
1117
+ const libraryEdits = fileObject({
1118
+ $schema: z.string().optional(),
1119
+ components: z.record(z.string(), z.union([z.boolean().pipe(z.literal(false)), libraryComponentEdit])).optional(),
1120
+ decorators: z.array(libraryDecorator).optional()
1121
+ });
1122
+ /**
1123
+ * What a library says about itself, in a `.lib.par` file at its package root: its name, the stylesheet a project
1124
+ * imports to use it, the breakpoints it's designed for, its design tokens, its components, icons and decorators, and its
1125
+ * own canvas of designs. Any package with one is a library Parity can load. Packages that don't ship one are described
1126
+ * by Parity's registry, in the same format.
1127
+ */
1128
+ const libraryManifest = fileObject({
1129
+ $schema: z.string().optional(),
1130
+ /** The current manifest format; obsolete formats are rejected rather than migrated. */
1131
+ version: z.literal(3),
1132
+ /** Short name its components are namespaced by, as in `nova/Button`. Defaults to the package name. */
1133
+ id: z.string().optional(),
1134
+ name: z.string(),
1135
+ description: z.string().optional(),
1136
+ /** The npm package it describes, and the versions it was made for. */
1137
+ package: libraryPackage.optional(),
1138
+ /** The stylesheet to import, relative to the package: its Tailwind entry, or plain CSS. */
1139
+ styles: z.string().optional(),
1140
+ /** The viewport widths it's designed around, smallest first, however the file lists them. */
1141
+ breakpoints: z.array(libraryBreakpoint).transform((breakpoints) => breakpoints.toSorted((a, b) => a.width - b.width)).optional(),
1142
+ /**
1143
+ * Its design tokens, in the DTCG format (2025.10): a path relative to the package, to a token file or to a resolver
1144
+ * that names its themes, or a resolver or token groups written inline.
1145
+ */
1146
+ tokens: z.union([z.string(), plainObject]).optional(),
1147
+ /** The components it exports, as the type checker found them. */
1148
+ components: libraryComponents.optional(),
1149
+ /** Its icons, when it's an icon set: how they're imported and drawn. */
1150
+ icons: libraryIcons.optional(),
1151
+ /** What its components need around them in every frame: providers, toast hosts, theme classes. */
1152
+ decorators: z.array(libraryDecorator).optional(),
1153
+ /** Hand edits merged over the generated parts, or the path of a shared file of them, relative to this file. */
1154
+ edits: z.union([z.string(), libraryEdits]).optional(),
1155
+ /** The library's own canvas: its designs where its author placed them, its notes and its modes, as in a `.par`. */
1156
+ canvas: canvasDocument.optional()
1157
+ });
849
1158
  /** A library manifest's extension. It describes a library, and its `canvas` holds the library's own designs. */
850
1159
  const libraryManifestExtension = ".lib.par";
1160
+ /** Reads a library file, or throws `TypeError` with the first problem as `/json/pointer: message`. */
851
1161
  function parseLibraryManifest(value) {
852
- const manifest = expectObject(value, "");
853
- expectKnownKeys(manifest, [
854
- "$schema",
855
- "version",
856
- "id",
857
- "name",
858
- "description",
859
- "styles",
860
- "breakpoints",
861
- "tokens",
862
- "canvas",
863
- "package",
864
- "components",
865
- "icons",
866
- "decorators",
867
- "edits"
868
- ], "");
869
- if (manifest.version !== 3) throw new TypeError("/version: expected 3");
870
- return compact({
871
- version: 3,
872
- id: optional(manifest.id, (v) => expectString(v, "/id")),
873
- name: expectString(manifest.name, "/name"),
874
- description: optional(manifest.description, (v) => expectString(v, "/description")),
875
- package: optional(manifest.package, parsePackage),
876
- styles: optional(manifest.styles, (v) => expectString(v, "/styles")),
877
- breakpoints: optional(manifest.breakpoints, (v) => expectArray(v, "/breakpoints").map((item, index) => {
878
- const at = `/breakpoints/${index}`;
879
- const breakpoint = expectObject(item, at);
880
- expectKnownKeys(breakpoint, [
881
- "id",
882
- "name",
883
- "width"
884
- ], at);
885
- return {
886
- id: expectString(breakpoint.id, `${at}/id`),
887
- name: expectString(breakpoint.name, `${at}/name`),
888
- width: expectNumber(breakpoint.width, `${at}/width`)
889
- };
890
- }).sort((a, b) => a.width - b.width)),
891
- tokens: optional(manifest.tokens, (v) => typeof v === "string" ? v : expectObject(v, "/tokens")),
892
- components: optional(manifest.components, parseComponents),
893
- icons: optional(manifest.icons, parseIcons),
894
- decorators: optional(manifest.decorators, (v) => expectArray(v, "/decorators").map(parseDecorator)),
895
- edits: optional(manifest.edits, (v) => typeof v === "string" ? v : parseLibraryEdits(v, "/edits")),
896
- canvas: optional(manifest.canvas, (v) => {
897
- try {
898
- return parseCanvasDocument(v);
899
- } catch (error) {
900
- throw new TypeError(`/canvas${error instanceof Error ? error.message : String(error)}`);
901
- }
902
- })
903
- });
904
- }
905
- function parsePackage(value) {
906
- const pkg = expectObject(value, "/package");
907
- expectKnownKeys(pkg, [
908
- "name",
909
- "version",
910
- "range"
911
- ], "/package");
912
- return compact({
913
- name: expectString(pkg.name, "/package/name"),
914
- version: optional(pkg.version, (v) => expectString(v, "/package/version")),
915
- range: optional(pkg.range, (v) => expectString(v, "/package/range"))
916
- });
917
- }
918
- function parseComponents(value) {
919
- const components = expectObject(value, "/components");
920
- expectKnownKeys(components, ["import", "list"], "/components");
921
- const list = {};
922
- for (const [name, entry] of Object.entries(expectObject(components.list, "/components/list"))) {
923
- const at = `/components/list/${name}`;
924
- const component = expectObject(entry, at);
925
- expectKnownKeys(component, [
926
- ...componentKeys,
927
- "fingerprint",
928
- "props"
929
- ], at);
930
- list[name] = compact({
931
- ...parseComponentFields(component, at),
932
- as: expectOneOf(component.as, componentEvidence, `${at}/as`),
933
- fingerprint: optional(component.fingerprint, (v) => expectString(v, `${at}/fingerprint`)),
934
- props: optional(component.props, (v) => expectStringRecord(v, `${at}/props`))
935
- });
936
- }
937
- return compact({
938
- import: optional(components.import, (v) => expectString(v, "/components/import")),
939
- list
940
- });
941
- }
942
- const componentKeys = [
943
- "as",
944
- "declaration",
945
- "group",
946
- "parents",
947
- "parentsFrom",
948
- "optionalParents",
949
- "parentParts",
950
- "visual",
951
- "internal",
952
- "sample"
953
- ];
954
- function parseComponentFields(component, at) {
955
- return compact({
956
- as: optional(component.as, (v) => expectOneOf(v, componentEvidence, `${at}/as`)),
957
- declaration: optional(component.declaration, (v) => expectString(v, `${at}/declaration`)),
958
- group: optional(component.group, (v) => expectString(v, `${at}/group`)),
959
- parents: optional(component.parents, (v) => expectArray(v, `${at}/parents`).map((name, index) => expectString(name, `${at}/parents/${index}`))),
960
- parentsFrom: optional(component.parentsFrom, (v) => expectOneOf(v, parentSignals, `${at}/parentsFrom`)),
961
- optionalParents: optional(component.optionalParents, (v) => expectArray(v, `${at}/optionalParents`).map((name, index) => expectString(name, `${at}/optionalParents/${index}`))),
962
- parentParts: optional(component.parentParts, (v) => {
963
- if (typeof v !== "boolean") throw new TypeError(`${at}/parentParts: expected a boolean`);
964
- return v;
965
- }),
966
- visual: optional(component.visual, (v) => {
967
- if (typeof v !== "boolean") throw new TypeError(`${at}/visual: expected a boolean`);
968
- return v;
969
- }),
970
- internal: optional(component.internal, (v) => {
971
- if (typeof v !== "boolean") throw new TypeError(`${at}/internal: expected a boolean`);
972
- return v;
973
- }),
974
- sample: optional(component.sample, (v) => parseSample(v, `${at}/sample`))
975
- });
976
- }
977
- function parseSample(value, at) {
978
- const sample = expectObject(value, at);
979
- expectKnownKeys(sample, ["props", "children"], at);
980
- return compact({
981
- props: optional(sample.props, (v) => expectObject(v, `${at}/props`)),
982
- children: optional(sample.children, (v) => parseSampleChildren(v, `${at}/children`))
983
- });
984
- }
985
- function parseSampleChildren(value, at) {
986
- return expectArray(value, at).map((item, index) => {
987
- const here = `${at}/${index}`;
988
- if (typeof item === "string") return item;
989
- const child = expectObject(item, here);
990
- if ("$render" in child) {
991
- expectKnownKeys(child, [
992
- "$render",
993
- "spread",
994
- "pass"
995
- ], here);
996
- if (child.spread !== void 0 && child.spread !== true) throw new TypeError(`${here}/spread: expected true`);
997
- const render = { $render: parseSampleChildren(child.$render, `${here}/$render`) };
998
- if (child.spread) render.spread = true;
999
- if (child.pass !== void 0) render.pass = expectArray(child.pass, `${here}/pass`).map((prop, index) => expectString(prop, `${here}/pass/${index}`));
1000
- return render;
1001
- }
1002
- expectKnownKeys(child, [
1003
- "component",
1004
- "props",
1005
- "children"
1006
- ], here);
1007
- return compact({
1008
- component: expectString(child.component, `${here}/component`),
1009
- props: optional(child.props, (v) => expectObject(v, `${here}/props`)),
1010
- children: optional(child.children, (v) => parseSampleChildren(v, `${here}/children`))
1011
- });
1012
- });
1162
+ const { $schema: _schema, ...manifest } = parseData(libraryManifest, value);
1163
+ return manifest;
1013
1164
  }
1014
1165
  /** Reads hand edits to a library file, from its `edits` or a shared file of them. */
1015
1166
  function parseLibraryEdits(value, at = "") {
1016
- const edits = expectObject(value, at);
1017
- expectKnownKeys(edits, [
1018
- "$schema",
1019
- "components",
1020
- "decorators"
1021
- ], at);
1022
- return compact({
1023
- components: optional(edits.components, (v) => {
1024
- const result = {};
1025
- for (const [name, entry] of Object.entries(expectObject(v, `${at}/components`))) {
1026
- const here = `${at}/components/${name}`;
1027
- if (entry === false) {
1028
- result[name] = false;
1029
- continue;
1030
- }
1031
- const component = expectObject(entry, here);
1032
- expectKnownKeys(component, componentKeys, here);
1033
- result[name] = parseComponentFields(component, here);
1034
- }
1035
- return result;
1036
- }),
1037
- decorators: optional(edits.decorators, (v) => expectArray(v, `${at}/decorators`).map(parseDecorator))
1038
- });
1167
+ const { $schema: _schema, ...edits } = parseData(libraryEdits, value, at);
1168
+ return edits;
1039
1169
  }
1040
1170
  /**
1041
1171
  * The manifest with hand edits merged over what was generated, and the edited exports it no longer has, which are
@@ -1074,125 +1204,18 @@ function applyLibraryEdits(manifest, edits) {
1074
1204
  list
1075
1205
  };
1076
1206
  }
1207
+ const merged = {
1208
+ ...manifest,
1209
+ components,
1210
+ decorators: edits.decorators ?? manifest.decorators
1211
+ };
1212
+ if (!merged.components) delete merged.components;
1213
+ if (!merged.decorators) delete merged.decorators;
1077
1214
  return {
1078
- manifest: compact({
1079
- ...manifest,
1080
- components,
1081
- decorators: edits.decorators ?? manifest.decorators
1082
- }),
1215
+ manifest: merged,
1083
1216
  orphans
1084
1217
  };
1085
1218
  }
1086
- function parseIcons(value) {
1087
- const icons = expectObject(value, "/icons");
1088
- expectKnownKeys(icons, [
1089
- "import",
1090
- "render",
1091
- "match",
1092
- "exclude",
1093
- "prefer",
1094
- "variants",
1095
- "count",
1096
- "tags",
1097
- "tagSource"
1098
- ], "/icons");
1099
- let render;
1100
- if (icons.render === "export") render = "export";
1101
- else {
1102
- const renderer = expectObject(icons.render, "/icons/render");
1103
- expectKnownKeys(renderer, [
1104
- "import",
1105
- "component",
1106
- "prop"
1107
- ], "/icons/render");
1108
- render = {
1109
- import: expectString(renderer.import, "/icons/render/import"),
1110
- component: expectString(renderer.component, "/icons/render/component"),
1111
- prop: expectString(renderer.prop, "/icons/render/prop")
1112
- };
1113
- }
1114
- return compact({
1115
- import: optional(icons.import, (v) => expectString(v, "/icons/import")),
1116
- render,
1117
- match: optional(icons.match, (v) => expectPattern(v, "/icons/match")),
1118
- exclude: optional(icons.exclude, (v) => expectArray(v, "/icons/exclude").map((name, index) => expectString(name, `/icons/exclude/${index}`))),
1119
- prefer: optional(icons.prefer, (v) => expectArray(v, "/icons/prefer").map((name, index) => expectString(name, `/icons/prefer/${index}`))),
1120
- variants: optional(icons.variants, (v) => {
1121
- const variants = expectObject(v, "/icons/variants");
1122
- expectKnownKeys(variants, [
1123
- "pattern",
1124
- "prop",
1125
- "modules",
1126
- "styles",
1127
- "sizes",
1128
- "default"
1129
- ], "/icons/variants");
1130
- return compact({
1131
- pattern: optional(variants.pattern, (pattern) => expectPattern(pattern, "/icons/variants/pattern")),
1132
- prop: optional(variants.prop, (prop) => expectString(prop, "/icons/variants/prop")),
1133
- modules: optional(variants.modules, (modules) => expectStringRecord(modules, "/icons/variants/modules")),
1134
- styles: optional(variants.styles, (list) => expectArray(list, "/icons/variants/styles").map((style, index) => expectString(style, `/icons/variants/styles/${index}`))),
1135
- sizes: optional(variants.sizes, (list) => expectArray(list, "/icons/variants/sizes").map((size, index) => expectNumber(size, `/icons/variants/sizes/${index}`))),
1136
- default: optional(variants.default, (d) => {
1137
- const fallback = expectObject(d, "/icons/variants/default");
1138
- expectKnownKeys(fallback, ["style", "size"], "/icons/variants/default");
1139
- return compact({
1140
- style: optional(fallback.style, (s) => expectString(s, "/icons/variants/default/style")),
1141
- size: optional(fallback.size, (s) => expectNumber(s, "/icons/variants/default/size"))
1142
- });
1143
- })
1144
- });
1145
- }),
1146
- count: optional(icons.count, (v) => expectNumber(v, "/icons/count")),
1147
- tags: optional(icons.tags, (v) => Object.fromEntries(Object.entries(expectObject(v, "/icons/tags")).map(([name, list]) => [name, expectArray(list, `/icons/tags/${name}`).map((tag, index) => expectString(tag, `/icons/tags/${name}/${index}`))]))),
1148
- tagSource: optional(icons.tagSource, (v) => expectString(v, "/icons/tagSource"))
1149
- });
1150
- }
1151
- function parseDecorator(value, index) {
1152
- const at = `/decorators/${index}`;
1153
- const decorator = expectObject(value, at);
1154
- expectKnownKeys(decorator, decoratorKeys, at);
1155
- if (decoratorKeys.filter((key) => key !== "when" && decorator[key] !== void 0).length !== 1) throw new TypeError(`${at}: expected one of wrap, add, class, attributes or style`);
1156
- const element = (v, path) => {
1157
- const spec = expectObject(v, path);
1158
- expectKnownKeys(spec, [
1159
- "import",
1160
- "component",
1161
- "props"
1162
- ], path);
1163
- return compact({
1164
- import: expectString(spec.import, `${path}/import`),
1165
- component: expectString(spec.component, `${path}/component`),
1166
- props: optional(spec.props, (props) => expectObject(props, `${path}/props`))
1167
- });
1168
- };
1169
- return compact({
1170
- when: optional(decorator.when, (v) => {
1171
- const when = expectObject(v, `${at}/when`);
1172
- for (const [name, option] of Object.entries(when)) expectString(option, `${at}/when/${name}`);
1173
- return when;
1174
- }),
1175
- wrap: optional(decorator.wrap, (v) => element(v, `${at}/wrap`)),
1176
- add: optional(decorator.add, (v) => element(v, `${at}/add`)),
1177
- class: decorator.class,
1178
- attributes: optional(decorator.attributes, (v) => expectObject(v, `${at}/attributes`)),
1179
- style: optional(decorator.style, (v) => expectObject(v, `${at}/style`))
1180
- });
1181
- }
1182
- function expectPattern(value, path) {
1183
- const pattern = expectString(value, path);
1184
- try {
1185
- new RegExp(pattern);
1186
- } catch {
1187
- throw new TypeError(`${path}: expected a regular expression`);
1188
- }
1189
- return pattern;
1190
- }
1191
- function expectStringRecord(value, path) {
1192
- const record = expectObject(value, path);
1193
- for (const [key, item] of Object.entries(record)) expectString(item, `${path}/${key}`);
1194
- return record;
1195
- }
1196
1219
  // ../core/src/project.ts
1197
1220
  /**
1198
1221
  * Props that say what's open or chosen: `defaultOpen` on what opens (a dialog, a popover, a menu), `defaultValue` on
@@ -1468,4 +1491,4 @@ function sampleIds(sample, library) {
1468
1491
  ...sample.children ? { children: sample.children.map(child) } : {}
1469
1492
  };
1470
1493
  }
1471
- export { remProperty as A, linkTypes as C, generateId as D, walkNodes as E, packageManifest as F, viewportWidthProperty as M, deviceKinds as N, modeSettings as O, lengthToPixels as P, linkEndKinds as S, parseCanvasDocument as T, canvasObjectKinds as _, openProps as a, imageFits as b, isMadeValue as c, libraryManifestExtension as d, parentSignals as f, canvasDocument as g, renderSlotOf as h, withLibraryContext as i, viewportHeightProperty as j, collectCustomProperties as k, isSampleElement as l, parseLibraryManifest as m, librarySource as n, applyLibraryEdits as o, parseLibraryEdits as p, sampleIds as r, componentEvidence as s, componentNode as t, isSampleRender as u, containerKinds as v, paramTypes as w, linkAllowed as x, detectionCorrections as y };
1494
+ export { paramTypes as A, packageManifest as B, imageCredit as C, linkTypes as D, linkEndKinds as E, remProperty as F, viewportHeightProperty as I, viewportWidthProperty as L, generateId as M, modeSettings as N, nodeTree as O, collectCustomProperties as P, deviceKinds as R, detectionCorrections as S, linkAllowed as T, renderSlotOf as _, openProps as a, containerKinds as b, isMadeValue as c, libraryManifest as d, libraryManifestExtension as f, parseLibraryManifest as g, parseLibraryEdits as h, withLibraryContext as i, walkNodes as j, noteSpec as k, isSampleElement as l, parentSignals as m, librarySource as n, applyLibraryEdits as o, libraryPackage as p, sampleIds as r, componentEvidence as s, componentNode as t, isSampleRender as u, canvasDocument as v, imageFits as w, containerSpec as x, canvasObjectKinds as y, lengthToPixels as z };
@@ -1,6 +1,6 @@
1
- import { i as jsonText, o as parseData, r as finiteNumber, s as plainObject } from "./schema-CemdtCeF.mjs";
2
- import { F as packageManifest, P as lengthToPixels, c as isMadeValue, d as libraryManifestExtension, h as renderSlotOf, k as collectCustomProperties, l as isSampleElement, m as parseLibraryManifest, o as applyLibraryEdits, p as parseLibraryEdits, u as isSampleRender } from "./src-DjSCuWcT.mjs";
3
- import { r as readLibraryEdits, s as parseJsonc } from "./src-B9VW36v9.mjs";
1
+ import { i as jsonText, o as parseData, r as finiteNumber, s as plainObject } from "./schema-Dp5Jhloe.mjs";
2
+ import { B as packageManifest, P as collectCustomProperties, _ as renderSlotOf, c as isMadeValue, f as libraryManifestExtension, g as parseLibraryManifest, h as parseLibraryEdits, l as isSampleElement, o as applyLibraryEdits, u as isSampleRender, z as lengthToPixels } from "./src-BZFjMWhp.mjs";
3
+ import { r as readLibraryEdits, s as parseJsonc } from "./src-CdMzjFSa.mjs";
4
4
  import { a as publishedVersions, n as packageFile, o as repositoryFiles, r as publishedSource } from "./published-CdXoUgfD.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
@@ -0,0 +1,5 @@
1
+ import "./schema-Dp5Jhloe.mjs";
2
+ import "./client-BkLeG26A.mjs";
3
+ export { t as componentNode, M as generateId, n as librarySource, i as withLibraryContext } from "./src-BZFjMWhp.mjs";
4
+ import "./src-CdMzjFSa.mjs";
5
+ import "./src-CMPL5C8p.mjs";
@@ -1,7 +1,9 @@
1
- import { d as libraryManifestExtension, m as parseLibraryManifest, o as applyLibraryEdits, p as parseLibraryEdits } from "./src-DjSCuWcT.mjs";
1
+ import { n as fileObject, o as parseData } from "./schema-Dp5Jhloe.mjs";
2
+ import { d as libraryManifest, f as libraryManifestExtension, h as parseLibraryEdits, o as applyLibraryEdits, p as libraryPackage } from "./src-BZFjMWhp.mjs";
2
3
  import { createRequire } from "node:module";
3
4
  import { readFile, readdir } from "node:fs/promises";
4
5
  import { dirname, join, resolve } from "node:path";
6
+ import { z } from "zod";
5
7
  import { existsSync } from "node:fs";
6
8
  import semver from "semver";
7
9
  // ../core/src/jsonc.ts
@@ -28,6 +30,11 @@ function parseJsonc(text) {
28
30
  }
29
31
  // ../registry/src/index.ts
30
32
  const require = createRequire(import.meta.url);
33
+ /** A library file in the registry, which names the package it describes, since that's how it's found. */
34
+ const registryManifest = fileObject({
35
+ ...libraryManifest.shape,
36
+ package: z.unknown().refine((value) => value !== void 0, "a registry file names the package it describes").pipe(libraryPackage)
37
+ });
31
38
  /**
32
39
  * The folder the registry's files are in. The published CLI bundles this module and ships the files beside it, where
33
40
  * the package can't be resolved. Otherwise they're found through the package's own `package.json`, so it's the same
@@ -51,8 +58,7 @@ async function readEntries(dir) {
51
58
  for (const file of files) {
52
59
  const path = join(dir, file);
53
60
  try {
54
- const manifest = parseLibraryManifest(JSON.parse(await readFile(path, "utf8")));
55
- if (!manifest.package) throw new TypeError("/package: a registry file names the package it describes");
61
+ const { $schema: _schema, ...manifest } = parseData(registryManifest, JSON.parse(await readFile(path, "utf8")));
56
62
  entries.push({
57
63
  file,
58
64
  path,
@@ -1 +1 @@
1
- export { t as covers, n as newestEntries, i as registryDir, a as registryEntries } from "./src-B9VW36v9.mjs";
1
+ export { t as covers, n as newestEntries, i as registryDir, a as registryEntries } from "./src-CdMzjFSa.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity-app/cli",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Drive the Parity app from a terminal or an agent: read state, run edits, take screenshots, serve MCP.",
@@ -1,5 +0,0 @@
1
- import "./schema-CemdtCeF.mjs";
2
- import "./client-D6bpjpy-.mjs";
3
- export { t as componentNode, D as generateId, n as librarySource, i as withLibraryContext } from "./src-DjSCuWcT.mjs";
4
- import "./src-B9VW36v9.mjs";
5
- import "./src-Bf12xdm5.mjs";