@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 +270 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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 (
|
|
433
|
+
if (fs9.existsSync(this.configPath)) {
|
|
434
434
|
try {
|
|
435
435
|
const existingConfig = JSON.parse(
|
|
436
|
-
|
|
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 (!
|
|
461
|
-
|
|
460
|
+
if (!fs9.existsSync(configDir)) {
|
|
461
|
+
fs9.mkdirSync(configDir, { recursive: true });
|
|
462
462
|
}
|
|
463
|
-
|
|
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 (!
|
|
522
|
-
|
|
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 (
|
|
578
|
-
const appsData = JSON.parse(
|
|
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 (
|
|
581
|
+
if (fs9.existsSync(this.bundleManifestsFile)) {
|
|
582
582
|
const bundleManifestsData = JSON.parse(
|
|
583
|
-
|
|
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 (
|
|
589
|
+
if (fs9.existsSync(this.artifactsFile)) {
|
|
590
590
|
const artifactsData = JSON.parse(
|
|
591
|
-
|
|
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
|
-
|
|
603
|
+
fs9.writeFileSync(this.appsFile, JSON.stringify(appsObj, null, 2));
|
|
604
604
|
const bundleManifestsObj = Object.fromEntries(this.data.bundleManifests);
|
|
605
|
-
|
|
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
|
-
|
|
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 (!
|
|
694
|
-
|
|
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
|
-
|
|
702
|
+
fs9.writeFileSync(backupPath, JSON.stringify(backupData, null, 2));
|
|
703
703
|
return backupPath;
|
|
704
704
|
}
|
|
705
705
|
async restore(backupPath) {
|
|
706
|
-
if (!
|
|
706
|
+
if (!fs9.existsSync(backupPath)) {
|
|
707
707
|
throw new Error(`Backup file not found: ${backupPath}`);
|
|
708
708
|
}
|
|
709
|
-
const backupData = JSON.parse(
|
|
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 (!
|
|
778
|
-
|
|
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 (!
|
|
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 (!
|
|
788
|
-
|
|
787
|
+
if (!fs9.existsSync(appVersionDir)) {
|
|
788
|
+
fs9.mkdirSync(appVersionDir, { recursive: true });
|
|
789
789
|
}
|
|
790
790
|
const targetPath = path7.join(appVersionDir, filename);
|
|
791
|
-
|
|
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 (!
|
|
799
|
+
if (!fs9.existsSync(artifactPath)) {
|
|
800
800
|
throw new Error(`Artifact not found: ${artifactPath}`);
|
|
801
801
|
}
|
|
802
|
-
return
|
|
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 || !
|
|
807
|
+
if (!artifactPath || !fs9.existsSync(artifactPath)) {
|
|
808
808
|
throw new Error(`Artifact not found for hash: ${hash}`);
|
|
809
809
|
}
|
|
810
|
-
return
|
|
810
|
+
return fs9.readFileSync(artifactPath);
|
|
811
811
|
}
|
|
812
812
|
// Validate artifact file
|
|
813
813
|
async validateArtifact(filePath) {
|
|
814
|
-
if (!
|
|
814
|
+
if (!fs9.existsSync(filePath)) {
|
|
815
815
|
throw new Error(`File not found: ${filePath}`);
|
|
816
816
|
}
|
|
817
|
-
const stats =
|
|
818
|
-
const fileBuffer =
|
|
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 =
|
|
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 =
|
|
867
|
+
const items = fs9.readdirSync(dir);
|
|
868
868
|
for (const item of items) {
|
|
869
869
|
const fullPath = path7.join(dir, item);
|
|
870
|
-
const stat =
|
|
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 =
|
|
881
|
+
const stats = fs9.statSync(file);
|
|
882
882
|
const age = now - stats.mtime.getTime();
|
|
883
883
|
if (age > maxAge) {
|
|
884
|
-
|
|
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 =
|
|
896
|
+
const items = fs9.readdirSync(dir);
|
|
897
897
|
for (const item of items) {
|
|
898
898
|
const fullPath = path7.join(dir, item);
|
|
899
|
-
const stat =
|
|
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 (
|
|
908
|
+
if (fs9.existsSync(this.artifactsDir)) {
|
|
909
909
|
const allFiles = getAllFiles(this.artifactsDir);
|
|
910
910
|
for (const file of allFiles) {
|
|
911
|
-
const stats =
|
|
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 (
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
1427
|
-
|
|
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 (!
|
|
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 (
|
|
1789
|
+
if (fs9.existsSync(this.configPath)) {
|
|
1790
1790
|
try {
|
|
1791
1791
|
const existingConfig = JSON.parse(
|
|
1792
|
-
|
|
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 (!
|
|
1809
|
-
|
|
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
|
-
|
|
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("
|
|
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 (!
|
|
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 =
|
|
2026
|
+
const wasmContent = fs9.readFileSync(wasmPath);
|
|
1914
2027
|
const wasmSize = wasmContent.length;
|
|
1915
|
-
const
|
|
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:
|
|
1918
|
-
description:
|
|
1919
|
-
author:
|
|
2075
|
+
name: finalName || finalPackage,
|
|
2076
|
+
description: finalDescription || "",
|
|
2077
|
+
author: finalAuthor
|
|
1920
2078
|
};
|
|
1921
2079
|
const links = {};
|
|
1922
|
-
if (
|
|
1923
|
-
if (
|
|
1924
|
-
if (
|
|
2080
|
+
if (finalFrontend) links.frontend = finalFrontend;
|
|
2081
|
+
if (finalGithub) links.github = finalGithub;
|
|
2082
|
+
if (finalDocs) links.docs = finalDocs;
|
|
1925
2083
|
const interfaces = {
|
|
1926
|
-
exports:
|
|
1927
|
-
uses:
|
|
2084
|
+
exports: finalExports,
|
|
2085
|
+
uses: finalUses
|
|
1928
2086
|
};
|
|
1929
2087
|
const manifest = {
|
|
1930
2088
|
version: "1.0",
|
|
1931
|
-
package:
|
|
1932
|
-
appVersion:
|
|
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:
|
|
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 =
|
|
2103
|
+
let outputPath = finalOutput;
|
|
1946
2104
|
if (!outputPath) {
|
|
1947
|
-
const outputDir = path7.join(
|
|
1948
|
-
|
|
1949
|
-
|
|
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(
|
|
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 (!
|
|
1956
|
-
|
|
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
|
-
|
|
2128
|
+
fs9.mkdirSync(tempDir, { recursive: true });
|
|
1964
2129
|
try {
|
|
1965
|
-
|
|
2130
|
+
fs9.writeFileSync(
|
|
1966
2131
|
path7.join(tempDir, "manifest.json"),
|
|
1967
2132
|
JSON.stringify(manifest, null, 2)
|
|
1968
2133
|
);
|
|
1969
|
-
|
|
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
|
-
|
|
2146
|
+
archiveFiles
|
|
1977
2147
|
);
|
|
1978
|
-
const outputSize =
|
|
2148
|
+
const outputSize = fs9.statSync(outputPath).size;
|
|
1979
2149
|
console.log(`\u2705 Created MPK bundle: ${outputPath}`);
|
|
1980
|
-
console.log(` Package: ${
|
|
1981
|
-
console.log(` Version: ${
|
|
2150
|
+
console.log(` Package: ${finalPackage}`);
|
|
2151
|
+
console.log(` Version: ${finalVersion}`);
|
|
1982
2152
|
console.log(` Size: ${outputSize} bytes`);
|
|
1983
|
-
console.log(` WASM Hash: ${
|
|
2153
|
+
console.log(` WASM Hash: ${wasmHash}`);
|
|
2154
|
+
if (abiArtifact) {
|
|
2155
|
+
console.log(` ABI Hash: ${abiArtifact.hash}`);
|
|
2156
|
+
}
|
|
1984
2157
|
} finally {
|
|
1985
|
-
if (
|
|
1986
|
-
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
2306
|
-
|
|
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 (
|
|
2316
|
-
const content =
|
|
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 (
|
|
2322
|
-
|
|
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 =
|
|
2592
|
+
const configFileExists = fs9.existsSync(configPath);
|
|
2420
2593
|
const url = config.getRegistryUrl();
|
|
2421
2594
|
let urlSource;
|
|
2422
2595
|
if (process.env.CALIMERO_REGISTRY_URL) {
|