@calimero-network/registry-cli 1.14.1 → 1.15.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 +294 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import axios from 'axios';
|
|
|
8
8
|
import fs9, { existsSync, writeFileSync } from 'fs';
|
|
9
9
|
import path7 from 'path';
|
|
10
10
|
import os from 'os';
|
|
11
|
-
import
|
|
11
|
+
import crypto2 from 'crypto';
|
|
12
12
|
import fastify from 'fastify';
|
|
13
13
|
import cors from '@fastify/cors';
|
|
14
14
|
import * as tar from 'tar';
|
|
@@ -817,7 +817,7 @@ var LocalArtifactServer = class {
|
|
|
817
817
|
}
|
|
818
818
|
const stats = fs9.statSync(filePath);
|
|
819
819
|
const fileBuffer = fs9.readFileSync(filePath);
|
|
820
|
-
const sha256 =
|
|
820
|
+
const sha256 = crypto2.createHash("sha256").update(fileBuffer).digest("hex");
|
|
821
821
|
return {
|
|
822
822
|
size: stats.size,
|
|
823
823
|
sha256
|
|
@@ -826,7 +826,7 @@ var LocalArtifactServer = class {
|
|
|
826
826
|
// Calculate file hash
|
|
827
827
|
async calculateFileHash(filePath) {
|
|
828
828
|
const fileBuffer = fs9.readFileSync(filePath);
|
|
829
|
-
return
|
|
829
|
+
return crypto2.createHash("sha256").update(fileBuffer).digest("hex");
|
|
830
830
|
}
|
|
831
831
|
// Get artifact URL for local serving
|
|
832
832
|
getArtifactUrl(appId, version2, filename) {
|
|
@@ -1888,6 +1888,111 @@ var RemoteConfig = class {
|
|
|
1888
1888
|
}
|
|
1889
1889
|
};
|
|
1890
1890
|
|
|
1891
|
+
// src/lib/services.ts
|
|
1892
|
+
var SERVICE_NAME_RE = /^[a-z0-9][a-z0-9_-]*$/;
|
|
1893
|
+
function validateServiceName(name) {
|
|
1894
|
+
if (typeof name !== "string" || !SERVICE_NAME_RE.test(name)) {
|
|
1895
|
+
throw new Error(
|
|
1896
|
+
`Invalid service name "${name}". Use lowercase letters, digits, "-" or "_" (must start alphanumeric).`
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1899
|
+
if (name.length > 64) {
|
|
1900
|
+
throw new Error(
|
|
1901
|
+
`Invalid service name "${name}": must be at most 64 characters.`
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
if (name === "app") {
|
|
1905
|
+
throw new Error(
|
|
1906
|
+
'Service name "app" is reserved for the main application. Choose another name.'
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function parseServiceSpec(spec) {
|
|
1911
|
+
const eq = spec.indexOf("=");
|
|
1912
|
+
if (eq === -1) {
|
|
1913
|
+
throw new Error(
|
|
1914
|
+
`Invalid --service "${spec}". Expected "name=path.wasm" or "name=path.wasm,abi=path.json".`
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
const name = spec.slice(0, eq).trim();
|
|
1918
|
+
let rest = spec.slice(eq + 1).trim();
|
|
1919
|
+
let abi;
|
|
1920
|
+
const abiMatch = rest.match(/,\s*abi\s*=\s*([^,]*)$/);
|
|
1921
|
+
if (abiMatch) {
|
|
1922
|
+
abi = abiMatch[1].trim();
|
|
1923
|
+
rest = rest.slice(0, abiMatch.index).trim();
|
|
1924
|
+
if (!abi) {
|
|
1925
|
+
throw new Error(`Invalid --service "${spec}": empty abi path.`);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
const wasm = rest;
|
|
1929
|
+
if (!wasm) {
|
|
1930
|
+
throw new Error(`Invalid --service "${spec}": missing WASM path.`);
|
|
1931
|
+
}
|
|
1932
|
+
if (wasm.includes(",")) {
|
|
1933
|
+
throw new Error(
|
|
1934
|
+
`Invalid --service "${spec}": unexpected comma in WASM path. Use "name=path.wasm,abi=path.json"; commas in paths are not supported.`
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
validateServiceName(name);
|
|
1938
|
+
return abi ? { name, wasm, abi } : { name, wasm };
|
|
1939
|
+
}
|
|
1940
|
+
function serviceWasmPath(name) {
|
|
1941
|
+
return `services/${name}.wasm`;
|
|
1942
|
+
}
|
|
1943
|
+
function serviceAbiPath(name) {
|
|
1944
|
+
return `services/${name}.abi.json`;
|
|
1945
|
+
}
|
|
1946
|
+
function isUnderServicesDir(p) {
|
|
1947
|
+
return typeof p === "string" && /^services[\\/]/.test(p);
|
|
1948
|
+
}
|
|
1949
|
+
function assertUniqueServiceNames(services) {
|
|
1950
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1951
|
+
for (const s of services) {
|
|
1952
|
+
if (seen.has(s.name)) {
|
|
1953
|
+
throw new Error(`Duplicate service name "${s.name}".`);
|
|
1954
|
+
}
|
|
1955
|
+
seen.add(s.name);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
function assertSafeBundlePath(p) {
|
|
1959
|
+
const segments = p.split(/[\\/]/);
|
|
1960
|
+
if (!p || p.startsWith("/") || /^[a-zA-Z]:/.test(p) || segments.includes("..") || segments.includes(".") || segments.includes("")) {
|
|
1961
|
+
throw new Error(
|
|
1962
|
+
`Unsafe bundle path "${p}": must be a non-empty relative path with no "." or ".." segments.`
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
function collectBundleFiles(manifest) {
|
|
1967
|
+
const files = ["manifest.json"];
|
|
1968
|
+
if (manifest.wasm?.path) files.push(manifest.wasm.path);
|
|
1969
|
+
if (manifest.abi?.path) files.push(manifest.abi.path);
|
|
1970
|
+
for (const svc of manifest.services ?? []) {
|
|
1971
|
+
const label = svc?.name ?? "<unnamed>";
|
|
1972
|
+
if (!svc.wasm?.path) {
|
|
1973
|
+
throw new Error(
|
|
1974
|
+
`Service "${label}" has no wasm.path; cannot pack the bundle.`
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
if (!isUnderServicesDir(svc.wasm.path)) {
|
|
1978
|
+
throw new Error(
|
|
1979
|
+
`Service "${label}" wasm.path "${svc.wasm.path}" must be under services/.`
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
files.push(svc.wasm.path);
|
|
1983
|
+
if (svc.abi?.path) {
|
|
1984
|
+
if (!isUnderServicesDir(svc.abi.path)) {
|
|
1985
|
+
throw new Error(
|
|
1986
|
+
`Service "${label}" abi.path "${svc.abi.path}" must be under services/.`
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
files.push(svc.abi.path);
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
files.forEach(assertSafeBundlePath);
|
|
1993
|
+
return [...new Set(files)];
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1891
1996
|
// src/commands/bundle.ts
|
|
1892
1997
|
var bundleCommand = new Command("bundle").description("Manage application bundles (V2)").addCommand(createCreateCommand()).addCommand(createPushCommand()).addCommand(createGetCommand()).addCommand(createEditCommand());
|
|
1893
1998
|
function createCreateCommand() {
|
|
@@ -1906,7 +2011,13 @@ function createCreateCommand() {
|
|
|
1906
2011
|
(value, prev) => {
|
|
1907
2012
|
return [...prev || [], value];
|
|
1908
2013
|
}
|
|
1909
|
-
).option("--abi <path>", "Path to ABI JSON file to include in bundle").
|
|
2014
|
+
).option("--abi <path>", "Path to ABI JSON file to include in bundle").option(
|
|
2015
|
+
"--service <spec>",
|
|
2016
|
+
'Add a service WASM alongside the main app: "name=path.wasm" or "name=path.wasm,abi=path.json" (repeatable)',
|
|
2017
|
+
(value, prev) => {
|
|
2018
|
+
return [...prev || [], parseServiceSpec(value)];
|
|
2019
|
+
}
|
|
2020
|
+
).addHelpText(
|
|
1910
2021
|
"after",
|
|
1911
2022
|
`
|
|
1912
2023
|
Examples:
|
|
@@ -1916,6 +2027,7 @@ Examples:
|
|
|
1916
2027
|
$ calimero-registry bundle create app.wasm com.calimero.myapp 1.0.0 --name "My App" --frontend https://app.example.com
|
|
1917
2028
|
$ calimero-registry bundle create app.wasm com.calimero.myapp 1.0.0 --abi abi.json
|
|
1918
2029
|
$ calimero-registry bundle create app.wasm --manifest manifest.json --abi res/abi.json
|
|
2030
|
+
$ calimero-registry bundle create tictactoe.wasm com.calimero.ttt 1.0.0 --service lobby=lobby.wasm,abi=lobby-abi.json
|
|
1919
2031
|
|
|
1920
2032
|
Manifest File Format (JSON):
|
|
1921
2033
|
{
|
|
@@ -1930,7 +2042,10 @@ Manifest File Format (JSON):
|
|
|
1930
2042
|
"docs": "https://docs.example.com",
|
|
1931
2043
|
"exports": ["interface1", "interface2"],
|
|
1932
2044
|
"uses": ["interface3"],
|
|
1933
|
-
"abi": "res/abi.json"
|
|
2045
|
+
"abi": "res/abi.json",
|
|
2046
|
+
"services": [
|
|
2047
|
+
{ "name": "lobby", "wasm": "res/lobby.wasm", "abi": "res/lobby-abi.json" }
|
|
2048
|
+
]
|
|
1934
2049
|
}
|
|
1935
2050
|
|
|
1936
2051
|
Note:
|
|
@@ -1940,6 +2055,8 @@ Note:
|
|
|
1940
2055
|
- The -o/--output option overrides manifest.output if both are provided
|
|
1941
2056
|
- ABI can be provided via --abi flag or manifest.abi field (file path string)
|
|
1942
2057
|
- ABI file will be included in the bundle and referenced in the manifest
|
|
2058
|
+
- The main app is always packed as app.wasm; services are packed under services/<name>.wasm
|
|
2059
|
+
- Services merge from --service flags and manifest.services; names must be unique
|
|
1943
2060
|
`
|
|
1944
2061
|
).action(async (wasmFile, pkg, version2, options) => {
|
|
1945
2062
|
try {
|
|
@@ -1988,6 +2105,10 @@ Note:
|
|
|
1988
2105
|
console.error('\u274C Invalid manifest: "uses" must be an array');
|
|
1989
2106
|
process.exit(1);
|
|
1990
2107
|
}
|
|
2108
|
+
if (manifestConfig.services !== void 0 && !Array.isArray(manifestConfig.services)) {
|
|
2109
|
+
console.error('\u274C Invalid manifest: "services" must be an array');
|
|
2110
|
+
process.exit(1);
|
|
2111
|
+
}
|
|
1991
2112
|
const finalExports = options.export && options.export.length > 0 ? options.export : manifestExports || [];
|
|
1992
2113
|
const finalUses = options.use && options.use.length > 0 ? options.use : manifestUses || [];
|
|
1993
2114
|
if (!wasmFile) {
|
|
@@ -2026,7 +2147,7 @@ Note:
|
|
|
2026
2147
|
console.log(`\u{1F4E6} Creating MPK bundle from: ${path7.basename(wasmPath)}`);
|
|
2027
2148
|
const wasmContent = fs9.readFileSync(wasmPath);
|
|
2028
2149
|
const wasmSize = wasmContent.length;
|
|
2029
|
-
const wasmHash =
|
|
2150
|
+
const wasmHash = crypto2.createHash("sha256").update(wasmContent).digest("hex");
|
|
2030
2151
|
let abiArtifact = void 0;
|
|
2031
2152
|
let abiContent = null;
|
|
2032
2153
|
const abiPathFromOption = options.abi;
|
|
@@ -2045,7 +2166,7 @@ Note:
|
|
|
2045
2166
|
try {
|
|
2046
2167
|
abiContent = fs9.readFileSync(abiResolvedPath);
|
|
2047
2168
|
JSON.parse(abiContent.toString("utf8"));
|
|
2048
|
-
const abiHash =
|
|
2169
|
+
const abiHash = crypto2.createHash("sha256").update(abiContent).digest("hex");
|
|
2049
2170
|
abiArtifact = {
|
|
2050
2171
|
path: "abi.json",
|
|
2051
2172
|
hash: abiHash,
|
|
@@ -2072,6 +2193,105 @@ Note:
|
|
|
2072
2193
|
);
|
|
2073
2194
|
process.exit(1);
|
|
2074
2195
|
}
|
|
2196
|
+
const cliServices = options.service || [];
|
|
2197
|
+
const manifestServices = Array.isArray(
|
|
2198
|
+
manifestConfig.services
|
|
2199
|
+
) ? manifestConfig.services : [];
|
|
2200
|
+
const manifestDir = options.manifest ? path7.dirname(path7.resolve(options.manifest)) : process.cwd();
|
|
2201
|
+
const allServiceSources = [
|
|
2202
|
+
...cliServices.map((src) => ({ src, baseDir: process.cwd() })),
|
|
2203
|
+
...manifestServices.map((src) => ({ src, baseDir: manifestDir }))
|
|
2204
|
+
];
|
|
2205
|
+
const serviceArtifacts = [];
|
|
2206
|
+
const serviceFilesToWrite = [];
|
|
2207
|
+
for (const { src } of allServiceSources) {
|
|
2208
|
+
try {
|
|
2209
|
+
validateServiceName(src.name);
|
|
2210
|
+
} catch (e) {
|
|
2211
|
+
console.error(`\u274C ${e instanceof Error ? e.message : String(e)}`);
|
|
2212
|
+
process.exit(1);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
try {
|
|
2216
|
+
assertUniqueServiceNames(allServiceSources.map((s) => s.src));
|
|
2217
|
+
} catch (e) {
|
|
2218
|
+
console.error(`\u274C ${e instanceof Error ? e.message : String(e)}`);
|
|
2219
|
+
process.exit(1);
|
|
2220
|
+
}
|
|
2221
|
+
for (const { src, baseDir } of allServiceSources) {
|
|
2222
|
+
if (typeof src.wasm !== "string" || src.wasm.length === 0) {
|
|
2223
|
+
console.error(
|
|
2224
|
+
`\u274C Service "${src.name}" wasm must be a file path string.`
|
|
2225
|
+
);
|
|
2226
|
+
process.exit(1);
|
|
2227
|
+
}
|
|
2228
|
+
if (src.abi !== void 0 && (typeof src.abi !== "string" || src.abi.length === 0)) {
|
|
2229
|
+
console.error(
|
|
2230
|
+
`\u274C Service "${src.name}" abi must be a file path string.`
|
|
2231
|
+
);
|
|
2232
|
+
process.exit(1);
|
|
2233
|
+
}
|
|
2234
|
+
const svcWasmPath = path7.resolve(baseDir, src.wasm);
|
|
2235
|
+
if (!fs9.existsSync(svcWasmPath)) {
|
|
2236
|
+
console.error(
|
|
2237
|
+
`\u274C Service "${src.name}" WASM not found: ${src.wasm}`
|
|
2238
|
+
);
|
|
2239
|
+
console.error(` Resolved path: ${svcWasmPath}`);
|
|
2240
|
+
process.exit(1);
|
|
2241
|
+
}
|
|
2242
|
+
const svcWasmContent = fs9.readFileSync(svcWasmPath);
|
|
2243
|
+
const svcWasmHash = crypto2.createHash("sha256").update(svcWasmContent).digest("hex");
|
|
2244
|
+
const wasmArchivePath = serviceWasmPath(src.name);
|
|
2245
|
+
const entry = {
|
|
2246
|
+
name: src.name,
|
|
2247
|
+
wasm: {
|
|
2248
|
+
path: wasmArchivePath,
|
|
2249
|
+
hash: svcWasmHash,
|
|
2250
|
+
size: svcWasmContent.length
|
|
2251
|
+
}
|
|
2252
|
+
};
|
|
2253
|
+
serviceFilesToWrite.push({
|
|
2254
|
+
relPath: wasmArchivePath,
|
|
2255
|
+
content: svcWasmContent
|
|
2256
|
+
});
|
|
2257
|
+
if (src.abi) {
|
|
2258
|
+
const svcAbiPath = path7.resolve(baseDir, src.abi);
|
|
2259
|
+
if (!fs9.existsSync(svcAbiPath)) {
|
|
2260
|
+
console.error(
|
|
2261
|
+
`\u274C Service "${src.name}" ABI not found: ${src.abi}`
|
|
2262
|
+
);
|
|
2263
|
+
console.error(` Resolved path: ${svcAbiPath}`);
|
|
2264
|
+
process.exit(1);
|
|
2265
|
+
}
|
|
2266
|
+
const svcAbiContent = fs9.readFileSync(svcAbiPath);
|
|
2267
|
+
try {
|
|
2268
|
+
JSON.parse(svcAbiContent.toString("utf8"));
|
|
2269
|
+
} catch (error) {
|
|
2270
|
+
console.error(
|
|
2271
|
+
`\u274C Service "${src.name}" ABI is not valid JSON: ${src.abi}`
|
|
2272
|
+
);
|
|
2273
|
+
console.error(
|
|
2274
|
+
error instanceof Error ? error.message : "Invalid JSON"
|
|
2275
|
+
);
|
|
2276
|
+
process.exit(1);
|
|
2277
|
+
}
|
|
2278
|
+
const svcAbiHash = crypto2.createHash("sha256").update(svcAbiContent).digest("hex");
|
|
2279
|
+
const abiArchivePath = serviceAbiPath(src.name);
|
|
2280
|
+
entry.abi = {
|
|
2281
|
+
path: abiArchivePath,
|
|
2282
|
+
hash: svcAbiHash,
|
|
2283
|
+
size: svcAbiContent.length
|
|
2284
|
+
};
|
|
2285
|
+
serviceFilesToWrite.push({
|
|
2286
|
+
relPath: abiArchivePath,
|
|
2287
|
+
content: svcAbiContent
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
serviceArtifacts.push(entry);
|
|
2291
|
+
console.log(
|
|
2292
|
+
` Including service: ${src.name} (${path7.basename(svcWasmPath)})`
|
|
2293
|
+
);
|
|
2294
|
+
}
|
|
2075
2295
|
const metadata = {
|
|
2076
2296
|
name: finalName || finalPackage,
|
|
2077
2297
|
description: finalDescription || "",
|
|
@@ -2097,6 +2317,7 @@ Note:
|
|
|
2097
2317
|
size: wasmSize
|
|
2098
2318
|
},
|
|
2099
2319
|
abi: abiArtifact || void 0,
|
|
2320
|
+
services: serviceArtifacts.length > 0 ? serviceArtifacts : void 0,
|
|
2100
2321
|
migrations: [],
|
|
2101
2322
|
links: Object.keys(links).length > 0 ? links : void 0,
|
|
2102
2323
|
signature: void 0
|
|
@@ -2113,6 +2334,19 @@ Note:
|
|
|
2113
2334
|
if (abiContent) {
|
|
2114
2335
|
fs9.writeFileSync(path7.join(outputDir, "abi.json"), abiContent);
|
|
2115
2336
|
}
|
|
2337
|
+
const servicesDir = path7.join(outputDir, "services");
|
|
2338
|
+
for (const { relPath, content } of serviceFilesToWrite) {
|
|
2339
|
+
const dest = path7.join(outputDir, relPath);
|
|
2340
|
+
const rel = path7.relative(servicesDir, dest);
|
|
2341
|
+
if (rel.startsWith("..") || path7.isAbsolute(rel)) {
|
|
2342
|
+
console.error(
|
|
2343
|
+
`\u274C Refusing to write service file outside services/: ${relPath}`
|
|
2344
|
+
);
|
|
2345
|
+
process.exit(1);
|
|
2346
|
+
}
|
|
2347
|
+
fs9.mkdirSync(path7.dirname(dest), { recursive: true });
|
|
2348
|
+
fs9.writeFileSync(dest, content);
|
|
2349
|
+
}
|
|
2116
2350
|
console.log(`\u2705 Bundle files written to: ${outputDir}`);
|
|
2117
2351
|
console.log(` Package: ${finalPackage}`);
|
|
2118
2352
|
console.log(` Version: ${finalVersion}`);
|
|
@@ -2120,6 +2354,11 @@ Note:
|
|
|
2120
2354
|
if (abiArtifact) {
|
|
2121
2355
|
console.log(` ABI Hash: ${abiArtifact.hash}`);
|
|
2122
2356
|
}
|
|
2357
|
+
if (serviceArtifacts.length > 0) {
|
|
2358
|
+
console.log(
|
|
2359
|
+
` Services: ${serviceArtifacts.map((s) => s.name).join(", ")}`
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2123
2362
|
console.log("");
|
|
2124
2363
|
console.log("Next steps:");
|
|
2125
2364
|
console.log(
|
|
@@ -2212,16 +2451,57 @@ Note:
|
|
|
2212
2451
|
process.exit(1);
|
|
2213
2452
|
}
|
|
2214
2453
|
tempMpk = path7.join(fullPath, `.temp-push-${Date.now()}.mpk`);
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2454
|
+
let dirManifest;
|
|
2455
|
+
try {
|
|
2456
|
+
dirManifest = JSON.parse(
|
|
2457
|
+
fs9.readFileSync(manifestInDir, "utf8")
|
|
2458
|
+
);
|
|
2459
|
+
} catch (e) {
|
|
2460
|
+
console.error(
|
|
2461
|
+
`\u274C Failed to parse manifest.json in ${fullPath}: ${e instanceof Error ? e.message : String(e)}`
|
|
2462
|
+
);
|
|
2463
|
+
console.error(
|
|
2464
|
+
" Fix the manifest JSON and retry (service files would otherwise be silently omitted)."
|
|
2465
|
+
);
|
|
2466
|
+
process.exit(1);
|
|
2467
|
+
}
|
|
2468
|
+
if (!dirManifest.wasm?.path) {
|
|
2469
|
+
console.error(
|
|
2470
|
+
"\u274C manifest.json has no main wasm (wasm.path). A bundle must include its main application."
|
|
2471
|
+
);
|
|
2472
|
+
process.exit(1);
|
|
2473
|
+
}
|
|
2474
|
+
for (const svc of dirManifest.services ?? []) {
|
|
2475
|
+
if (!svc?.wasm?.path) {
|
|
2476
|
+
console.error(
|
|
2477
|
+
`\u274C Service "${svc?.name ?? "<unnamed>"}" in manifest.json has no wasm.path.`
|
|
2478
|
+
);
|
|
2479
|
+
process.exit(1);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
let archiveFiles;
|
|
2483
|
+
try {
|
|
2484
|
+
archiveFiles = collectBundleFiles(dirManifest);
|
|
2485
|
+
} catch (e) {
|
|
2486
|
+
console.error(`\u274C ${e instanceof Error ? e.message : String(e)}`);
|
|
2487
|
+
process.exit(1);
|
|
2488
|
+
}
|
|
2489
|
+
for (const f of archiveFiles) {
|
|
2490
|
+
if (!fs9.existsSync(path7.join(fullPath, f))) {
|
|
2491
|
+
console.error(
|
|
2492
|
+
`\u274C Bundle file referenced by manifest not found: ${f}`
|
|
2493
|
+
);
|
|
2494
|
+
process.exit(1);
|
|
2495
|
+
}
|
|
2218
2496
|
}
|
|
2219
2497
|
await tar.create(
|
|
2220
2498
|
{ gzip: true, file: tempMpk, cwd: fullPath },
|
|
2221
2499
|
archiveFiles
|
|
2222
2500
|
);
|
|
2223
2501
|
mpkPath = tempMpk;
|
|
2224
|
-
console.log(
|
|
2502
|
+
console.log(
|
|
2503
|
+
`\u{1F4E6} Packed directory into temporary bundle (${archiveFiles.length} files)`
|
|
2504
|
+
);
|
|
2225
2505
|
}
|
|
2226
2506
|
console.log(`\u{1F4E6} Processing bundle: ${path7.basename(mpkPath)}`);
|
|
2227
2507
|
const manifest = await extractManifest(mpkPath);
|
|
@@ -2476,6 +2756,9 @@ async function pushToRemote(bundlePath, manifest, registryUrl, apiKey) {
|
|
|
2476
2756
|
if (manifest.abi !== void 0) {
|
|
2477
2757
|
payload.abi = manifest.abi;
|
|
2478
2758
|
}
|
|
2759
|
+
if (manifest.services !== void 0) {
|
|
2760
|
+
payload.services = manifest.services;
|
|
2761
|
+
}
|
|
2479
2762
|
payload.migrations = manifest.migrations ?? [];
|
|
2480
2763
|
if (manifest.links) {
|
|
2481
2764
|
payload.links = manifest.links;
|