@udohjeremiah/moniq 0.3.1 → 0.3.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/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { n as loadConfig } from "./dist-B1TNZsla.js";
2
+ import { n as loadConfig } from "./dist-DVPiOZCC.js";
3
3
  import path from "node:path";
4
- import { stdin } from "node:process";
5
- import { styleText } from "node:util";
6
4
  import { execFile, execFileSync } from "node:child_process";
5
+ import { styleText } from "node:util";
6
+ import { stdin } from "node:process";
7
7
  import { createInterface } from "node:readline/promises";
8
8
  //#region ../../node_modules/.pnpm/cac@7.0.0/node_modules/cac/dist/index.js
9
9
  function toArr(any) {
@@ -917,7 +917,7 @@ async function resolve(config, root, packages_) {
917
917
  }
918
918
  //#endregion
919
919
  //#region ../cli/dist/index.js
920
- var version = "0.3.1";
920
+ var version = "0.3.3";
921
921
  function formatDiagnostics(diagnostics, options) {
922
922
  if ((options?.format ?? "pretty") === "json") return formatJson(diagnostics);
923
923
  return formatPretty(diagnostics, options?.isDryRun);
@@ -926,7 +926,7 @@ function formatJson(diagnostics) {
926
926
  return `${JSON.stringify(diagnostics, void 0, 2)}\n`;
927
927
  }
928
928
  function formatPretty(diagnostics, isDryRun) {
929
- if (diagnostics.length === 0) return styleText(["bold", "green"], " No issues found.");
929
+ if (diagnostics.length === 0) return styleText(["bold", "green"], " No issues found.");
930
930
  const lines = [];
931
931
  const byPackage = /* @__PURE__ */ new Map();
932
932
  for (const d of diagnostics) {
@@ -935,7 +935,7 @@ function formatPretty(diagnostics, isDryRun) {
935
935
  else byPackage.set(d.packageName, [d]);
936
936
  }
937
937
  for (const [packageName, diags] of byPackage) {
938
- lines.push("", `📦 ${styleText(["bold", "cyan"], packageName)}`);
938
+ lines.push("", styleText(["bold", "cyan"], packageName));
939
939
  for (const d of diags) pushDiagnostic(lines, d, isDryRun);
940
940
  }
941
941
  const errorCount = diagnostics.filter((d) => d.severity === "error").length;
@@ -944,25 +944,24 @@ function formatPretty(diagnostics, isDryRun) {
944
944
  if (errorCount > 0) countParts.push(styleText("red", `${String(errorCount)} error(s)`));
945
945
  if (warningCount > 0) countParts.push(styleText("yellow", `${String(warningCount)} warning(s)`));
946
946
  const summary = countParts.join(", ");
947
- const summaryLine = `📋 Found ${String(diagnostics.length)} issue(s) — ${summary.length > 0 ? summary : "all clear"}`;
947
+ const summaryLine = `${styleText("cyan", "ℹ")} Found ${String(diagnostics.length)} issue(s) — ${summary.length > 0 ? summary : "all clear"}`;
948
948
  lines.push("", styleText("dim", summaryLine));
949
949
  if (isDryRun) {
950
950
  const fixableCount = diagnostics.filter((d) => d.fix && d.severity !== "off").length;
951
- lines.push("", styleText("dim", `🔮 Dry-run: ${String(fixableCount)} fix(es) available`));
951
+ lines.push("", styleText("dim", `${styleText("cyan", "ℹ")} Dry-run: ${String(fixableCount)} fix(es) available`));
952
952
  }
953
953
  return lines.join("\n");
954
954
  }
955
955
  function pushDiagnostic(lines, d, isDryRun) {
956
956
  const badge = severityBadge(d.severity);
957
- const emoji = severityEmoji(d.severity);
958
- lines.push(` ${emoji} ${badge} ${d.message}`);
957
+ const icon = severityIcon(d.severity);
958
+ lines.push(` ${icon} ${badge} ${d.message}`);
959
959
  if (d.expected && d.actual) lines.push(` ${styleText("dim", "Expected:")} ${styleText("cyan", d.expected)}`, ` ${styleText("dim", "Actual:")} ${styleText("red", d.actual)}`);
960
960
  else if (d.expected) lines.push(` ${styleText("dim", "Expected:")} ${styleText("cyan", d.expected)}`);
961
961
  else if (d.actual) lines.push(` ${styleText("dim", "Actual:")} ${styleText("red", d.actual)}`);
962
962
  if (d.fix) {
963
963
  const label = styleText("dim", isDryRun ? "Would fix:" : "Fix:");
964
- const icon = isDryRun ? "🔮" : "🔧";
965
- lines.push(` ${icon} ${label} ${d.fix}`);
964
+ lines.push(` ${label} ${d.fix}`);
966
965
  }
967
966
  }
968
967
  function severityBadge(severity) {
@@ -970,10 +969,10 @@ function severityBadge(severity) {
970
969
  if (severity === "warn") return styleText(["bold", "yellow"], "WARN");
971
970
  return styleText("gray", "OFF");
972
971
  }
973
- function severityEmoji(severity) {
974
- if (severity === "error") return "";
975
- if (severity === "warn") return "⚠️ ";
976
- return "";
972
+ function severityIcon(severity) {
973
+ if (severity === "error") return "";
974
+ if (severity === "warn") return "";
975
+ return " ";
977
976
  }
978
977
  async function applyScriptFixes(diagnostics, options) {
979
978
  const fixable = diagnostics.filter((d) => d.fix && d.severity !== "off");
@@ -1022,8 +1021,8 @@ async function check(options) {
1022
1021
  let config;
1023
1022
  try {
1024
1023
  config = await loadConfig(cwd);
1025
- } catch {
1026
- throw new Error("No moniq.config file found in or above the current directory.");
1024
+ } catch (error) {
1025
+ throw new Error(`Failed to load moniq.config: ${String(error)}`, { cause: error });
1027
1026
  }
1028
1027
  const packages = await discoverWorkspace(cwd);
1029
1028
  if (packages.length === 0) throw new Error("No workspace packages found.");
@@ -1031,7 +1030,7 @@ async function check(options) {
1031
1030
  let fixSummary;
1032
1031
  if (options.fix) fixSummary = await applyScriptFixes(diagnostics, { isDryRun: options.isDryRun });
1033
1032
  if (options.format !== "json") {
1034
- console.log(` 🔍 Scanned ${String(packages.length)} package(s)`);
1033
+ console.log(` ${styleText("cyan", "ℹ")} Scanned ${String(packages.length)} package(s)`);
1035
1034
  console.log();
1036
1035
  }
1037
1036
  console.log(formatDiagnostics(diagnostics, {
@@ -1039,29 +1038,18 @@ async function check(options) {
1039
1038
  isDryRun: options.isDryRun
1040
1039
  }));
1041
1040
  if (fixSummary) if (fixSummary.isDryRun) {
1042
- const message = `🔮 Dry-run: ${String(fixSummary.fixed)} fix(es) available, ${String(fixSummary.errors)} error(s)`;
1041
+ const message = `${styleText("cyan", "ℹ")} Dry-run: ${String(fixSummary.fixed)} fix(es) available, ${String(fixSummary.errors)} error(s)`;
1043
1042
  console.log(styleText("dim", message));
1044
1043
  } else {
1045
- const message = `✅ Fixed ${String(fixSummary.fixed)} issue(s) across ${String(fixSummary.packageCount)} package(s)`;
1044
+ const message = `✔ Fixed ${String(fixSummary.fixed)} issue(s) across ${String(fixSummary.packageCount)} package(s)`;
1046
1045
  console.log(styleText(["bold", "green"], message));
1047
1046
  }
1048
1047
  }
1049
1048
  async function doctor() {
1050
1049
  const cwd = process.cwd();
1051
1050
  const issues = [];
1052
- try {
1053
- const config = await loadConfig(cwd);
1054
- issues.push({
1055
- message: "moniq.config file found and loadable.",
1056
- severity: "warn"
1057
- });
1058
- checkScriptPolicies(config, issues);
1059
- } catch {
1060
- issues.push({
1061
- message: "No moniq.config file found in or above the current directory.",
1062
- severity: "error"
1063
- });
1064
- }
1051
+ console.log();
1052
+ console.log(` ${styleText("bold", "Configuration Doctor")}`);
1065
1053
  try {
1066
1054
  const packageCount = (await discoverWorkspace(cwd)).length;
1067
1055
  if (packageCount === 0) issues.push({
@@ -1070,7 +1058,7 @@ async function doctor() {
1070
1058
  });
1071
1059
  else issues.push({
1072
1060
  message: `Detected ${String(packageCount)} workspace package(s).`,
1073
- severity: "warn"
1061
+ severity: "info"
1074
1062
  });
1075
1063
  } catch {
1076
1064
  issues.push({
@@ -1078,25 +1066,33 @@ async function doctor() {
1078
1066
  severity: "error"
1079
1067
  });
1080
1068
  }
1069
+ try {
1070
+ const config = await loadConfig(cwd);
1071
+ issues.push({
1072
+ message: "moniq.config file found and loadable.",
1073
+ severity: "info"
1074
+ });
1075
+ checkScriptPolicies(config, issues);
1076
+ } catch (error) {
1077
+ issues.push({
1078
+ message: `Failed to load moniq.config: ${String(error)}`,
1079
+ severity: "error"
1080
+ });
1081
+ }
1081
1082
  console.log();
1082
- console.log(` ${styleText("bold", "🏥 Configuration Doctor")}`);
1083
- console.log();
1084
- if (issues.length === 0) {
1085
- console.log(` ${styleText(["bold", "green"], "✅ Everything looks good!")}`);
1083
+ issues.sort((a, b) => severityIndex(a.severity) - severityIndex(b.severity));
1084
+ if (!issues.some((issue) => issue.severity !== "info")) {
1085
+ console.log(` ${styleText(["bold", "green"], "✔ Everything looks good!")}`);
1086
1086
  return;
1087
1087
  }
1088
- for (const issue of issues) {
1089
- const icon = issue.severity === "error" ? "❌" : "⚠️ ";
1090
- const label = issue.severity === "error" ? styleText(["bold", "red"], "ERROR") : styleText(["bold", "yellow"], "WARN");
1091
- console.log(` ${icon} ${label} ${issue.message}`);
1092
- }
1093
- const errorCount = issues.filter((index) => index.severity === "error").length;
1094
- const warningCount = issues.filter((index) => index.severity === "warn").length;
1088
+ for (const issue of issues) console.log(formatIssue(issue));
1089
+ const errorCount = issues.filter((issue) => issue.severity === "error").length;
1090
+ const warningCount = issues.filter((issue) => issue.severity === "warn").length;
1095
1091
  const summary = styleText("dim", `Found ${`${String(errorCount)} error(s)`}, ${`${String(warningCount)} warning(s)`}`);
1096
1092
  console.log();
1097
1093
  console.log(` ${summary}`);
1098
1094
  if (errorCount > 0) {
1099
- const tip = styleText(["bold", "cyan"], "💡 Tip:");
1095
+ const tip = styleText(["bold", "cyan"], "Tip:");
1100
1096
  const hint = styleText("dim", "moniq init");
1101
1097
  console.log();
1102
1098
  console.log(` ${tip} Run ${hint} to scaffold a starter configuration.`);
@@ -1120,6 +1116,30 @@ function checkScriptPolicies(config, issues) {
1120
1116
  }
1121
1117
  }
1122
1118
  }
1119
+ function formatIssue(issue) {
1120
+ let icon;
1121
+ let label;
1122
+ let iconColor;
1123
+ if (issue.severity === "error") {
1124
+ icon = "✘";
1125
+ label = styleText(["bold", "red"], "ERROR");
1126
+ iconColor = "dim";
1127
+ } else if (issue.severity === "warn") {
1128
+ icon = "⚠";
1129
+ label = styleText(["bold", "yellow"], "WARN");
1130
+ iconColor = "dim";
1131
+ } else {
1132
+ icon = "ℹ";
1133
+ label = styleText(["bold", "cyan"], "INFO");
1134
+ iconColor = "cyan";
1135
+ }
1136
+ return ` ${styleText(iconColor, icon)} ${label} ${issue.message}`;
1137
+ }
1138
+ function severityIndex(severity) {
1139
+ if (severity === "error") return 2;
1140
+ if (severity === "warn") return 1;
1141
+ return 0;
1142
+ }
1123
1143
  const colorFns = [
1124
1144
  (s) => styleText("cyan", s),
1125
1145
  (s) => styleText("magenta", s),
@@ -1166,7 +1186,7 @@ const letterRows = [
1166
1186
  "██║ ██║",
1167
1187
  "██║ ██║",
1168
1188
  "╚██████╔╝",
1169
- " ╚════╝╗ "
1189
+ " ╚════╝╲╲ "
1170
1190
  ]
1171
1191
  ];
1172
1192
  const DESCRIPTION = "Policy-driven workspace linter for JavaScript/TypeScript monorepos.";
@@ -1217,14 +1237,15 @@ export default defineConfig({
1217
1237
  async function detectLang(cwd, packageJson) {
1218
1238
  const rawDependencies = packageJson["dependencies"];
1219
1239
  const rawDevelopmentDependencies = packageJson["devDependencies"];
1240
+ const isModule = packageJson["type"] === "module";
1220
1241
  const { access } = await import("node:fs/promises");
1221
1242
  try {
1222
1243
  await access(path.join(cwd, "tsconfig.json"));
1223
- return "ts";
1244
+ return isModule ? "ts" : "mts";
1224
1245
  } catch {}
1225
- if (typeof rawDependencies === "object" && rawDependencies !== null && Object.hasOwn(rawDependencies, "typescript")) return "ts";
1226
- if (typeof rawDevelopmentDependencies === "object" && rawDevelopmentDependencies !== null && Object.hasOwn(rawDevelopmentDependencies, "typescript")) return "ts";
1227
- return "js";
1246
+ if (typeof rawDependencies === "object" && rawDependencies !== null && Object.hasOwn(rawDependencies, "typescript")) return isModule ? "ts" : "mts";
1247
+ if (typeof rawDevelopmentDependencies === "object" && rawDevelopmentDependencies !== null && Object.hasOwn(rawDevelopmentDependencies, "typescript")) return isModule ? "ts" : "mts";
1248
+ return isModule ? "js" : "mjs";
1228
1249
  }
1229
1250
  async function init(options) {
1230
1251
  const { _cwd, lang: explicitLang } = options;
@@ -1243,10 +1264,10 @@ async function init(options) {
1243
1264
  const configPath = path.join(cwd, filename);
1244
1265
  if (!await handleExistingConfig(configPath, filename)) return;
1245
1266
  let workspaceLabel = "single package";
1246
- let packages = [];
1267
+ let childPackages = [];
1247
1268
  try {
1248
- packages = await discoverWorkspace(cwd);
1249
- if (packages.length > 1) workspaceLabel = `monorepo with ${String(packages.length)} packages`;
1269
+ childPackages = (await discoverWorkspace(cwd)).filter((p) => path.resolve(cwd, p.path) !== path.resolve(cwd));
1270
+ if (childPackages.length > 1) workspaceLabel = `monorepo with ${String(childPackages.length)} packages`;
1250
1271
  } catch {
1251
1272
  workspaceLabel = "unknown (workspace detection failed)";
1252
1273
  }
@@ -1264,7 +1285,7 @@ async function init(options) {
1264
1285
  const labelIndent = " ".repeat(19);
1265
1286
  console.log(topDivider);
1266
1287
  console.log(` ${dim(labelPad("Workspace:"))} ${cyan(workspaceLabel)}`);
1267
- if (packages.length > 1) for (const package_ of packages) {
1288
+ if (childPackages.length > 1) for (const package_ of childPackages) {
1268
1289
  const bullet = dim(`• ${path.relative(cwd, package_.path)}`);
1269
1290
  console.log(` ${labelIndent}${bullet}`);
1270
1291
  }
@@ -1275,13 +1296,12 @@ async function init(options) {
1275
1296
  if (!_cwd) {
1276
1297
  const stopSpinner = startSpinner("Installing @udohjeremiah/moniq as devDependency...");
1277
1298
  try {
1278
- await installPackage(pm, cwd);
1299
+ await installPackage(pm, cwd, options.version);
1279
1300
  stopSpinner();
1280
- console.log(` Installed @udohjeremiah/moniq as devDependency`);
1281
- console.log();
1301
+ console.log(` Installed @udohjeremiah/moniq as devDependency`);
1282
1302
  } catch (error) {
1283
1303
  stopSpinner();
1284
- const styledError = styleText("red", `❌ ${`Installation failed: ${String(error)}`}`);
1304
+ const styledError = styleText("red", `✘ ${`Installation failed: ${String(error)}`}`);
1285
1305
  console.log(` ${styledError}`);
1286
1306
  console.log(` ${styleText("dim", "Make sure you have a working internet connection and try again.")}`);
1287
1307
  console.log();
@@ -1291,11 +1311,9 @@ async function init(options) {
1291
1311
  }
1292
1312
  const { writeFile } = await import("node:fs/promises");
1293
1313
  await writeFile(configPath, STARTER_CONFIG, "utf8");
1294
- const createdMessage = `✅ Created ${filename}`;
1314
+ const createdMessage = `✔ Created ${filename}`;
1295
1315
  console.log(` ${styleText(["bold", "green"], createdMessage)}`);
1296
1316
  console.log();
1297
- await doctor();
1298
- console.log();
1299
1317
  console.log(` ${styleText("dim", "Next steps:")}`);
1300
1318
  console.log(` 1. ${styleText("dim", "Edit")} ${styleText("cyan", filename)} ${styleText("dim", "to configure your policies.")}`);
1301
1319
  console.log(` 2. ${styleText("dim", "Run")} ${styleText("cyan", "moniq check")} ${styleText("dim", "to validate your workspace.")}`);
@@ -1320,35 +1338,36 @@ async function handleExistingConfig(configPath, filename) {
1320
1338
  if (answer.trim().length === 0) return false;
1321
1339
  return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
1322
1340
  }
1323
- function installArguments(pm) {
1341
+ function installArguments(pm, version) {
1342
+ const spec = version ? `@udohjeremiah/moniq@${version}` : "@udohjeremiah/moniq";
1324
1343
  switch (pm) {
1325
1344
  case "bun": return [
1326
1345
  "add",
1327
1346
  "--dev",
1328
- "@udohjeremiah/moniq"
1347
+ spec
1329
1348
  ];
1330
1349
  case "npm": return [
1331
1350
  "install",
1332
1351
  "--save-dev",
1333
- "@udohjeremiah/moniq"
1352
+ spec
1334
1353
  ];
1335
1354
  case "pnpm": return [
1336
1355
  "add",
1337
1356
  "-D",
1338
1357
  "-w",
1339
- "@udohjeremiah/moniq"
1358
+ spec
1340
1359
  ];
1341
1360
  case "yarn": return [
1342
1361
  "add",
1343
1362
  "--dev",
1344
- "@udohjeremiah/moniq"
1363
+ spec
1345
1364
  ];
1346
1365
  }
1347
1366
  throw new Error(`Unknown package manager: ${pm}`);
1348
1367
  }
1349
- function installPackage(pm, root) {
1368
+ function installPackage(pm, root, version) {
1350
1369
  return new Promise((resolve, reject) => {
1351
- const child = execFile(pm, installArguments(pm), { cwd: root });
1370
+ const child = execFile(pm, installArguments(pm, version), { cwd: root });
1352
1371
  let stderr = "";
1353
1372
  child.stderr?.on("data", (chunk) => {
1354
1373
  stderr += chunk.toString();
@@ -1423,7 +1442,10 @@ cli.command("doctor", "Detect configuration mistakes").action(async () => {
1423
1442
  await doctor();
1424
1443
  });
1425
1444
  cli.command("init", "Scaffold a moniq.config file in the current directory").option("--lang <type>", "Config language: ts, js, mjs, cjs, mts, cts (default: auto-detected)").action(async (options) => {
1426
- await init({ lang: typeof options["lang"] === "string" ? options["lang"] : void 0 });
1445
+ await init({
1446
+ lang: typeof options["lang"] === "string" ? options["lang"] : void 0,
1447
+ version
1448
+ });
1427
1449
  });
1428
1450
  cli.help();
1429
1451
  cli.version(version);