@glass-ui-kit/cli 0.2.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +410 -19
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command3 } from "commander";
4
+ import { Command as Command6 } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
7
  import chalk2 from "chalk";
@@ -122,8 +122,20 @@ function exists(filePath, baseDir = process.cwd()) {
122
122
  }
123
123
 
124
124
  // src/utils/get-project-info.ts
125
+ import path4 from "path";
125
126
  import { spawn } from "child_process";
127
+ function resolveProjectRoot(cwdOption, cwd = process.cwd()) {
128
+ return cwdOption ? path4.resolve(cwd, cwdOption) : cwd;
129
+ }
130
+ function getLockfilePath(projectRoot = process.cwd(), existsAtPath = exists) {
131
+ if (existsAtPath("bun.lock", projectRoot)) return "bun.lock";
132
+ if (existsAtPath("bun.lockb", projectRoot)) return "bun.lockb";
133
+ if (existsAtPath("pnpm-lock.yaml", projectRoot)) return "pnpm-lock.yaml";
134
+ if (existsAtPath("yarn.lock", projectRoot)) return "yarn.lock";
135
+ return null;
136
+ }
126
137
  async function getPackageManager(projectRoot = process.cwd()) {
138
+ if (exists("bun.lock", projectRoot)) return "bun";
127
139
  if (exists("bun.lockb", projectRoot)) return "bun";
128
140
  if (exists("pnpm-lock.yaml", projectRoot)) return "pnpm";
129
141
  if (exists("yarn.lock", projectRoot)) return "yarn";
@@ -519,7 +531,7 @@ import chalk4 from "chalk";
519
531
  import { Command as Command2 } from "commander";
520
532
 
521
533
  // src/utils/registry.ts
522
- import path4 from "path";
534
+ import path5 from "path";
523
535
  import os from "os";
524
536
  import fs2 from "fs/promises";
525
537
 
@@ -553,8 +565,8 @@ var registryIndexSchema = z.array(registryItemSchema);
553
565
 
554
566
  // src/utils/registry.ts
555
567
  var DEFAULT_REGISTRY_URL = "https://ui-glass.vercel.app/registry.json";
556
- var CACHE_DIR = path4.join(os.homedir(), ".glass-ui");
557
- var CACHE_FILE = path4.join(CACHE_DIR, "registry.json");
568
+ var CACHE_DIR = path5.join(os.homedir(), ".glass-ui");
569
+ var CACHE_FILE = path5.join(CACHE_DIR, "registry.json");
558
570
  var CACHE_TTL = 1e3 * 60 * 60 * 24;
559
571
  function getRegistryUrl() {
560
572
  return process.env.GLASS_UI_REGISTRY_URL || DEFAULT_REGISTRY_URL;
@@ -585,6 +597,12 @@ async function writeCache(data) {
585
597
  } catch {
586
598
  }
587
599
  }
600
+ function getErrorMessage(error, fallback) {
601
+ if (error instanceof Error && error.message.length > 0) {
602
+ return error.message;
603
+ }
604
+ return fallback;
605
+ }
588
606
  async function fetchRegistry() {
589
607
  const cachedRegistry = await readCache();
590
608
  if (cachedRegistry) {
@@ -595,7 +613,7 @@ async function fetchRegistry() {
595
613
  try {
596
614
  response = await fetch(url);
597
615
  } catch (error) {
598
- throw new Error("Network error: Unable to connect to registry. Check your internet connection.");
616
+ throw new Error(getErrorMessage(error, "Network error: Unable to connect to registry."));
599
617
  }
600
618
  if (!response.ok) {
601
619
  throw new Error(`Registry unavailable. URL: ${url} (Status: ${response.status})`);
@@ -603,15 +621,14 @@ async function fetchRegistry() {
603
621
  let data;
604
622
  try {
605
623
  data = await response.json();
606
- } catch {
607
- throw new Error("Invalid response: Registry returned non-JSON data.");
624
+ } catch (error) {
625
+ throw new Error(getErrorMessage(error, "Invalid response: Registry returned non-JSON data."));
608
626
  }
609
627
  const parsed = registryIndexSchema.safeParse(data);
610
628
  if (!parsed.success) {
611
- console.error("Debug: Schema validation errors:", parsed.error.flatten());
612
- throw new Error(
613
- "Incompatible registry version. Your CLI might be outdated. Please try updating @glass-ui-kit/cli."
614
- );
629
+ const issue = parsed.error.issues[0];
630
+ const location = issue?.path.length ? issue.path.join(".") : "registry";
631
+ throw new Error(`${issue?.message ?? "Schema validation failed"}: ${location}`);
615
632
  }
616
633
  await writeCache(parsed.data);
617
634
  return parsed.data;
@@ -697,7 +714,7 @@ function resolveTargetDir(config, hasSrc, explicitPath) {
697
714
  }
698
715
 
699
716
  // src/utils/add/planner.ts
700
- import path5 from "path";
717
+ import path6 from "path";
701
718
 
702
719
  // src/utils/transformers.ts
703
720
  function transformImports(content, config) {
@@ -725,8 +742,8 @@ function buildWritePlan(items, config, hasSrc, options) {
725
742
  const targetDir = resolveTargetDir(config, hasSrc, options.path);
726
743
  return items.flatMap(
727
744
  (item) => item.files.filter((file) => Boolean(file.content)).map((file) => {
728
- const fileName = path5.basename(file.path);
729
- const filePath = path5.join(targetDir, fileName);
745
+ const fileName = path6.basename(file.path);
746
+ const filePath = path6.join(targetDir, fileName);
730
747
  return {
731
748
  filePath,
732
749
  content: transformImports(file.content || "", config),
@@ -737,7 +754,7 @@ function buildWritePlan(items, config, hasSrc, options) {
737
754
  }
738
755
 
739
756
  // src/utils/add/run-add.ts
740
- import path6 from "path";
757
+ import path7 from "path";
741
758
  import chalk3 from "chalk";
742
759
  var defaultRuntime2 = {
743
760
  cwd: () => process.cwd(),
@@ -752,11 +769,11 @@ var defaultRuntime2 = {
752
769
  function buildMissingComponentsMessage(names) {
753
770
  return `Components not found: ${names.join(", ")}.`;
754
771
  }
755
- function resolveProjectRoot(cwdOption, cwd) {
756
- return cwdOption ? path6.resolve(cwd, cwdOption) : cwd;
772
+ function resolveProjectRoot2(cwdOption, cwd) {
773
+ return cwdOption ? path7.resolve(cwd, cwdOption) : cwd;
757
774
  }
758
775
  async function runAddCommand(componentNames = [], options = {}, runtime = defaultRuntime2) {
759
- const projectRoot = resolveProjectRoot(options.cwd, runtime.cwd?.() ?? process.cwd());
776
+ const projectRoot = resolveProjectRoot2(options.cwd, runtime.cwd?.() ?? process.cwd());
760
777
  if (options.depsOnly && options.install === false) {
761
778
  throw new Error("invalid-install-combination");
762
779
  }
@@ -878,9 +895,383 @@ function createAddAction(deps = {
878
895
  }
879
896
  var add = new Command2().name("add").description("Add one or more components to your project").argument("[components...]", "The components to add").option("--all", "Add all available components").option("--overwrite", "Replace existing component files").option("--path <dir>", "Use a custom output directory").option("--no-install", "Skip dependency installation").option("--deps-only", "Install dependencies without writing component files").option("--cwd <path>", "Run the command against another project directory").action(createAddAction());
880
897
 
898
+ // src/commands/list.ts
899
+ import chalk5 from "chalk";
900
+ import { Command as Command3 } from "commander";
901
+
902
+ // src/utils/list/run-list.ts
903
+ var defaultRuntime3 = {
904
+ fetchRegistry
905
+ };
906
+ async function runListCommand(options = {}, runtime = defaultRuntime3) {
907
+ const registry = await runtime.fetchRegistry();
908
+ if (options.json) {
909
+ return JSON.stringify(registry, null, 2);
910
+ }
911
+ return registry.map((item) => item.name).join("\n");
912
+ }
913
+
914
+ // src/commands/list.ts
915
+ async function runListCommand2(options = {}, runtime = defaultRuntime3) {
916
+ return runListCommand(options, runtime);
917
+ }
918
+ function createListAction(deps = {
919
+ runListCommand: runListCommand2,
920
+ error: console.error,
921
+ log: console.log,
922
+ exit: process.exit
923
+ }) {
924
+ return async (options = {}) => {
925
+ try {
926
+ const output = await deps.runListCommand({ json: options.json === true });
927
+ if (output.length > 0) {
928
+ deps.log(output);
929
+ }
930
+ } catch (error) {
931
+ deps.error(chalk5.red("\nList failed:"));
932
+ if (error instanceof Error) {
933
+ deps.error(chalk5.gray(error.message));
934
+ } else {
935
+ deps.error(chalk5.gray(String(error)));
936
+ }
937
+ deps.exit(1);
938
+ }
939
+ };
940
+ }
941
+ var list = new Command3().name("list").description("List available components from the registry").option("--json", "Output the validated registry payload as JSON", false).action(createListAction());
942
+
943
+ // src/commands/info.ts
944
+ import chalk6 from "chalk";
945
+ import { Command as Command4 } from "commander";
946
+
947
+ // src/utils/info/format-info.ts
948
+ function formatDependencySection(label, values) {
949
+ return `${label}: ${values && values.length > 0 ? values.join(", ") : "None"}`;
950
+ }
951
+ function formatInfo(item) {
952
+ const lines = [
953
+ `Name: ${item.name}`,
954
+ `Type: ${item.type}`,
955
+ "Files:",
956
+ ...item.files.map((file) => `- ${file.path} (${file.type})`),
957
+ formatDependencySection("Dependencies", item.dependencies),
958
+ formatDependencySection("Dev Dependencies", item.devDependencies),
959
+ formatDependencySection("Registry Dependencies", item.registryDependencies)
960
+ ];
961
+ if (item.meta?.requiresBlur !== void 0) {
962
+ lines.push(`Requires Blur: ${item.meta.requiresBlur}`);
963
+ }
964
+ return lines.join("\n");
965
+ }
966
+
967
+ // src/utils/info/run-info.ts
968
+ var defaultRuntime4 = {
969
+ fetchRegistry,
970
+ getItem
971
+ };
972
+ async function runInfoCommand(componentName, options = {}, runtime = defaultRuntime4) {
973
+ const registry = await runtime.fetchRegistry();
974
+ const item = runtime.getItem(registry, componentName);
975
+ if (!item) {
976
+ throw new Error(`Component not found: "${componentName}"`);
977
+ }
978
+ if (options.json) {
979
+ return JSON.stringify(item, null, 2);
980
+ }
981
+ return formatInfo(item);
982
+ }
983
+
984
+ // src/commands/info.ts
985
+ async function runInfoCommand2(componentName, options = {}, runtime = defaultRuntime4) {
986
+ return runInfoCommand(componentName, options, runtime);
987
+ }
988
+ function createInfoAction(deps = {
989
+ runInfoCommand: runInfoCommand2,
990
+ error: console.error,
991
+ log: console.log,
992
+ exit: process.exit
993
+ }) {
994
+ return async (componentName, options = {}) => {
995
+ try {
996
+ const output = await deps.runInfoCommand(componentName, { json: options.json === true });
997
+ if (output.length > 0) {
998
+ deps.log(output);
999
+ }
1000
+ } catch (error) {
1001
+ deps.error(chalk6.red("\nInfo failed:"));
1002
+ if (error instanceof Error) {
1003
+ deps.error(chalk6.gray(error.message));
1004
+ } else {
1005
+ deps.error(chalk6.gray(String(error)));
1006
+ }
1007
+ deps.exit(1);
1008
+ }
1009
+ };
1010
+ }
1011
+ var info = new Command4().name("info").description("Show details for a single registry component").argument("<component>", "The exact component name to inspect").option("--json", "Output the validated registry item as JSON", false).action(createInfoAction());
1012
+
1013
+ // src/commands/doctor.ts
1014
+ import chalk7 from "chalk";
1015
+ import { Command as Command5 } from "commander";
1016
+
1017
+ // src/utils/doctor/format-doctor.ts
1018
+ function formatCheck(check) {
1019
+ const icon = check.status === "ok" ? "\u2713" : check.status === "warn" ? "!" : "\u2716";
1020
+ const lines = [`${icon} ${check.id} \u2014 ${check.summary}`];
1021
+ if (check.detail) {
1022
+ lines.push(` Next step: ${check.detail}`);
1023
+ }
1024
+ return lines.join("\n");
1025
+ }
1026
+ function formatDoctorReport(report) {
1027
+ const aliasLine = report.config.aliases ? `- Aliases: components=${report.config.aliases.components}, utils=${report.config.aliases.utils}` : "- Aliases: missing";
1028
+ return [
1029
+ "Glass UI Doctor",
1030
+ `Project root: ${report.projectRoot}`,
1031
+ `Init readiness: ${report.readiness.init ? "ready" : "not ready"}`,
1032
+ `Add readiness: ${report.readiness.add ? "ready" : "not ready"}`,
1033
+ "",
1034
+ "Detected state:",
1035
+ `- Framework: ${report.framework.value} (${report.framework.source})`,
1036
+ `- Package manager: ${report.packageManager.value} (${report.packageManager.source})`,
1037
+ `- Config: ${report.config.path} (${report.config.source})`,
1038
+ `- CSS: ${report.css.path ?? "unresolved"} (${report.css.source}, ${report.css.exists ? "exists" : "missing"})`,
1039
+ aliasLine,
1040
+ "",
1041
+ "Checks:",
1042
+ ...report.checks.map(formatCheck)
1043
+ ].join("\n");
1044
+ }
1045
+
1046
+ // src/utils/doctor/inspect-project.ts
1047
+ import { z as z2 } from "zod";
1048
+ var configSchema = z2.object({
1049
+ framework: z2.enum(["react", "next", "vite", "astro", "remix", "unknown"]),
1050
+ style: z2.string(),
1051
+ css: z2.string().min(1),
1052
+ aliases: z2.object({
1053
+ components: z2.string().min(1),
1054
+ utils: z2.string().min(1)
1055
+ })
1056
+ });
1057
+ function buildChecks(report) {
1058
+ const checks = [];
1059
+ if (report.config.source === "detected") {
1060
+ checks.push({ id: "config", status: "ok", summary: "Found valid glass.config.json." });
1061
+ } else if (report.config.source === "missing") {
1062
+ checks.push({
1063
+ id: "config",
1064
+ status: "error",
1065
+ summary: "glass.config.json was not found.",
1066
+ detail: "Run `glass-ui init` in this project before running `glass-ui add`."
1067
+ });
1068
+ } else {
1069
+ checks.push({
1070
+ id: "config",
1071
+ status: "error",
1072
+ summary: "glass.config.json is invalid.",
1073
+ detail: report.config.error ?? "Fix the config JSON and try doctor again."
1074
+ });
1075
+ }
1076
+ if (report.framework.source === "detected") {
1077
+ checks.push({
1078
+ id: "framework",
1079
+ status: "ok",
1080
+ summary: `Detected framework: ${report.framework.value}.`
1081
+ });
1082
+ } else {
1083
+ checks.push({
1084
+ id: "framework",
1085
+ status: "warn",
1086
+ summary: `Could not confidently detect the framework; using ${report.framework.value}.`,
1087
+ detail: "Check package.json dependencies or pass an explicit framework during `glass-ui init`."
1088
+ });
1089
+ }
1090
+ if (report.packageManager.source === "detected") {
1091
+ checks.push({
1092
+ id: "package-manager",
1093
+ status: "ok",
1094
+ summary: `Detected package manager: ${report.packageManager.value}.`
1095
+ });
1096
+ } else {
1097
+ checks.push({
1098
+ id: "package-manager",
1099
+ status: "warn",
1100
+ summary: `No lockfile found; defaulting to ${report.packageManager.value}.`,
1101
+ detail: "Create or commit the lockfile used by this project to confirm the package manager."
1102
+ });
1103
+ }
1104
+ if (report.css.path && report.css.exists && report.css.source === "detected") {
1105
+ checks.push({
1106
+ id: "css",
1107
+ status: "ok",
1108
+ summary: `CSS file is available at ${report.css.path}.`
1109
+ });
1110
+ } else if (report.css.path && report.css.exists) {
1111
+ checks.push({
1112
+ id: "css",
1113
+ status: "warn",
1114
+ summary: `CSS path was inferred as ${report.css.path}.`,
1115
+ detail: "Save the CSS path in glass.config.json to confirm it explicitly."
1116
+ });
1117
+ } else if (report.css.path) {
1118
+ checks.push({
1119
+ id: "css",
1120
+ status: "warn",
1121
+ summary: `CSS file is missing at ${report.css.path}.`,
1122
+ detail: "Create the CSS file or update glass.config.json to point at the correct path."
1123
+ });
1124
+ } else {
1125
+ checks.push({
1126
+ id: "css",
1127
+ status: "warn",
1128
+ summary: "Could not resolve a CSS file path.",
1129
+ detail: "Set the css field in glass.config.json or rerun `glass-ui init`."
1130
+ });
1131
+ }
1132
+ if (report.config.aliases) {
1133
+ checks.push({
1134
+ id: "aliases",
1135
+ status: "ok",
1136
+ summary: "Detected components and utils aliases."
1137
+ });
1138
+ } else {
1139
+ checks.push({
1140
+ id: "aliases",
1141
+ status: "error",
1142
+ summary: "Components and utils aliases are missing.",
1143
+ detail: "Save both aliases in glass.config.json so generated imports resolve correctly."
1144
+ });
1145
+ }
1146
+ if (report.readiness.add) {
1147
+ checks.push({ id: "add-readiness", status: "ok", summary: "Project is ready for add." });
1148
+ } else {
1149
+ checks.push({
1150
+ id: "add-readiness",
1151
+ status: "error",
1152
+ summary: "Project is not ready for add.",
1153
+ detail: "Create a valid glass.config.json with aliases before adding components."
1154
+ });
1155
+ }
1156
+ return checks;
1157
+ }
1158
+ async function inspectProject(options = {}, runtime) {
1159
+ const projectRoot = resolveProjectRoot(options.cwd, runtime.cwd());
1160
+ if (!runtime.exists(".", projectRoot)) {
1161
+ throw new Error(
1162
+ `Could not inspect directory "${projectRoot}": path does not exist or is not accessible.`
1163
+ );
1164
+ }
1165
+ const hasPackageJson = runtime.exists("package.json", projectRoot);
1166
+ const frameworkValue = await runtime.getFramework(projectRoot);
1167
+ const frameworkSource = hasPackageJson && frameworkValue !== "unknown" ? "detected" : "inferred";
1168
+ const packageManagerValue = await runtime.getPackageManager(projectRoot);
1169
+ const packageManagerSource = getLockfilePath(projectRoot, runtime.exists) ? "detected" : "inferred";
1170
+ let config = {
1171
+ path: "glass.config.json",
1172
+ source: "missing"
1173
+ };
1174
+ if (runtime.exists("glass.config.json", projectRoot)) {
1175
+ try {
1176
+ const parsed = configSchema.parse(
1177
+ JSON.parse(await runtime.readFile("glass.config.json", projectRoot))
1178
+ );
1179
+ config = {
1180
+ path: "glass.config.json",
1181
+ source: "detected",
1182
+ css: parsed.css,
1183
+ aliases: parsed.aliases
1184
+ };
1185
+ } catch (error) {
1186
+ config = {
1187
+ path: "glass.config.json",
1188
+ source: "invalid",
1189
+ error: error instanceof Error ? `Invalid config: ${error.message}` : "Invalid config."
1190
+ };
1191
+ }
1192
+ }
1193
+ const cssPath = config.css ?? runtime.getCssPath(frameworkValue, projectRoot);
1194
+ const cssSource = config.css ? "detected" : cssPath ? "inferred" : "missing";
1195
+ const cssExists = cssPath ? runtime.exists(cssPath, projectRoot) : false;
1196
+ const readiness = {
1197
+ init: true,
1198
+ add: config.source === "detected" && Boolean(config.aliases?.components) && Boolean(config.aliases?.utils)
1199
+ };
1200
+ const reportWithoutChecks = {
1201
+ projectRoot,
1202
+ framework: { value: frameworkValue, source: frameworkSource },
1203
+ packageManager: { value: packageManagerValue, source: packageManagerSource },
1204
+ config,
1205
+ css: {
1206
+ path: cssPath,
1207
+ exists: cssExists,
1208
+ source: cssSource
1209
+ },
1210
+ readiness
1211
+ };
1212
+ return {
1213
+ ...reportWithoutChecks,
1214
+ checks: buildChecks(reportWithoutChecks)
1215
+ };
1216
+ }
1217
+
1218
+ // src/utils/doctor/run-doctor.ts
1219
+ var defaultRuntime5 = {
1220
+ cwd: () => process.cwd(),
1221
+ exists,
1222
+ readFile,
1223
+ writeFile,
1224
+ getFramework,
1225
+ getPackageManager,
1226
+ getCssPath,
1227
+ installDependencies,
1228
+ inspectProject,
1229
+ formatDoctorReport
1230
+ };
1231
+ async function runDoctorCommand(options = {}, runtime = defaultRuntime5) {
1232
+ const resolvedRuntime = { ...defaultRuntime5, ...runtime };
1233
+ const report = await resolvedRuntime.inspectProject(options, resolvedRuntime);
1234
+ if (options.json) {
1235
+ return JSON.stringify(report, null, 2);
1236
+ }
1237
+ return resolvedRuntime.formatDoctorReport(report);
1238
+ }
1239
+
1240
+ // src/commands/doctor.ts
1241
+ async function runDoctorCommand2(options = {}, runtime = defaultRuntime5) {
1242
+ return runDoctorCommand(options, runtime);
1243
+ }
1244
+ function createDoctorAction(deps = {
1245
+ runDoctorCommand: runDoctorCommand2,
1246
+ error: console.error,
1247
+ log: console.log,
1248
+ exit: process.exit
1249
+ }) {
1250
+ return async (options = {}) => {
1251
+ try {
1252
+ const output = await deps.runDoctorCommand({ cwd: options.cwd, json: options.json === true });
1253
+ if (output.length > 0) {
1254
+ deps.log(output);
1255
+ }
1256
+ } catch (error) {
1257
+ deps.error(chalk7.red("\nDoctor failed:"));
1258
+ if (error instanceof Error) {
1259
+ deps.error(chalk7.gray(error.message));
1260
+ } else {
1261
+ deps.error(chalk7.gray(String(error)));
1262
+ }
1263
+ deps.exit(1);
1264
+ }
1265
+ };
1266
+ }
1267
+ var doctor = new Command5().name("doctor").description("Diagnose whether a project is ready to use the CLI").option("--cwd <path>", "Run the command against another project directory").option("--json", "Output the diagnostic report as JSON", false).action(createDoctorAction());
1268
+
881
1269
  // src/index.ts
882
- var program = new Command3();
1270
+ var program = new Command6();
883
1271
  program.name("glass-ui").description("The Glass UI CLI - Add glassmorphism components to your app").version("0.2.5");
884
1272
  program.addCommand(init);
885
1273
  program.addCommand(add);
1274
+ program.addCommand(list);
1275
+ program.addCommand(info);
1276
+ program.addCommand(doctor);
886
1277
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glass-ui-kit/cli",
3
- "version": "0.2.5",
3
+ "version": "1.0.0",
4
4
  "description": "The official CLI for Glass UI. Add glassmorphism components to your React projects in seconds.",
5
5
  "keywords": [
6
6
  "glassmorphism",
@@ -20,7 +20,7 @@
20
20
  "directory": "packages/cli"
21
21
  },
22
22
  "license": "MIT",
23
- "author": "Glass UI Team",
23
+ "author": "jntellez (https://jntellez.dev)",
24
24
  "type": "module",
25
25
  "bin": {
26
26
  "glass-ui": "./dist/index.js"
@@ -44,8 +44,8 @@
44
44
  "vitest": "^3.2.4",
45
45
  "tsup": "^8.0.1",
46
46
  "typescript": "^5.3.3",
47
- "@glass-ui-kit/schema": "0.0.1",
48
- "@glass-ui-kit/tsconfig": "0.0.1"
47
+ "@glass-ui-kit/tsconfig": "0.0.1",
48
+ "@glass-ui-kit/schema": "0.0.1"
49
49
  },
50
50
  "publishConfig": {
51
51
  "access": "public"