@calimero-network/registry-cli 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import chalk6 from 'chalk';
4
4
  import ora6 from 'ora';
5
5
  import { table } from 'table';
6
6
  import axios from 'axios';
7
- import fs3, { existsSync, writeFileSync } from 'fs';
7
+ import fs9, { existsSync, writeFileSync } from 'fs';
8
8
  import path7 from 'path';
9
9
  import os from 'os';
10
10
  import crypto from 'crypto';
@@ -430,10 +430,10 @@ var LocalConfig = class {
430
430
  allowedTypes: ["wasm", "js", "html"]
431
431
  }
432
432
  };
433
- if (fs3.existsSync(this.configPath)) {
433
+ if (fs9.existsSync(this.configPath)) {
434
434
  try {
435
435
  const existingConfig = JSON.parse(
436
- fs3.readFileSync(this.configPath, "utf8")
436
+ fs9.readFileSync(this.configPath, "utf8")
437
437
  );
438
438
  return {
439
439
  server: {
@@ -457,10 +457,10 @@ var LocalConfig = class {
457
457
  }
458
458
  saveConfig() {
459
459
  const configDir = path7.dirname(this.configPath);
460
- if (!fs3.existsSync(configDir)) {
461
- fs3.mkdirSync(configDir, { recursive: true });
460
+ if (!fs9.existsSync(configDir)) {
461
+ fs9.mkdirSync(configDir, { recursive: true });
462
462
  }
463
- fs3.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
463
+ fs9.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
464
464
  }
465
465
  // Server configuration
466
466
  getPort() {
@@ -518,8 +518,8 @@ var LocalConfig = class {
518
518
  path7.join(this.getDataDir(), "logs")
519
519
  ];
520
520
  dirs.forEach((dir) => {
521
- if (!fs3.existsSync(dir)) {
522
- fs3.mkdirSync(dir, { recursive: true });
521
+ if (!fs9.existsSync(dir)) {
522
+ fs9.mkdirSync(dir, { recursive: true });
523
523
  }
524
524
  });
525
525
  }
@@ -574,21 +574,21 @@ var LocalDataStore = class {
574
574
  }
575
575
  loadData() {
576
576
  try {
577
- if (fs3.existsSync(this.appsFile)) {
578
- const appsData = JSON.parse(fs3.readFileSync(this.appsFile, "utf8"));
577
+ if (fs9.existsSync(this.appsFile)) {
578
+ const appsData = JSON.parse(fs9.readFileSync(this.appsFile, "utf8"));
579
579
  this.data.apps = new Map(Object.entries(appsData));
580
580
  }
581
- if (fs3.existsSync(this.bundleManifestsFile)) {
581
+ if (fs9.existsSync(this.bundleManifestsFile)) {
582
582
  const bundleManifestsData = JSON.parse(
583
- fs3.readFileSync(this.bundleManifestsFile, "utf8")
583
+ fs9.readFileSync(this.bundleManifestsFile, "utf8")
584
584
  );
585
585
  this.data.bundleManifests = new Map(
586
586
  Object.entries(bundleManifestsData)
587
587
  );
588
588
  }
589
- if (fs3.existsSync(this.artifactsFile)) {
589
+ if (fs9.existsSync(this.artifactsFile)) {
590
590
  const artifactsData = JSON.parse(
591
- fs3.readFileSync(this.artifactsFile, "utf8")
591
+ fs9.readFileSync(this.artifactsFile, "utf8")
592
592
  );
593
593
  this.data.artifacts = new Map(Object.entries(artifactsData));
594
594
  }
@@ -600,14 +600,14 @@ var LocalDataStore = class {
600
600
  try {
601
601
  this.config.ensureDirectories();
602
602
  const appsObj = Object.fromEntries(this.data.apps);
603
- fs3.writeFileSync(this.appsFile, JSON.stringify(appsObj, null, 2));
603
+ fs9.writeFileSync(this.appsFile, JSON.stringify(appsObj, null, 2));
604
604
  const bundleManifestsObj = Object.fromEntries(this.data.bundleManifests);
605
- fs3.writeFileSync(
605
+ fs9.writeFileSync(
606
606
  this.bundleManifestsFile,
607
607
  JSON.stringify(bundleManifestsObj, null, 2)
608
608
  );
609
609
  const artifactsObj = Object.fromEntries(this.data.artifacts);
610
- fs3.writeFileSync(
610
+ fs9.writeFileSync(
611
611
  this.artifactsFile,
612
612
  JSON.stringify(artifactsObj, null, 2)
613
613
  );
@@ -690,8 +690,8 @@ var LocalDataStore = class {
690
690
  `backup-${timestamp}.json`
691
691
  );
692
692
  const backupDir = path7.dirname(backupPath);
693
- if (!fs3.existsSync(backupDir)) {
694
- fs3.mkdirSync(backupDir, { recursive: true });
693
+ if (!fs9.existsSync(backupDir)) {
694
+ fs9.mkdirSync(backupDir, { recursive: true });
695
695
  }
696
696
  const backupData = {
697
697
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -699,14 +699,14 @@ var LocalDataStore = class {
699
699
  bundleManifests: Object.fromEntries(this.data.bundleManifests),
700
700
  artifacts: Object.fromEntries(this.data.artifacts)
701
701
  };
702
- fs3.writeFileSync(backupPath, JSON.stringify(backupData, null, 2));
702
+ fs9.writeFileSync(backupPath, JSON.stringify(backupData, null, 2));
703
703
  return backupPath;
704
704
  }
705
705
  async restore(backupPath) {
706
- if (!fs3.existsSync(backupPath)) {
706
+ if (!fs9.existsSync(backupPath)) {
707
707
  throw new Error(`Backup file not found: ${backupPath}`);
708
708
  }
709
- const backupData = JSON.parse(fs3.readFileSync(backupPath, "utf8"));
709
+ const backupData = JSON.parse(fs9.readFileSync(backupPath, "utf8"));
710
710
  this.data.apps = new Map(Object.entries(backupData.apps || {}));
711
711
  this.data.bundleManifests = new Map(
712
712
  Object.entries(backupData.bundleManifests || {})
@@ -774,21 +774,21 @@ var LocalArtifactServer = class {
774
774
  this.ensureArtifactsDir();
775
775
  }
776
776
  ensureArtifactsDir() {
777
- if (!fs3.existsSync(this.artifactsDir)) {
778
- fs3.mkdirSync(this.artifactsDir, { recursive: true });
777
+ if (!fs9.existsSync(this.artifactsDir)) {
778
+ fs9.mkdirSync(this.artifactsDir, { recursive: true });
779
779
  }
780
780
  }
781
781
  // Copy artifact to local storage
782
782
  async copyArtifactToLocal(sourcePath, appId, version, filename) {
783
- if (!fs3.existsSync(sourcePath)) {
783
+ if (!fs9.existsSync(sourcePath)) {
784
784
  throw new Error(`Source file not found: ${sourcePath}`);
785
785
  }
786
786
  const appVersionDir = path7.join(this.artifactsDir, appId, version);
787
- if (!fs3.existsSync(appVersionDir)) {
788
- fs3.mkdirSync(appVersionDir, { recursive: true });
787
+ if (!fs9.existsSync(appVersionDir)) {
788
+ fs9.mkdirSync(appVersionDir, { recursive: true });
789
789
  }
790
790
  const targetPath = path7.join(appVersionDir, filename);
791
- fs3.copyFileSync(sourcePath, targetPath);
791
+ fs9.copyFileSync(sourcePath, targetPath);
792
792
  const fileHash = await this.calculateFileHash(targetPath);
793
793
  this.dataStore.setArtifactPath(fileHash, targetPath);
794
794
  return targetPath;
@@ -796,26 +796,26 @@ var LocalArtifactServer = class {
796
796
  // Serve artifact by app ID, version, and filename
797
797
  async serveArtifact(appId, version, filename) {
798
798
  const artifactPath = path7.join(this.artifactsDir, appId, version, filename);
799
- if (!fs3.existsSync(artifactPath)) {
799
+ if (!fs9.existsSync(artifactPath)) {
800
800
  throw new Error(`Artifact not found: ${artifactPath}`);
801
801
  }
802
- return fs3.readFileSync(artifactPath);
802
+ return fs9.readFileSync(artifactPath);
803
803
  }
804
804
  // Serve artifact by hash
805
805
  async serveByHash(hash) {
806
806
  const artifactPath = this.dataStore.getArtifactPath(hash);
807
- if (!artifactPath || !fs3.existsSync(artifactPath)) {
807
+ if (!artifactPath || !fs9.existsSync(artifactPath)) {
808
808
  throw new Error(`Artifact not found for hash: ${hash}`);
809
809
  }
810
- return fs3.readFileSync(artifactPath);
810
+ return fs9.readFileSync(artifactPath);
811
811
  }
812
812
  // Validate artifact file
813
813
  async validateArtifact(filePath) {
814
- if (!fs3.existsSync(filePath)) {
814
+ if (!fs9.existsSync(filePath)) {
815
815
  throw new Error(`File not found: ${filePath}`);
816
816
  }
817
- const stats = fs3.statSync(filePath);
818
- const fileBuffer = fs3.readFileSync(filePath);
817
+ const stats = fs9.statSync(filePath);
818
+ const fileBuffer = fs9.readFileSync(filePath);
819
819
  const sha256 = crypto.createHash("sha256").update(fileBuffer).digest("hex");
820
820
  return {
821
821
  size: stats.size,
@@ -824,7 +824,7 @@ var LocalArtifactServer = class {
824
824
  }
825
825
  // Calculate file hash
826
826
  async calculateFileHash(filePath) {
827
- const fileBuffer = fs3.readFileSync(filePath);
827
+ const fileBuffer = fs9.readFileSync(filePath);
828
828
  return crypto.createHash("sha256").update(fileBuffer).digest("hex");
829
829
  }
830
830
  // Get artifact URL for local serving
@@ -864,10 +864,10 @@ var LocalArtifactServer = class {
864
864
  const now = Date.now();
865
865
  const getAllFiles = (dir) => {
866
866
  let files = [];
867
- const items = fs3.readdirSync(dir);
867
+ const items = fs9.readdirSync(dir);
868
868
  for (const item of items) {
869
869
  const fullPath = path7.join(dir, item);
870
- const stat = fs3.statSync(fullPath);
870
+ const stat = fs9.statSync(fullPath);
871
871
  if (stat.isDirectory()) {
872
872
  files = files.concat(getAllFiles(fullPath));
873
873
  } else {
@@ -878,10 +878,10 @@ var LocalArtifactServer = class {
878
878
  };
879
879
  const allFiles = getAllFiles(this.artifactsDir);
880
880
  for (const file of allFiles) {
881
- const stats = fs3.statSync(file);
881
+ const stats = fs9.statSync(file);
882
882
  const age = now - stats.mtime.getTime();
883
883
  if (age > maxAge) {
884
- fs3.unlinkSync(file);
884
+ fs9.unlinkSync(file);
885
885
  console.log(`Cleaned up old artifact: ${file}`);
886
886
  }
887
887
  }
@@ -893,10 +893,10 @@ var LocalArtifactServer = class {
893
893
  let oldestFile = null;
894
894
  const getAllFiles = (dir) => {
895
895
  let files = [];
896
- const items = fs3.readdirSync(dir);
896
+ const items = fs9.readdirSync(dir);
897
897
  for (const item of items) {
898
898
  const fullPath = path7.join(dir, item);
899
- const stat = fs3.statSync(fullPath);
899
+ const stat = fs9.statSync(fullPath);
900
900
  if (stat.isDirectory()) {
901
901
  files = files.concat(getAllFiles(fullPath));
902
902
  } else {
@@ -905,10 +905,10 @@ var LocalArtifactServer = class {
905
905
  }
906
906
  return files;
907
907
  };
908
- if (fs3.existsSync(this.artifactsDir)) {
908
+ if (fs9.existsSync(this.artifactsDir)) {
909
909
  const allFiles = getAllFiles(this.artifactsDir);
910
910
  for (const file of allFiles) {
911
- const stats = fs3.statSync(file);
911
+ const stats = fs9.statSync(file);
912
912
  totalFiles++;
913
913
  totalSize += stats.size;
914
914
  if (!oldestFile || stats.mtime < oldestFile) {
@@ -994,7 +994,7 @@ var LocalRegistryClient = class {
994
994
  const processedManifest = { ...manifest };
995
995
  if (manifest.artifact?.uri?.startsWith("file://")) {
996
996
  const filePath = manifest.artifact.uri.replace("file://", "");
997
- if (fs3.existsSync(filePath)) {
997
+ if (fs9.existsSync(filePath)) {
998
998
  const filename = path7.basename(filePath);
999
999
  try {
1000
1000
  await this.artifactServer.copyArtifactToLocal(
@@ -1138,12 +1138,12 @@ var appsCommand = new Command("apps").description("Manage SSApp applications").a
1138
1138
  const spinner2 = ora6("Reading manifest file...").start();
1139
1139
  try {
1140
1140
  const manifestPath = path7.resolve(manifestFile);
1141
- if (!fs3.existsSync(manifestPath)) {
1141
+ if (!fs9.existsSync(manifestPath)) {
1142
1142
  spinner2.fail("Manifest file not found");
1143
1143
  console.error(chalk6.red(`File not found: ${manifestFile}`));
1144
1144
  process.exit(1);
1145
1145
  }
1146
- const manifestContent = fs3.readFileSync(manifestPath, "utf8");
1146
+ const manifestContent = fs9.readFileSync(manifestPath, "utf8");
1147
1147
  const manifest = JSON.parse(manifestContent);
1148
1148
  spinner2.text = "Submitting application manifest...";
1149
1149
  const result = await client.submitAppManifest(manifest);
@@ -1423,8 +1423,8 @@ var LocalRegistryServer = class {
1423
1423
  async reset() {
1424
1424
  this.dataStore.reset();
1425
1425
  const artifactsDir = this.config.getArtifactsDir();
1426
- if (fs3.existsSync(artifactsDir)) {
1427
- fs3.rmSync(artifactsDir, { recursive: true, force: true });
1426
+ if (fs9.existsSync(artifactsDir)) {
1427
+ fs9.rmSync(artifactsDir, { recursive: true, force: true });
1428
1428
  }
1429
1429
  }
1430
1430
  async backup(outputPath) {
@@ -1727,7 +1727,7 @@ localCommand.addCommand(
1727
1727
  new Command("restore").description("Restore local registry data from backup").argument("<backup-file>", "Path to backup file").action(async (backupFile) => {
1728
1728
  const spinner2 = ora6("Restoring from backup...").start();
1729
1729
  try {
1730
- if (!fs3.existsSync(backupFile)) {
1730
+ if (!fs9.existsSync(backupFile)) {
1731
1731
  spinner2.fail("Backup file not found");
1732
1732
  console.error(chalk6.red(`File not found: ${backupFile}`));
1733
1733
  process.exit(1);
@@ -1786,10 +1786,10 @@ var RemoteConfig = class {
1786
1786
  url: "https://apps.calimero.network"
1787
1787
  }
1788
1788
  };
1789
- if (fs3.existsSync(this.configPath)) {
1789
+ if (fs9.existsSync(this.configPath)) {
1790
1790
  try {
1791
1791
  const existingConfig = JSON.parse(
1792
- fs3.readFileSync(this.configPath, "utf8")
1792
+ fs9.readFileSync(this.configPath, "utf8")
1793
1793
  );
1794
1794
  return {
1795
1795
  registry: {
@@ -1805,8 +1805,8 @@ var RemoteConfig = class {
1805
1805
  }
1806
1806
  saveConfig() {
1807
1807
  const configDir = path7.dirname(this.configPath);
1808
- if (!fs3.existsSync(configDir)) {
1809
- fs3.mkdirSync(configDir, { recursive: true });
1808
+ if (!fs9.existsSync(configDir)) {
1809
+ fs9.mkdirSync(configDir, { recursive: true });
1810
1810
  }
1811
1811
  const configToSave = {
1812
1812
  registry: {
@@ -1815,7 +1815,7 @@ var RemoteConfig = class {
1815
1815
  ...this.config.registry.apiKey ? { apiKey: this.config.registry.apiKey } : {}
1816
1816
  }
1817
1817
  };
1818
- fs3.writeFileSync(this.configPath, JSON.stringify(configToSave, null, 2));
1818
+ fs9.writeFileSync(this.configPath, JSON.stringify(configToSave, null, 2));
1819
1819
  }
1820
1820
  /**
1821
1821
  * Get registry URL with priority:
@@ -1890,7 +1890,10 @@ var RemoteConfig = class {
1890
1890
  // src/commands/bundle.ts
1891
1891
  var bundleCommand = new Command("bundle").description("Manage application bundles (V2)").addCommand(createCreateCommand()).addCommand(createPushCommand()).addCommand(createGetCommand());
1892
1892
  function createCreateCommand() {
1893
- return new Command("create").description("Create an MPK bundle from a WASM file").argument("<wasm-file>", "Path to the WASM file").argument("<package>", "Package name (e.g. com.calimero.myapp)").argument("<version>", "Version (e.g. 1.0.0)").option("-o, --output <path>", "Output path for the MPK file").option("--name <name>", "Application name").option("--description <description>", "Application description").option("--author <author>", "Application author", "Calimero Team").option("--frontend <url>", "Frontend URL").option("--github <url>", "GitHub URL").option("--docs <url>", "Documentation URL").option(
1893
+ return new Command("create").description("Create an MPK bundle from a WASM file").argument("<wasm-file>", "Path to the WASM file").argument("[package]", "Package name (e.g. com.calimero.myapp)").argument("[version]", "Version (e.g. 1.0.0)").option(
1894
+ "-m, --manifest <path>",
1895
+ "Path to manifest JSON file (can contain package, version, and other options)"
1896
+ ).option("-o, --output <path>", "Output path for the MPK file").option("--name <name>", "Application name").option("--description <description>", "Application description").option("--author <author>", "Application author").option("--frontend <url>", "Frontend URL").option("--github <url>", "GitHub URL").option("--docs <url>", "Documentation URL").option(
1894
1897
  "--export <interface>",
1895
1898
  "Export interface (can be specified multiple times)",
1896
1899
  (value, prev) => {
@@ -1902,88 +1905,258 @@ function createCreateCommand() {
1902
1905
  (value, prev) => {
1903
1906
  return [...prev || [], value];
1904
1907
  }
1908
+ ).option("--abi <path>", "Path to ABI JSON file to include in bundle").addHelpText(
1909
+ "after",
1910
+ `
1911
+ Examples:
1912
+ $ calimero-registry bundle create app.wasm com.calimero.myapp 1.0.0
1913
+ $ calimero-registry bundle create app.wasm --manifest bundle-manifest.json
1914
+ $ calimero-registry bundle create app.wasm --manifest bundle-manifest.json -o output.mpk
1915
+ $ calimero-registry bundle create app.wasm com.calimero.myapp 1.0.0 --name "My App" --frontend https://app.example.com
1916
+ $ calimero-registry bundle create app.wasm com.calimero.myapp 1.0.0 --abi abi.json
1917
+ $ calimero-registry bundle create app.wasm --manifest manifest.json --abi res/abi.json
1918
+
1919
+ Manifest File Format (JSON):
1920
+ {
1921
+ "package": "com.calimero.myapp",
1922
+ "version": "1.0.0",
1923
+ "output": "./dist/myapp.mpk",
1924
+ "name": "My Application",
1925
+ "description": "Application description",
1926
+ "author": "Calimero Team",
1927
+ "frontend": "https://app.example.com",
1928
+ "github": "https://github.com/user/repo",
1929
+ "docs": "https://docs.example.com",
1930
+ "exports": ["interface1", "interface2"],
1931
+ "uses": ["interface3"],
1932
+ "abi": "res/abi.json"
1933
+ }
1934
+
1935
+ Note:
1936
+ - Package and version can be provided via arguments, manifest file, or both
1937
+ - CLI arguments take precedence over manifest file values
1938
+ - If using manifest file, package and version can be omitted from command line
1939
+ - The -o/--output option overrides manifest.output if both are provided
1940
+ - ABI can be provided via --abi flag or manifest.abi field (file path string)
1941
+ - ABI file will be included in the bundle and referenced in the manifest
1942
+ `
1905
1943
  ).action(async (wasmFile, pkg, version, options) => {
1906
1944
  try {
1945
+ let manifestConfig = {};
1946
+ if (options.manifest) {
1947
+ const manifestPath = path7.resolve(options.manifest);
1948
+ if (!fs9.existsSync(manifestPath)) {
1949
+ console.error(`\u274C Manifest file not found: ${options.manifest}`);
1950
+ process.exit(1);
1951
+ }
1952
+ try {
1953
+ const manifestContent = fs9.readFileSync(manifestPath, "utf8");
1954
+ const parsed = JSON.parse(manifestContent);
1955
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1956
+ console.error(`\u274C Invalid manifest file: ${options.manifest}`);
1957
+ console.error(" Manifest must be a JSON object");
1958
+ process.exit(1);
1959
+ }
1960
+ manifestConfig = parsed;
1961
+ } catch (error) {
1962
+ console.error(
1963
+ `\u274C Failed to parse manifest file: ${options.manifest}`
1964
+ );
1965
+ console.error(
1966
+ error instanceof Error ? error.message : "Invalid JSON"
1967
+ );
1968
+ process.exit(1);
1969
+ }
1970
+ }
1971
+ const finalPackage = pkg || manifestConfig.package;
1972
+ const finalVersion = version || manifestConfig.version;
1973
+ const finalOutput = options.output || manifestConfig.output;
1974
+ const finalName = options.name || manifestConfig.name;
1975
+ const finalDescription = options.description || manifestConfig.description;
1976
+ const finalAuthor = options.author || manifestConfig.author || "Calimero Team";
1977
+ const finalFrontend = options.frontend || manifestConfig.frontend;
1978
+ const finalGithub = options.github || manifestConfig.github;
1979
+ const finalDocs = options.docs || manifestConfig.docs;
1980
+ const manifestExports = manifestConfig.exports;
1981
+ const manifestUses = manifestConfig.uses;
1982
+ if (manifestExports !== void 0 && !Array.isArray(manifestExports)) {
1983
+ console.error('\u274C Invalid manifest: "exports" must be an array');
1984
+ process.exit(1);
1985
+ }
1986
+ if (manifestUses !== void 0 && !Array.isArray(manifestUses)) {
1987
+ console.error('\u274C Invalid manifest: "uses" must be an array');
1988
+ process.exit(1);
1989
+ }
1990
+ const finalExports = options.export && options.export.length > 0 ? options.export : manifestExports || [];
1991
+ const finalUses = options.use && options.use.length > 0 ? options.use : manifestUses || [];
1992
+ if (!wasmFile) {
1993
+ console.error("\u274C WASM file is required");
1994
+ process.exit(1);
1995
+ }
1996
+ if (!finalPackage) {
1997
+ console.error(
1998
+ "\u274C Package name is required (provide via argument, --manifest file, or manifest.package)"
1999
+ );
2000
+ process.exit(1);
2001
+ }
2002
+ if (!finalVersion) {
2003
+ console.error(
2004
+ "\u274C Version is required (provide via argument, --manifest file, or manifest.version)"
2005
+ );
2006
+ process.exit(1);
2007
+ }
2008
+ if (!/^[a-z0-9-]+(\.[a-z0-9-]+)+$/.test(finalPackage)) {
2009
+ console.error(
2010
+ "\u274C Invalid package name format. Expected format: com.calimero.myapp or com.my-org.my-app"
2011
+ );
2012
+ process.exit(1);
2013
+ }
2014
+ if (!/^\d+\.\d+\.\d+(-[a-z0-9.-]+)?(\+[a-z0-9.-]+)?$/i.test(finalVersion)) {
2015
+ console.error(
2016
+ "\u274C Invalid version format. Expected format: 1.0.0, 1.0.0-alpha, or 1.0.0-alpha.1"
2017
+ );
2018
+ process.exit(1);
2019
+ }
1907
2020
  const wasmPath = path7.resolve(wasmFile);
1908
- if (!fs3.existsSync(wasmPath)) {
2021
+ if (!fs9.existsSync(wasmPath)) {
1909
2022
  console.error(`\u274C WASM file not found: ${wasmFile}`);
1910
2023
  process.exit(1);
1911
2024
  }
1912
2025
  console.log(`\u{1F4E6} Creating MPK bundle from: ${path7.basename(wasmPath)}`);
1913
- const wasmContent = fs3.readFileSync(wasmPath);
2026
+ const wasmContent = fs9.readFileSync(wasmPath);
1914
2027
  const wasmSize = wasmContent.length;
1915
- const hash = crypto.createHash("sha256").update(wasmContent).digest("hex");
2028
+ const wasmHash = crypto.createHash("sha256").update(wasmContent).digest("hex");
2029
+ let abiArtifact = void 0;
2030
+ let abiContent = null;
2031
+ const abiPathFromOption = options.abi;
2032
+ const abiPathFromManifest = typeof manifestConfig.abi === "string" ? manifestConfig.abi : null;
2033
+ const abiFilePath = abiPathFromOption || abiPathFromManifest;
2034
+ if (abiFilePath) {
2035
+ const abiResolvedPath = abiPathFromOption ? path7.resolve(abiFilePath) : options.manifest && abiPathFromManifest ? path7.resolve(
2036
+ path7.dirname(path7.resolve(options.manifest)),
2037
+ abiFilePath
2038
+ ) : path7.resolve(abiFilePath);
2039
+ if (!fs9.existsSync(abiResolvedPath)) {
2040
+ console.error(`\u274C ABI file not found: ${abiFilePath}`);
2041
+ console.error(` Resolved path: ${abiResolvedPath}`);
2042
+ process.exit(1);
2043
+ }
2044
+ try {
2045
+ abiContent = fs9.readFileSync(abiResolvedPath);
2046
+ JSON.parse(abiContent.toString("utf8"));
2047
+ const abiHash = crypto.createHash("sha256").update(abiContent).digest("hex");
2048
+ abiArtifact = {
2049
+ path: "abi.json",
2050
+ hash: abiHash,
2051
+ size: abiContent.length
2052
+ };
2053
+ console.log(
2054
+ ` Including ABI file: ${path7.basename(abiResolvedPath)}`
2055
+ );
2056
+ } catch (error) {
2057
+ console.error(
2058
+ `\u274C Failed to read or parse ABI file: ${abiFilePath}`
2059
+ );
2060
+ console.error(
2061
+ error instanceof Error ? error.message : "Invalid JSON"
2062
+ );
2063
+ process.exit(1);
2064
+ }
2065
+ } else if (manifestConfig.abi && typeof manifestConfig.abi === "object") {
2066
+ console.error(
2067
+ "\u274C Manifest provides ABI as object, but --abi flag is required to include the ABI file in bundle"
2068
+ );
2069
+ console.error(
2070
+ " Provide the ABI file path with --abi flag, or change manifest.abi to a file path string"
2071
+ );
2072
+ process.exit(1);
2073
+ }
1916
2074
  const metadata = {
1917
- name: options.name || pkg,
1918
- description: options.description || "",
1919
- author: options.author || "Calimero Team"
2075
+ name: finalName || finalPackage,
2076
+ description: finalDescription || "",
2077
+ author: finalAuthor
1920
2078
  };
1921
2079
  const links = {};
1922
- if (options.frontend) links.frontend = options.frontend;
1923
- if (options.github) links.github = options.github;
1924
- if (options.docs) links.docs = options.docs;
2080
+ if (finalFrontend) links.frontend = finalFrontend;
2081
+ if (finalGithub) links.github = finalGithub;
2082
+ if (finalDocs) links.docs = finalDocs;
1925
2083
  const interfaces = {
1926
- exports: options.export || [],
1927
- uses: options.use || []
2084
+ exports: finalExports,
2085
+ uses: finalUses
1928
2086
  };
1929
2087
  const manifest = {
1930
2088
  version: "1.0",
1931
- package: pkg,
1932
- appVersion: version,
2089
+ package: finalPackage,
2090
+ appVersion: finalVersion,
1933
2091
  metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
1934
2092
  interfaces: interfaces.exports.length > 0 || interfaces.uses.length > 0 ? interfaces : void 0,
1935
2093
  wasm: {
1936
2094
  path: "app.wasm",
1937
- hash,
2095
+ hash: wasmHash,
1938
2096
  size: wasmSize
1939
2097
  },
1940
- abi: null,
2098
+ abi: abiArtifact || void 0,
1941
2099
  migrations: [],
1942
2100
  links: Object.keys(links).length > 0 ? links : void 0,
1943
2101
  signature: void 0
1944
2102
  };
1945
- let outputPath = options.output;
2103
+ let outputPath = finalOutput;
1946
2104
  if (!outputPath) {
1947
- const outputDir = path7.join(process.cwd(), pkg, version);
1948
- if (!fs3.existsSync(outputDir)) {
1949
- fs3.mkdirSync(outputDir, { recursive: true });
2105
+ const outputDir = path7.join(
2106
+ process.cwd(),
2107
+ finalPackage,
2108
+ finalVersion
2109
+ );
2110
+ if (!fs9.existsSync(outputDir)) {
2111
+ fs9.mkdirSync(outputDir, { recursive: true });
1950
2112
  }
1951
- outputPath = path7.join(outputDir, `${pkg}-${version}.mpk`);
2113
+ outputPath = path7.join(
2114
+ outputDir,
2115
+ `${finalPackage}-${finalVersion}.mpk`
2116
+ );
1952
2117
  } else {
1953
2118
  outputPath = path7.resolve(outputPath);
1954
2119
  const outputDir = path7.dirname(outputPath);
1955
- if (!fs3.existsSync(outputDir)) {
1956
- fs3.mkdirSync(outputDir, { recursive: true });
2120
+ if (!fs9.existsSync(outputDir)) {
2121
+ fs9.mkdirSync(outputDir, { recursive: true });
1957
2122
  }
1958
2123
  }
1959
2124
  const tempDir = path7.join(
1960
2125
  path7.dirname(outputPath),
1961
2126
  `.temp-bundle-${Date.now()}`
1962
2127
  );
1963
- fs3.mkdirSync(tempDir, { recursive: true });
2128
+ fs9.mkdirSync(tempDir, { recursive: true });
1964
2129
  try {
1965
- fs3.writeFileSync(
2130
+ fs9.writeFileSync(
1966
2131
  path7.join(tempDir, "manifest.json"),
1967
2132
  JSON.stringify(manifest, null, 2)
1968
2133
  );
1969
- fs3.writeFileSync(path7.join(tempDir, "app.wasm"), wasmContent);
2134
+ fs9.writeFileSync(path7.join(tempDir, "app.wasm"), wasmContent);
2135
+ const archiveFiles = ["manifest.json", "app.wasm"];
2136
+ if (abiContent) {
2137
+ fs9.writeFileSync(path7.join(tempDir, "abi.json"), abiContent);
2138
+ archiveFiles.push("abi.json");
2139
+ }
1970
2140
  await tar.create(
1971
2141
  {
1972
2142
  gzip: true,
1973
2143
  file: outputPath,
1974
2144
  cwd: tempDir
1975
2145
  },
1976
- ["manifest.json", "app.wasm"]
2146
+ archiveFiles
1977
2147
  );
1978
- const outputSize = fs3.statSync(outputPath).size;
2148
+ const outputSize = fs9.statSync(outputPath).size;
1979
2149
  console.log(`\u2705 Created MPK bundle: ${outputPath}`);
1980
- console.log(` Package: ${pkg}`);
1981
- console.log(` Version: ${version}`);
2150
+ console.log(` Package: ${finalPackage}`);
2151
+ console.log(` Version: ${finalVersion}`);
1982
2152
  console.log(` Size: ${outputSize} bytes`);
1983
- console.log(` WASM Hash: ${hash}`);
2153
+ console.log(` WASM Hash: ${wasmHash}`);
2154
+ if (abiArtifact) {
2155
+ console.log(` ABI Hash: ${abiArtifact.hash}`);
2156
+ }
1984
2157
  } finally {
1985
- if (fs3.existsSync(tempDir)) {
1986
- fs3.rmSync(tempDir, { recursive: true, force: true });
2158
+ if (fs9.existsSync(tempDir)) {
2159
+ fs9.rmSync(tempDir, { recursive: true, force: true });
1987
2160
  }
1988
2161
  }
1989
2162
  } catch (error) {
@@ -2049,7 +2222,7 @@ Note:
2049
2222
  process.exit(1);
2050
2223
  }
2051
2224
  const fullPath = path7.resolve(bundleFile);
2052
- if (!fs3.existsSync(fullPath)) {
2225
+ if (!fs9.existsSync(fullPath)) {
2053
2226
  console.error(`\u274C File not found: ${bundleFile}`);
2054
2227
  process.exit(1);
2055
2228
  }
@@ -2128,7 +2301,7 @@ function createGetCommand() {
2128
2301
  async function pushToRemote(bundlePath, manifest, registryUrl, apiKey) {
2129
2302
  try {
2130
2303
  console.log(`\u{1F4E4} Pushing to remote registry: ${registryUrl}`);
2131
- const bundleBuffer = fs3.readFileSync(bundlePath);
2304
+ const bundleBuffer = fs9.readFileSync(bundlePath);
2132
2305
  const bundleSize = bundleBuffer.length;
2133
2306
  console.log(` Bundle size: ${bundleSize} bytes`);
2134
2307
  const bundleHex = bundleBuffer.toString("hex");
@@ -2302,8 +2475,8 @@ async function extractManifest(bundlePath) {
2302
2475
  }
2303
2476
  });
2304
2477
  const extractDir = path7.join(path7.dirname(bundlePath), `.temp-${Date.now()}`);
2305
- if (!fs3.existsSync(extractDir)) {
2306
- fs3.mkdirSync(extractDir);
2478
+ if (!fs9.existsSync(extractDir)) {
2479
+ fs9.mkdirSync(extractDir);
2307
2480
  }
2308
2481
  try {
2309
2482
  await tar.x({
@@ -2312,14 +2485,14 @@ async function extractManifest(bundlePath) {
2312
2485
  filter: (path8) => path8 === "manifest.json"
2313
2486
  });
2314
2487
  const manifestPath = path7.join(extractDir, "manifest.json");
2315
- if (fs3.existsSync(manifestPath)) {
2316
- const content = fs3.readFileSync(manifestPath, "utf8");
2488
+ if (fs9.existsSync(manifestPath)) {
2489
+ const content = fs9.readFileSync(manifestPath, "utf8");
2317
2490
  manifestContent = content;
2318
2491
  }
2319
2492
  } catch {
2320
2493
  } finally {
2321
- if (fs3.existsSync(extractDir)) {
2322
- fs3.rmSync(extractDir, { recursive: true, force: true });
2494
+ if (fs9.existsSync(extractDir)) {
2495
+ fs9.rmSync(extractDir, { recursive: true, force: true });
2323
2496
  }
2324
2497
  }
2325
2498
  if (manifestContent) {
@@ -2416,7 +2589,7 @@ function createConfigListCommand() {
2416
2589
  const config = new RemoteConfig();
2417
2590
  console.log(chalk6.blue("\n\u{1F4CB} Remote Registry Configuration\n"));
2418
2591
  const configPath = config.getConfigPath();
2419
- const configFileExists = fs3.existsSync(configPath);
2592
+ const configFileExists = fs9.existsSync(configPath);
2420
2593
  const url = config.getRegistryUrl();
2421
2594
  let urlSource;
2422
2595
  if (process.env.CALIMERO_REGISTRY_URL) {