@hasna/microservices 0.0.9 → 0.0.10

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/bin/index.js CHANGED
@@ -3519,8 +3519,8 @@ var {
3519
3519
 
3520
3520
  // src/cli/index.tsx
3521
3521
  import chalk2 from "chalk";
3522
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
3523
- import { join as join4 } from "path";
3522
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
3523
+ import { join as join5 } from "path";
3524
3524
  import { homedir } from "os";
3525
3525
 
3526
3526
  // src/cli/components/App.tsx
@@ -4028,6 +4028,13 @@ var MICROSERVICES = [
4028
4028
  category: "CRM",
4029
4029
  tags: ["social-media", "posts", "scheduling", "engagement", "analytics", "x", "linkedin", "instagram"]
4030
4030
  },
4031
+ {
4032
+ name: "leads",
4033
+ displayName: "Leads",
4034
+ description: "Lead generation, storage, scoring, and data enrichment with pipeline tracking, bulk import/export, and deduplication",
4035
+ category: "CRM",
4036
+ tags: ["leads", "lead-generation", "scoring", "enrichment", "pipeline", "dedup", "import", "export"]
4037
+ },
4031
4038
  {
4032
4039
  name: "inventory",
4033
4040
  displayName: "Inventory",
@@ -4862,6 +4869,28 @@ function resolveSourceDir() {
4862
4869
  return fromBin;
4863
4870
  }
4864
4871
  var SOURCE_DIR = resolveSourceDir();
4872
+ var PRESERVED_DB_FILES = new Set(["data.db", "data.db-wal", "data.db-shm"]);
4873
+ function getCliCandidates(baseDir) {
4874
+ return [
4875
+ join2(baseDir, "src", "cli", "index.ts"),
4876
+ join2(baseDir, "cli.ts"),
4877
+ join2(baseDir, "src", "index.ts")
4878
+ ];
4879
+ }
4880
+ function hasInstalledSource(baseDir) {
4881
+ return getCliCandidates(baseDir).some((candidate) => existsSync2(candidate));
4882
+ }
4883
+ function clearInstalledSource(baseDir) {
4884
+ if (!existsSync2(baseDir)) {
4885
+ return;
4886
+ }
4887
+ for (const entry of readdirSync(baseDir)) {
4888
+ if (PRESERVED_DB_FILES.has(entry)) {
4889
+ continue;
4890
+ }
4891
+ rmSync(join2(baseDir, entry), { recursive: true, force: true });
4892
+ }
4893
+ }
4865
4894
  function getMicroservicePath(name) {
4866
4895
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
4867
4896
  return join2(SOURCE_DIR, msName);
@@ -4899,6 +4928,9 @@ function installMicroservice(name, options = {}) {
4899
4928
  if (!existsSync2(targetDir)) {
4900
4929
  mkdirSync2(targetDir, { recursive: true });
4901
4930
  }
4931
+ if (existsSync2(destPath) && overwrite) {
4932
+ clearInstalledSource(destPath);
4933
+ }
4902
4934
  cpSync(sourcePath, destPath, { recursive: true });
4903
4935
  return {
4904
4936
  microservice: cleanName,
@@ -4923,7 +4955,7 @@ function getInstalledMicroservices(targetDir) {
4923
4955
  }
4924
4956
  return readdirSync(dir).filter((f) => {
4925
4957
  const fullPath = join2(dir, f);
4926
- return f.startsWith("microservice-") && statSync(fullPath).isDirectory();
4958
+ return f.startsWith("microservice-") && statSync(fullPath).isDirectory() && hasInstalledSource(fullPath);
4927
4959
  }).map((f) => f.replace("microservice-", ""));
4928
4960
  }
4929
4961
  function removeMicroservice(name, options = {}) {
@@ -4952,7 +4984,7 @@ function getMicroserviceStatus(name) {
4952
4984
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
4953
4985
  const msPath = join2(dir, msName);
4954
4986
  const dbPath = join2(msPath, "data.db");
4955
- const installed = existsSync2(msPath);
4987
+ const installed = hasInstalledSource(msPath);
4956
4988
  const hasDatabase = existsSync2(dbPath);
4957
4989
  let dbSizeBytes = 0;
4958
4990
  if (hasDatabase) {
@@ -5274,6 +5306,65 @@ function App({ initialServices, overwrite = false }) {
5274
5306
  }, undefined, true, undefined, this);
5275
5307
  }
5276
5308
 
5309
+ // src/cli/config-utils.ts
5310
+ import { mkdirSync as mkdirSync3 } from "fs";
5311
+ import { dirname as dirname3 } from "path";
5312
+ function parseTimeoutMs(raw, fallback = 30000) {
5313
+ if (raw === undefined || raw.trim() === "") {
5314
+ return fallback;
5315
+ }
5316
+ const value = Number(raw);
5317
+ if (!Number.isInteger(value) || value <= 0) {
5318
+ throw new Error("Timeout must be a positive integer in milliseconds.");
5319
+ }
5320
+ return value;
5321
+ }
5322
+ function ensureParentDirectory(filePath) {
5323
+ mkdirSync3(dirname3(filePath), { recursive: true });
5324
+ }
5325
+ function upsertClaudeMcpConfig(content, command) {
5326
+ const parsed = content ? JSON.parse(content) : {};
5327
+ const config = parsed;
5328
+ if (!config.mcpServers) {
5329
+ config.mcpServers = {};
5330
+ }
5331
+ config.mcpServers.microservices = {
5332
+ type: "stdio",
5333
+ command,
5334
+ args: [],
5335
+ env: {}
5336
+ };
5337
+ return JSON.stringify(config, null, 2);
5338
+ }
5339
+ function upsertCodexMcpConfig(content, command) {
5340
+ const existing = content ?? "";
5341
+ if (existing.includes("[mcp_servers.microservices]")) {
5342
+ return { content: existing, alreadyRegistered: true };
5343
+ }
5344
+ const trimmed = existing.trimEnd();
5345
+ const prefix = trimmed.length > 0 ? `${trimmed}
5346
+
5347
+ ` : "";
5348
+ return {
5349
+ content: `${prefix}[mcp_servers.microservices]
5350
+ command = "${command}"
5351
+ `,
5352
+ alreadyRegistered: false
5353
+ };
5354
+ }
5355
+ function upsertGeminiMcpConfig(content, command) {
5356
+ const parsed = content ? JSON.parse(content) : {};
5357
+ const config = parsed;
5358
+ if (!config.mcpServers) {
5359
+ config.mcpServers = {};
5360
+ }
5361
+ config.mcpServers.microservices = {
5362
+ command,
5363
+ args: []
5364
+ };
5365
+ return JSON.stringify(config, null, 2);
5366
+ }
5367
+
5277
5368
  // src/lib/runner.ts
5278
5369
  import { existsSync as existsSync3 } from "fs";
5279
5370
  import { join as join3 } from "path";
@@ -5348,11 +5439,43 @@ async function getMicroserviceOperations(name) {
5348
5439
  return { commands, helpText };
5349
5440
  }
5350
5441
 
5442
+ // src/lib/package-info.ts
5443
+ import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
5444
+ import { dirname as dirname4, join as join4, resolve as resolve2 } from "path";
5445
+ import { fileURLToPath as fileURLToPath2 } from "url";
5446
+ var DEFAULT_VERSION = "0.0.1";
5447
+ function findNearestPackageJson(startDir) {
5448
+ let dir = resolve2(startDir);
5449
+ while (true) {
5450
+ const candidate = join4(dir, "package.json");
5451
+ if (existsSync4(candidate)) {
5452
+ return candidate;
5453
+ }
5454
+ const parent = dirname4(dir);
5455
+ if (parent === dir) {
5456
+ return null;
5457
+ }
5458
+ dir = parent;
5459
+ }
5460
+ }
5461
+ function readPackageVersion(packageJsonPath) {
5462
+ const raw = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
5463
+ return typeof raw.version === "string" && raw.version.length > 0 ? raw.version : DEFAULT_VERSION;
5464
+ }
5465
+ function getPackageVersion(startDir) {
5466
+ const resolvedStartDir = startDir ?? dirname4(fileURLToPath2(import.meta.url));
5467
+ const packageJsonPath = findNearestPackageJson(resolvedStartDir);
5468
+ if (!packageJsonPath) {
5469
+ return DEFAULT_VERSION;
5470
+ }
5471
+ return readPackageVersion(packageJsonPath);
5472
+ }
5473
+
5351
5474
  // src/cli/index.tsx
5352
5475
  import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
5353
5476
  var isTTY = process.stdout.isTTY ?? false;
5354
5477
  var program2 = new Command;
5355
- program2.name("microservices").description("Mini business apps for AI agents \u2014 invoices, contacts, bookkeeping and more").version("0.0.1").enablePositionalOptions();
5478
+ program2.name("microservices").description("Mini business apps for AI agents \u2014 invoices, contacts, bookkeeping and more").version(getPackageVersion()).enablePositionalOptions();
5356
5479
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive microservice browser").action(() => {
5357
5480
  if (!isTTY) {
5358
5481
  console.log(`Non-interactive environment detected. Use a subcommand:
@@ -5540,7 +5663,14 @@ program2.command("run").argument("<name>", "Microservice name").argument("[args.
5540
5663
  console.error(chalk2.red(`Microservice '${name}' is not installed or has no CLI.`));
5541
5664
  process.exit(1);
5542
5665
  }
5543
- const result = await runMicroserviceCommand(name, args, parseInt(options.timeout));
5666
+ let timeout;
5667
+ try {
5668
+ timeout = parseTimeoutMs(options.timeout);
5669
+ } catch (error) {
5670
+ console.error(chalk2.red(error instanceof Error ? error.message : String(error)));
5671
+ process.exit(1);
5672
+ }
5673
+ const result = await runMicroserviceCommand(name, args, timeout);
5544
5674
  if (result.stdout)
5545
5675
  console.log(result.stdout);
5546
5676
  if (result.stderr)
@@ -5563,21 +5693,13 @@ program2.command("ops").argument("<name>", "Microservice name").description("Lis
5563
5693
  program2.command("mcp").description("Register MCP server with AI coding agents").option("--register <target>", "Register with: claude, codex, gemini, or all", "all").action((options) => {
5564
5694
  const target = options.register;
5565
5695
  const mcpBin = "microservices-mcp";
5566
- const mcpBinFull = join4(homedir(), ".bun", "bin", "microservices-mcp");
5696
+ const mcpBinFull = join5(homedir(), ".bun", "bin", "microservices-mcp");
5567
5697
  let registered = 0;
5568
5698
  if (target === "all" || target === "claude") {
5569
- const claudePath = join4(homedir(), ".claude.json");
5699
+ const claudePath = join5(homedir(), ".claude.json");
5570
5700
  try {
5571
- const config = existsSync4(claudePath) ? JSON.parse(readFileSync2(claudePath, "utf-8")) : {};
5572
- if (!config.mcpServers)
5573
- config.mcpServers = {};
5574
- config.mcpServers.microservices = {
5575
- type: "stdio",
5576
- command: mcpBin,
5577
- args: [],
5578
- env: {}
5579
- };
5580
- writeFileSync2(claudePath, JSON.stringify(config, null, 2));
5701
+ const content = existsSync5(claudePath) ? readFileSync3(claudePath, "utf-8") : undefined;
5702
+ writeFileSync2(claudePath, upsertClaudeMcpConfig(content, mcpBin));
5581
5703
  console.log(chalk2.green(" + Claude Code") + chalk2.gray(` (${claudePath})`));
5582
5704
  registered++;
5583
5705
  } catch (e) {
@@ -5585,17 +5707,15 @@ program2.command("mcp").description("Register MCP server with AI coding agents")
5585
5707
  }
5586
5708
  }
5587
5709
  if (target === "all" || target === "codex") {
5588
- const codexPath = join4(homedir(), ".codex", "config.toml");
5710
+ const codexPath = join5(homedir(), ".codex", "config.toml");
5589
5711
  try {
5590
- let content = existsSync4(codexPath) ? readFileSync2(codexPath, "utf-8") : "";
5591
- if (content.includes("[mcp_servers.microservices]")) {
5712
+ const existing = existsSync5(codexPath) ? readFileSync3(codexPath, "utf-8") : undefined;
5713
+ const updated = upsertCodexMcpConfig(existing, mcpBin);
5714
+ if (updated.alreadyRegistered) {
5592
5715
  console.log(chalk2.yellow(" ~ Codex CLI (already registered)"));
5593
5716
  } else {
5594
- content += `
5595
- [mcp_servers.microservices]
5596
- command = "${mcpBin}"
5597
- `;
5598
- writeFileSync2(codexPath, content);
5717
+ ensureParentDirectory(codexPath);
5718
+ writeFileSync2(codexPath, updated.content);
5599
5719
  console.log(chalk2.green(" + Codex CLI") + chalk2.gray(` (${codexPath})`));
5600
5720
  }
5601
5721
  registered++;
@@ -5604,16 +5724,11 @@ command = "${mcpBin}"
5604
5724
  }
5605
5725
  }
5606
5726
  if (target === "all" || target === "gemini") {
5607
- const geminiPath = join4(homedir(), ".gemini", "settings.json");
5727
+ const geminiPath = join5(homedir(), ".gemini", "settings.json");
5608
5728
  try {
5609
- const config = existsSync4(geminiPath) ? JSON.parse(readFileSync2(geminiPath, "utf-8")) : {};
5610
- if (!config.mcpServers)
5611
- config.mcpServers = {};
5612
- config.mcpServers.microservices = {
5613
- command: mcpBinFull,
5614
- args: []
5615
- };
5616
- writeFileSync2(geminiPath, JSON.stringify(config, null, 2));
5729
+ const content = existsSync5(geminiPath) ? readFileSync3(geminiPath, "utf-8") : undefined;
5730
+ ensureParentDirectory(geminiPath);
5731
+ writeFileSync2(geminiPath, upsertGeminiMcpConfig(content, mcpBinFull));
5617
5732
  console.log(chalk2.green(" + Gemini CLI") + chalk2.gray(` (${geminiPath})`));
5618
5733
  registered++;
5619
5734
  } catch (e) {
package/bin/mcp.js CHANGED
@@ -19529,6 +19529,13 @@ var MICROSERVICES = [
19529
19529
  category: "CRM",
19530
19530
  tags: ["social-media", "posts", "scheduling", "engagement", "analytics", "x", "linkedin", "instagram"]
19531
19531
  },
19532
+ {
19533
+ name: "leads",
19534
+ displayName: "Leads",
19535
+ description: "Lead generation, storage, scoring, and data enrichment with pipeline tracking, bulk import/export, and deduplication",
19536
+ category: "CRM",
19537
+ tags: ["leads", "lead-generation", "scoring", "enrichment", "pipeline", "dedup", "import", "export"]
19538
+ },
19532
19539
  {
19533
19540
  name: "inventory",
19534
19541
  displayName: "Inventory",
@@ -19677,6 +19684,28 @@ function resolveSourceDir() {
19677
19684
  return fromBin;
19678
19685
  }
19679
19686
  var SOURCE_DIR = resolveSourceDir();
19687
+ var PRESERVED_DB_FILES = new Set(["data.db", "data.db-wal", "data.db-shm"]);
19688
+ function getCliCandidates(baseDir) {
19689
+ return [
19690
+ join2(baseDir, "src", "cli", "index.ts"),
19691
+ join2(baseDir, "cli.ts"),
19692
+ join2(baseDir, "src", "index.ts")
19693
+ ];
19694
+ }
19695
+ function hasInstalledSource(baseDir) {
19696
+ return getCliCandidates(baseDir).some((candidate) => existsSync2(candidate));
19697
+ }
19698
+ function clearInstalledSource(baseDir) {
19699
+ if (!existsSync2(baseDir)) {
19700
+ return;
19701
+ }
19702
+ for (const entry of readdirSync(baseDir)) {
19703
+ if (PRESERVED_DB_FILES.has(entry)) {
19704
+ continue;
19705
+ }
19706
+ rmSync(join2(baseDir, entry), { recursive: true, force: true });
19707
+ }
19708
+ }
19680
19709
  function getMicroservicePath(name) {
19681
19710
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
19682
19711
  return join2(SOURCE_DIR, msName);
@@ -19714,6 +19743,9 @@ function installMicroservice(name, options = {}) {
19714
19743
  if (!existsSync2(targetDir)) {
19715
19744
  mkdirSync2(targetDir, { recursive: true });
19716
19745
  }
19746
+ if (existsSync2(destPath) && overwrite) {
19747
+ clearInstalledSource(destPath);
19748
+ }
19717
19749
  cpSync(sourcePath, destPath, { recursive: true });
19718
19750
  return {
19719
19751
  microservice: cleanName,
@@ -19735,7 +19767,7 @@ function getInstalledMicroservices(targetDir) {
19735
19767
  }
19736
19768
  return readdirSync(dir).filter((f) => {
19737
19769
  const fullPath = join2(dir, f);
19738
- return f.startsWith("microservice-") && statSync(fullPath).isDirectory();
19770
+ return f.startsWith("microservice-") && statSync(fullPath).isDirectory() && hasInstalledSource(fullPath);
19739
19771
  }).map((f) => f.replace("microservice-", ""));
19740
19772
  }
19741
19773
  function removeMicroservice(name, options = {}) {
@@ -19764,7 +19796,7 @@ function getMicroserviceStatus(name) {
19764
19796
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
19765
19797
  const msPath = join2(dir, msName);
19766
19798
  const dbPath = join2(msPath, "data.db");
19767
- const installed = existsSync2(msPath);
19799
+ const installed = hasInstalledSource(msPath);
19768
19800
  const hasDatabase = existsSync2(dbPath);
19769
19801
  let dbSizeBytes = 0;
19770
19802
  if (hasDatabase) {
@@ -19855,10 +19887,42 @@ async function getMicroserviceOperations(name) {
19855
19887
  return { commands, helpText };
19856
19888
  }
19857
19889
 
19890
+ // src/lib/package-info.ts
19891
+ import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
19892
+ import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
19893
+ import { fileURLToPath as fileURLToPath2 } from "url";
19894
+ var DEFAULT_VERSION = "0.0.1";
19895
+ function findNearestPackageJson(startDir) {
19896
+ let dir = resolve2(startDir);
19897
+ while (true) {
19898
+ const candidate = join4(dir, "package.json");
19899
+ if (existsSync4(candidate)) {
19900
+ return candidate;
19901
+ }
19902
+ const parent = dirname3(dir);
19903
+ if (parent === dir) {
19904
+ return null;
19905
+ }
19906
+ dir = parent;
19907
+ }
19908
+ }
19909
+ function readPackageVersion(packageJsonPath) {
19910
+ const raw = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
19911
+ return typeof raw.version === "string" && raw.version.length > 0 ? raw.version : DEFAULT_VERSION;
19912
+ }
19913
+ function getPackageVersion(startDir) {
19914
+ const resolvedStartDir = startDir ?? dirname3(fileURLToPath2(import.meta.url));
19915
+ const packageJsonPath = findNearestPackageJson(resolvedStartDir);
19916
+ if (!packageJsonPath) {
19917
+ return DEFAULT_VERSION;
19918
+ }
19919
+ return readPackageVersion(packageJsonPath);
19920
+ }
19921
+
19858
19922
  // src/mcp/index.ts
19859
19923
  var server = new McpServer({
19860
19924
  name: "microservices",
19861
- version: "0.0.1"
19925
+ version: getPackageVersion()
19862
19926
  });
19863
19927
  server.registerTool("search_microservices", {
19864
19928
  title: "Search Microservices",
package/dist/index.js CHANGED
@@ -73,6 +73,13 @@ var MICROSERVICES = [
73
73
  category: "CRM",
74
74
  tags: ["social-media", "posts", "scheduling", "engagement", "analytics", "x", "linkedin", "instagram"]
75
75
  },
76
+ {
77
+ name: "leads",
78
+ displayName: "Leads",
79
+ description: "Lead generation, storage, scoring, and data enrichment with pipeline tracking, bulk import/export, and deduplication",
80
+ category: "CRM",
81
+ tags: ["leads", "lead-generation", "scoring", "enrichment", "pipeline", "dedup", "import", "export"]
82
+ },
76
83
  {
77
84
  name: "inventory",
78
85
  displayName: "Inventory",
@@ -270,6 +277,28 @@ function resolveSourceDir() {
270
277
  return fromBin;
271
278
  }
272
279
  var SOURCE_DIR = resolveSourceDir();
280
+ var PRESERVED_DB_FILES = new Set(["data.db", "data.db-wal", "data.db-shm"]);
281
+ function getCliCandidates(baseDir) {
282
+ return [
283
+ join2(baseDir, "src", "cli", "index.ts"),
284
+ join2(baseDir, "cli.ts"),
285
+ join2(baseDir, "src", "index.ts")
286
+ ];
287
+ }
288
+ function hasInstalledSource(baseDir) {
289
+ return getCliCandidates(baseDir).some((candidate) => existsSync2(candidate));
290
+ }
291
+ function clearInstalledSource(baseDir) {
292
+ if (!existsSync2(baseDir)) {
293
+ return;
294
+ }
295
+ for (const entry of readdirSync(baseDir)) {
296
+ if (PRESERVED_DB_FILES.has(entry)) {
297
+ continue;
298
+ }
299
+ rmSync(join2(baseDir, entry), { recursive: true, force: true });
300
+ }
301
+ }
273
302
  function getMicroservicePath(name) {
274
303
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
275
304
  return join2(SOURCE_DIR, msName);
@@ -310,6 +339,9 @@ function installMicroservice(name, options = {}) {
310
339
  if (!existsSync2(targetDir)) {
311
340
  mkdirSync2(targetDir, { recursive: true });
312
341
  }
342
+ if (existsSync2(destPath) && overwrite) {
343
+ clearInstalledSource(destPath);
344
+ }
313
345
  cpSync(sourcePath, destPath, { recursive: true });
314
346
  return {
315
347
  microservice: cleanName,
@@ -334,7 +366,7 @@ function getInstalledMicroservices(targetDir) {
334
366
  }
335
367
  return readdirSync(dir).filter((f) => {
336
368
  const fullPath = join2(dir, f);
337
- return f.startsWith("microservice-") && statSync(fullPath).isDirectory();
369
+ return f.startsWith("microservice-") && statSync(fullPath).isDirectory() && hasInstalledSource(fullPath);
338
370
  }).map((f) => f.replace("microservice-", ""));
339
371
  }
340
372
  function removeMicroservice(name, options = {}) {
@@ -363,7 +395,7 @@ function getMicroserviceStatus(name) {
363
395
  const msName = name.startsWith("microservice-") ? name : `microservice-${name}`;
364
396
  const msPath = join2(dir, msName);
365
397
  const dbPath = join2(msPath, "data.db");
366
- const installed = existsSync2(msPath);
398
+ const installed = hasInstalledSource(msPath);
367
399
  const hasDatabase = existsSync2(dbPath);
368
400
  let dbSizeBytes = 0;
369
401
  if (hasDatabase) {
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@hasna/microservice-leads",
3
+ "version": "0.0.1",
4
+ "description": "Lead generation, storage, scoring, and data enrichment microservice for AI agents",
5
+ "type": "module",
6
+ "bin": {
7
+ "microservice-leads": "./src/cli/index.ts",
8
+ "microservice-leads-mcp": "./src/mcp/index.ts"
9
+ },
10
+ "exports": {
11
+ ".": "./src/index.ts"
12
+ },
13
+ "scripts": {
14
+ "dev": "bun run ./src/cli/index.ts",
15
+ "test": "bun test"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.26.0",
19
+ "commander": "^12.1.0",
20
+ "zod": "^3.24.0"
21
+ },
22
+ "license": "Apache-2.0",
23
+ "publishConfig": {
24
+ "registry": "https://registry.npmjs.org",
25
+ "access": "public"
26
+ }
27
+ }