@caatinga/core 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/browser-CuET2GqM.d.cts +174 -0
- package/dist/browser-CuET2GqM.d.ts +174 -0
- package/dist/browser-DUcSR5D3.d.cts +173 -0
- package/dist/browser-DUcSR5D3.d.ts +173 -0
- package/dist/browser.cjs +107 -0
- package/dist/browser.d.cts +2 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +10 -0
- package/dist/chunk-EKHNKCJV.js +79 -0
- package/dist/chunk-GMABXVEY.js +78 -0
- package/dist/index.cjs +400 -153
- package/dist/index.d.cts +50 -177
- package/dist/index.d.ts +50 -177
- package/dist/index.js +401 -223
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -1,72 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
UNEXPECTED_ERROR: "CAATINGA_UNEXPECTED_ERROR",
|
|
7
|
-
STELLAR_CLI_NOT_FOUND: "CAATINGA_STELLAR_CLI_NOT_FOUND",
|
|
8
|
-
STELLAR_CLI_VERSION_PARSE_FAILED: "CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
|
|
9
|
-
UNSUPPORTED_CLI_VERSION: "CAATINGA_UNSUPPORTED_CLI_VERSION",
|
|
10
|
-
UNTESTED_CLI_VERSION: "CAATINGA_UNTESTED_CLI_VERSION",
|
|
11
|
-
RUST_NOT_FOUND: "CAATINGA_RUST_NOT_FOUND",
|
|
12
|
-
RUST_TARGET_NOT_FOUND: "CAATINGA_RUST_TARGET_NOT_FOUND",
|
|
13
|
-
DEPLOY_FAILED: "CAATINGA_DEPLOY_FAILED",
|
|
14
|
-
BUILD_FAILED: "CAATINGA_BUILD_FAILED",
|
|
15
|
-
BINDINGS_FAILED: "CAATINGA_BINDINGS_FAILED",
|
|
16
|
-
INVOKE_FAILED: "CAATINGA_INVOKE_FAILED",
|
|
17
|
-
CONTRACT_NOT_FOUND: "CAATINGA_CONTRACT_NOT_FOUND",
|
|
18
|
-
NETWORK_NOT_FOUND: "CAATINGA_NETWORK_NOT_FOUND",
|
|
19
|
-
ARTIFACT_NOT_FOUND: "CAATINGA_ARTIFACT_NOT_FOUND",
|
|
20
|
-
ARTIFACT_INVALID: "CAATINGA_ARTIFACT_INVALID",
|
|
21
|
-
CONTRACT_ID_NOT_FOUND: "CAATINGA_CONTRACT_ID_NOT_FOUND",
|
|
22
|
-
CONTRACT_ARTIFACT_NOT_FOUND: "CAATINGA_CONTRACT_ARTIFACT_NOT_FOUND",
|
|
23
|
-
CONTRACT_DEPENDENCY_NOT_FOUND: "CAATINGA_CONTRACT_DEPENDENCY_NOT_FOUND",
|
|
24
|
-
CONTRACT_DEPENDENCY_CYCLE: "CAATINGA_CONTRACT_DEPENDENCY_CYCLE",
|
|
25
|
-
CONTRACT_DEPENDENCY_ARTIFACT_NOT_FOUND: "CAATINGA_CONTRACT_DEPENDENCY_ARTIFACT_NOT_FOUND",
|
|
26
|
-
DEPLOY_ARG_PLACEHOLDER_INVALID: "CAATINGA_DEPLOY_ARG_PLACEHOLDER_INVALID",
|
|
27
|
-
DEPLOY_ARG_PLACEHOLDER_UNRESOLVED: "CAATINGA_DEPLOY_ARG_PLACEHOLDER_UNRESOLVED",
|
|
28
|
-
BINDING_CLIENT_NOT_FOUND: "CAATINGA_BINDING_CLIENT_NOT_FOUND",
|
|
29
|
-
BINDING_METHOD_NOT_FOUND: "CAATINGA_BINDING_METHOD_NOT_FOUND",
|
|
30
|
-
XDR_BUILD_FAILED: "CAATINGA_XDR_BUILD_FAILED",
|
|
31
|
-
XDR_PREPARE_FAILED: "CAATINGA_XDR_PREPARE_FAILED",
|
|
32
|
-
XDR_SIGN_FAILED: "CAATINGA_XDR_SIGN_FAILED",
|
|
33
|
-
XDR_SUBMIT_FAILED: "CAATINGA_XDR_SUBMIT_FAILED",
|
|
34
|
-
XDR_RESULT_FAILED: "CAATINGA_XDR_RESULT_FAILED",
|
|
35
|
-
WALLET_NOT_CONNECTED: "CAATINGA_WALLET_NOT_CONNECTED",
|
|
36
|
-
SOURCE_ACCOUNT_REQUIRED: "CAATINGA_SOURCE_ACCOUNT_REQUIRED",
|
|
37
|
-
UNSAFE_SOURCE_ACCOUNT: "CAATINGA_UNSAFE_SOURCE_ACCOUNT",
|
|
38
|
-
INVOKE_TARGET_INVALID: "CAATINGA_INVOKE_TARGET_INVALID",
|
|
39
|
-
TEMPLATE_NOT_FOUND: "CAATINGA_TEMPLATE_NOT_FOUND",
|
|
40
|
-
INVALID_TEMPLATE_MANIFEST: "CAATINGA_INVALID_TEMPLATE_MANIFEST",
|
|
41
|
-
TEMPLATE_MANIFEST_NOT_FOUND: "CAATINGA_TEMPLATE_MANIFEST_NOT_FOUND",
|
|
42
|
-
TEMPLATE_INCOMPATIBLE: "CAATINGA_TEMPLATE_INCOMPATIBLE"
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// src/errors/CaatingaError.ts
|
|
46
|
-
var CaatingaError = class extends Error {
|
|
47
|
-
constructor(message, code, hint, cause) {
|
|
48
|
-
super(message);
|
|
49
|
-
this.code = code;
|
|
50
|
-
this.hint = hint;
|
|
51
|
-
this.cause = cause;
|
|
52
|
-
this.name = "CaatingaError";
|
|
53
|
-
}
|
|
54
|
-
code;
|
|
55
|
-
hint;
|
|
56
|
-
cause;
|
|
57
|
-
};
|
|
58
|
-
function toCaatingaError(error) {
|
|
59
|
-
if (error instanceof CaatingaError) {
|
|
60
|
-
return error;
|
|
61
|
-
}
|
|
62
|
-
if (error instanceof Error) {
|
|
63
|
-
return new CaatingaError(error.message, CaatingaErrorCode.UNEXPECTED_ERROR, void 0, error);
|
|
64
|
-
}
|
|
65
|
-
return new CaatingaError("An unexpected error occurred.", CaatingaErrorCode.UNEXPECTED_ERROR);
|
|
66
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
CaatingaError,
|
|
3
|
+
CaatingaErrorCode,
|
|
4
|
+
toCaatingaError
|
|
5
|
+
} from "./chunk-EKHNKCJV.js";
|
|
67
6
|
|
|
68
7
|
// src/version.ts
|
|
69
|
-
var CAATINGA_CORE_VERSION = "0.2.
|
|
8
|
+
var CAATINGA_CORE_VERSION = "0.2.3";
|
|
70
9
|
|
|
71
10
|
// src/config/config.schema.ts
|
|
72
11
|
import { z } from "zod";
|
|
@@ -253,7 +192,7 @@ import { execa } from "execa";
|
|
|
253
192
|
|
|
254
193
|
// src/stellar-cli/version.ts
|
|
255
194
|
import semver from "semver";
|
|
256
|
-
var STELLAR_CLI_MIN_VERSION = "
|
|
195
|
+
var STELLAR_CLI_MIN_VERSION = "23.0.0";
|
|
257
196
|
var STELLAR_CLI_TESTED_MAX_VERSION = "25.2.0";
|
|
258
197
|
var STELLAR_CLI_SEMVER_REGEX = /\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?)\b/;
|
|
259
198
|
function parseStellarCliVersion(output) {
|
|
@@ -386,6 +325,146 @@ function parseContractId(output) {
|
|
|
386
325
|
return match[0];
|
|
387
326
|
}
|
|
388
327
|
|
|
328
|
+
// src/stellar-cli/build-stellar-network-args.ts
|
|
329
|
+
function matchesWellKnownNetwork(name, config) {
|
|
330
|
+
const known = WELL_KNOWN_NETWORKS[name];
|
|
331
|
+
if (!known) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
return known.rpcUrl === config.rpcUrl && known.networkPassphrase === config.networkPassphrase;
|
|
335
|
+
}
|
|
336
|
+
function buildRpcNetworkArgs(config) {
|
|
337
|
+
return [
|
|
338
|
+
"--rpc-url",
|
|
339
|
+
config.rpcUrl,
|
|
340
|
+
"--network-passphrase",
|
|
341
|
+
config.networkPassphrase
|
|
342
|
+
];
|
|
343
|
+
}
|
|
344
|
+
function buildStellarNetworkArgsFromConfig(config) {
|
|
345
|
+
for (const [name, known] of Object.entries(WELL_KNOWN_NETWORKS)) {
|
|
346
|
+
if (known.rpcUrl === config.rpcUrl && known.networkPassphrase === config.networkPassphrase) {
|
|
347
|
+
return ["--network", name];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return buildRpcNetworkArgs(config);
|
|
351
|
+
}
|
|
352
|
+
function buildStellarNetworkArgs(network) {
|
|
353
|
+
if (matchesWellKnownNetwork(network.name, network.config)) {
|
|
354
|
+
return ["--network", network.name];
|
|
355
|
+
}
|
|
356
|
+
return buildStellarNetworkArgsFromConfig(network.config);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/stellar-cli/recover-deploy-contract-id.ts
|
|
360
|
+
var TX_HASH_REGEX = /Transaction hash is ([a-f0-9]{64})/i;
|
|
361
|
+
var DEPLOY_SIGNING_FAILURE_REGEX = /xdr processing error: xdr value invalid/i;
|
|
362
|
+
var HORIZON_URL_BY_PASSPHRASE = {
|
|
363
|
+
"Test SDF Network ; September 2015": "https://horizon-testnet.stellar.org",
|
|
364
|
+
"Public Global Stellar Network ; September 2015": "https://horizon.stellar.org"
|
|
365
|
+
};
|
|
366
|
+
function isLikelyPublicKeySource(source) {
|
|
367
|
+
return /^G[A-Z2-7]{55}$/.test(source);
|
|
368
|
+
}
|
|
369
|
+
function decimalSaltToHex(salt) {
|
|
370
|
+
return BigInt(salt).toString(16).padStart(64, "0");
|
|
371
|
+
}
|
|
372
|
+
function resolveHorizonUrl(network) {
|
|
373
|
+
const horizonUrl = HORIZON_URL_BY_PASSPHRASE[network.networkPassphrase];
|
|
374
|
+
if (!horizonUrl) {
|
|
375
|
+
throw new CaatingaError(
|
|
376
|
+
`No Horizon URL mapping for network passphrase "${network.networkPassphrase}".`,
|
|
377
|
+
CaatingaErrorCode.NETWORK_NOT_FOUND,
|
|
378
|
+
"Use testnet or mainnet, or extend Caatinga network metadata."
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
return horizonUrl;
|
|
382
|
+
}
|
|
383
|
+
async function fetchCreateContractSalt(horizonUrl, transactionHash, fetchImpl = fetch) {
|
|
384
|
+
const response = await fetchImpl(`${horizonUrl}/transactions/${transactionHash}/operations`);
|
|
385
|
+
if (!response.ok) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const body = await response.json();
|
|
389
|
+
const operation = body._embedded?.records?.find(
|
|
390
|
+
(record) => record.transaction_successful === true && record.type === "invoke_host_function" && record.function === "HostFunctionTypeHostFunctionTypeCreateContract" && typeof record.salt === "string"
|
|
391
|
+
);
|
|
392
|
+
return operation?.salt ?? null;
|
|
393
|
+
}
|
|
394
|
+
async function resolveContractIdFromDeploySalt(options) {
|
|
395
|
+
const saltHex = decimalSaltToHex(options.salt);
|
|
396
|
+
const result = await runCommand("stellar", [
|
|
397
|
+
"contract",
|
|
398
|
+
"id",
|
|
399
|
+
"wasm",
|
|
400
|
+
"--salt",
|
|
401
|
+
saltHex,
|
|
402
|
+
"--source-account",
|
|
403
|
+
options.source,
|
|
404
|
+
...buildStellarNetworkArgsFromConfig(options.network)
|
|
405
|
+
], {
|
|
406
|
+
cwd: options.cwd,
|
|
407
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
408
|
+
skipStellarVersionCheck: true
|
|
409
|
+
});
|
|
410
|
+
return parseContractId(result.all || `${result.stdout}
|
|
411
|
+
${result.stderr}`);
|
|
412
|
+
}
|
|
413
|
+
async function tryRecoverContractIdFromDeployFailure(options) {
|
|
414
|
+
if (!DEPLOY_SIGNING_FAILURE_REGEX.test(options.output)) {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
const hashMatch = options.output.match(TX_HASH_REGEX);
|
|
418
|
+
if (!hashMatch) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
const horizonUrl = resolveHorizonUrl(options.network);
|
|
422
|
+
const salt = await fetchCreateContractSalt(horizonUrl, hashMatch[1], options.fetchImpl);
|
|
423
|
+
if (!salt) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
return resolveContractIdFromDeploySalt({
|
|
427
|
+
salt,
|
|
428
|
+
source: options.source,
|
|
429
|
+
network: options.network,
|
|
430
|
+
cwd: options.cwd,
|
|
431
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/contracts/validate-source-shape.ts
|
|
436
|
+
function validateSourceShape(source) {
|
|
437
|
+
if (source.startsWith("S")) {
|
|
438
|
+
return new CaatingaError(
|
|
439
|
+
"Refusing to accept a Stellar secret key as --source.",
|
|
440
|
+
CaatingaErrorCode.SOURCE_IS_SECRET_KEY,
|
|
441
|
+
"Use a Stellar CLI identity alias instead, for example: --source alice"
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
if (source.trim().includes(" ")) {
|
|
445
|
+
return new CaatingaError(
|
|
446
|
+
"Refusing to accept a seed phrase as --source.",
|
|
447
|
+
CaatingaErrorCode.SOURCE_IS_SEED_PHRASE,
|
|
448
|
+
"Use a Stellar CLI identity alias instead, for example: --source alice"
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
if (isLikelyPublicKeySource(source)) {
|
|
452
|
+
return new CaatingaError(
|
|
453
|
+
`Public account address cannot sign transactions: ${source}`,
|
|
454
|
+
CaatingaErrorCode.SOURCE_IS_PUBLIC_KEY,
|
|
455
|
+
"Use a Stellar CLI identity with a secret key. Example: stellar keys generate alice --fund --network testnet, then --source alice"
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if (source.startsWith("G")) {
|
|
459
|
+
return new CaatingaError(
|
|
460
|
+
"Refusing to accept a public account address as --source.",
|
|
461
|
+
CaatingaErrorCode.UNSAFE_SOURCE_ACCOUNT,
|
|
462
|
+
"Use a Stellar CLI identity alias, not a public address. Example: --source alice"
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
return void 0;
|
|
466
|
+
}
|
|
467
|
+
|
|
389
468
|
// src/contracts/resolve-contract.ts
|
|
390
469
|
import path4 from "path";
|
|
391
470
|
function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
@@ -407,25 +486,99 @@ function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
|
407
486
|
|
|
408
487
|
// src/contracts/wasm.ts
|
|
409
488
|
import { createHash } from "crypto";
|
|
410
|
-
import { access as access2, readFile as readFile2 } from "fs/promises";
|
|
411
|
-
|
|
489
|
+
import { access as access2, readdir, readFile as readFile2, stat } from "fs/promises";
|
|
490
|
+
import path5 from "path";
|
|
491
|
+
var LEGACY_RUST_WASM_TARGET = "wasm32-unknown-unknown";
|
|
492
|
+
var CURRENT_RUST_WASM_TARGET = "wasm32v1-none";
|
|
493
|
+
function toCurrentWasmTargetPath(wasmPath) {
|
|
494
|
+
if (!wasmPath.includes(LEGACY_RUST_WASM_TARGET)) {
|
|
495
|
+
return wasmPath;
|
|
496
|
+
}
|
|
497
|
+
return wasmPath.replaceAll(LEGACY_RUST_WASM_TARGET, CURRENT_RUST_WASM_TARGET);
|
|
498
|
+
}
|
|
499
|
+
function wasmNotFoundError(configuredWasmPath, options) {
|
|
500
|
+
const migratedPath = options?.migratedPath;
|
|
501
|
+
const hint = migratedPath === void 0 ? "Run caatinga build before deploy or generate." : [
|
|
502
|
+
"Run caatinga build before deploy or generate.",
|
|
503
|
+
`Soroban builds use the "${CURRENT_RUST_WASM_TARGET}" target.`,
|
|
504
|
+
`Update wasm in caatinga.config.ts to "${toConfigRelativeWasmPath(migratedPath)}" or an equivalent path under target/${CURRENT_RUST_WASM_TARGET}/release/.`
|
|
505
|
+
].join(" ");
|
|
506
|
+
return new CaatingaError(
|
|
507
|
+
`WASM output was not found at ${configuredWasmPath}.`,
|
|
508
|
+
CaatingaErrorCode.ARTIFACT_NOT_FOUND,
|
|
509
|
+
hint
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
function toConfigRelativeWasmPath(absoluteWasmPath) {
|
|
513
|
+
const relative = path5.relative(process.cwd(), absoluteWasmPath);
|
|
514
|
+
return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(path5.sep).join("/")}`;
|
|
515
|
+
}
|
|
516
|
+
async function resolveWasmArtifactPath(configuredWasmPath) {
|
|
412
517
|
try {
|
|
413
|
-
await access2(
|
|
518
|
+
await access2(configuredWasmPath);
|
|
519
|
+
return configuredWasmPath;
|
|
414
520
|
} catch {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
521
|
+
const currentTargetPath = toCurrentWasmTargetPath(configuredWasmPath);
|
|
522
|
+
if (currentTargetPath === configuredWasmPath) {
|
|
523
|
+
throw wasmNotFoundError(configuredWasmPath);
|
|
524
|
+
}
|
|
525
|
+
try {
|
|
526
|
+
await access2(currentTargetPath);
|
|
527
|
+
return currentTargetPath;
|
|
528
|
+
} catch {
|
|
529
|
+
throw wasmNotFoundError(configuredWasmPath, { migratedPath: currentTargetPath });
|
|
530
|
+
}
|
|
420
531
|
}
|
|
421
532
|
}
|
|
422
533
|
async function hashWasm(wasmPath) {
|
|
423
534
|
const bytes = await readFile2(wasmPath);
|
|
424
535
|
return createHash("sha256").update(bytes).digest("hex");
|
|
425
536
|
}
|
|
537
|
+
async function getNewestMtimeInDirectory(directory) {
|
|
538
|
+
try {
|
|
539
|
+
await access2(directory);
|
|
540
|
+
} catch {
|
|
541
|
+
return void 0;
|
|
542
|
+
}
|
|
543
|
+
let newest = 0;
|
|
544
|
+
async function walk(dir) {
|
|
545
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
546
|
+
for (const entry of entries) {
|
|
547
|
+
const entryPath = path5.join(dir, entry.name);
|
|
548
|
+
if (entry.isDirectory()) {
|
|
549
|
+
await walk(entryPath);
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
if (!entry.isFile()) {
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
const fileStat = await stat(entryPath);
|
|
556
|
+
newest = Math.max(newest, fileStat.mtimeMs);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
await walk(directory);
|
|
560
|
+
return newest > 0 ? newest : void 0;
|
|
561
|
+
}
|
|
562
|
+
async function isWasmOlderThanSources(input) {
|
|
563
|
+
const srcDir = path5.join(input.contractPath, "src");
|
|
564
|
+
const newestSourceMtime = await getNewestMtimeInDirectory(srcDir);
|
|
565
|
+
if (newestSourceMtime === void 0) {
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
let wasmStat;
|
|
569
|
+
try {
|
|
570
|
+
wasmStat = await stat(input.wasmPath);
|
|
571
|
+
} catch {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
return wasmStat.mtimeMs < newestSourceMtime;
|
|
575
|
+
}
|
|
576
|
+
function formatStaleWasmWarning(contractName) {
|
|
577
|
+
return `WASM for "${contractName}" may be stale: contract sources under src/ are newer than the WASM file. Run \`caatinga build\` before deploy.`;
|
|
578
|
+
}
|
|
426
579
|
|
|
427
580
|
// src/contracts/build-contract.ts
|
|
428
|
-
var RUST_WASM_TARGET = "
|
|
581
|
+
var RUST_WASM_TARGET = "wasm32v1-none";
|
|
429
582
|
var MISSING_WASM_TARGET_HINT_SUBSTRINGS = [
|
|
430
583
|
"not installed",
|
|
431
584
|
"not found",
|
|
@@ -467,100 +620,24 @@ async function buildContract(options) {
|
|
|
467
620
|
throw new CaatingaError(
|
|
468
621
|
`Required Rust wasm target "${RUST_WASM_TARGET}" is missing.`,
|
|
469
622
|
CaatingaErrorCode.RUST_TARGET_NOT_FOUND,
|
|
470
|
-
`Run \`rustup target add ${RUST_WASM_TARGET}\` and retry
|
|
623
|
+
`Run \`rustup target add ${RUST_WASM_TARGET}\` and retry.`,
|
|
471
624
|
error
|
|
472
625
|
);
|
|
473
626
|
}
|
|
474
627
|
throw error;
|
|
475
628
|
}
|
|
476
|
-
await
|
|
629
|
+
const wasmPath = await resolveWasmArtifactPath(contract.wasmPath);
|
|
477
630
|
return {
|
|
478
|
-
contract
|
|
631
|
+
contract: {
|
|
632
|
+
...contract,
|
|
633
|
+
wasmPath
|
|
634
|
+
},
|
|
479
635
|
output: result.all || result.stdout
|
|
480
636
|
};
|
|
481
637
|
}
|
|
482
638
|
|
|
483
639
|
// src/contracts/deploy-contract.ts
|
|
484
|
-
import
|
|
485
|
-
|
|
486
|
-
// src/stellar-cli/recover-deploy-contract-id.ts
|
|
487
|
-
var TX_HASH_REGEX = /Transaction hash is ([a-f0-9]{64})/i;
|
|
488
|
-
var DEPLOY_SIGNING_FAILURE_REGEX = /xdr processing error: xdr value invalid/i;
|
|
489
|
-
var HORIZON_URL_BY_PASSPHRASE = {
|
|
490
|
-
"Test SDF Network ; September 2015": "https://horizon-testnet.stellar.org",
|
|
491
|
-
"Public Global Stellar Network ; September 2015": "https://horizon.stellar.org"
|
|
492
|
-
};
|
|
493
|
-
function isLikelyPublicKeySource(source) {
|
|
494
|
-
return /^G[A-Z2-7]{55}$/.test(source);
|
|
495
|
-
}
|
|
496
|
-
function decimalSaltToHex(salt) {
|
|
497
|
-
return BigInt(salt).toString(16).padStart(64, "0");
|
|
498
|
-
}
|
|
499
|
-
function resolveHorizonUrl(network) {
|
|
500
|
-
const horizonUrl = HORIZON_URL_BY_PASSPHRASE[network.networkPassphrase];
|
|
501
|
-
if (!horizonUrl) {
|
|
502
|
-
throw new CaatingaError(
|
|
503
|
-
`No Horizon URL mapping for network passphrase "${network.networkPassphrase}".`,
|
|
504
|
-
CaatingaErrorCode.NETWORK_NOT_FOUND,
|
|
505
|
-
"Use testnet or mainnet, or extend Caatinga network metadata."
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
return horizonUrl;
|
|
509
|
-
}
|
|
510
|
-
async function fetchCreateContractSalt(horizonUrl, transactionHash, fetchImpl = fetch) {
|
|
511
|
-
const response = await fetchImpl(`${horizonUrl}/transactions/${transactionHash}/operations`);
|
|
512
|
-
if (!response.ok) {
|
|
513
|
-
return null;
|
|
514
|
-
}
|
|
515
|
-
const body = await response.json();
|
|
516
|
-
const operation = body._embedded?.records?.find(
|
|
517
|
-
(record) => record.transaction_successful === true && record.type === "invoke_host_function" && record.function === "HostFunctionTypeHostFunctionTypeCreateContract" && typeof record.salt === "string"
|
|
518
|
-
);
|
|
519
|
-
return operation?.salt ?? null;
|
|
520
|
-
}
|
|
521
|
-
async function resolveContractIdFromDeploySalt(options) {
|
|
522
|
-
const saltHex = decimalSaltToHex(options.salt);
|
|
523
|
-
const result = await runCommand("stellar", [
|
|
524
|
-
"contract",
|
|
525
|
-
"id",
|
|
526
|
-
"wasm",
|
|
527
|
-
"--salt",
|
|
528
|
-
saltHex,
|
|
529
|
-
"--source-account",
|
|
530
|
-
options.source,
|
|
531
|
-
"--rpc-url",
|
|
532
|
-
options.network.rpcUrl,
|
|
533
|
-
"--network-passphrase",
|
|
534
|
-
options.network.networkPassphrase
|
|
535
|
-
], {
|
|
536
|
-
cwd: options.cwd,
|
|
537
|
-
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
538
|
-
skipStellarVersionCheck: true
|
|
539
|
-
});
|
|
540
|
-
return parseContractId(result.all || `${result.stdout}
|
|
541
|
-
${result.stderr}`);
|
|
542
|
-
}
|
|
543
|
-
async function tryRecoverContractIdFromDeployFailure(options) {
|
|
544
|
-
if (!DEPLOY_SIGNING_FAILURE_REGEX.test(options.output)) {
|
|
545
|
-
return null;
|
|
546
|
-
}
|
|
547
|
-
const hashMatch = options.output.match(TX_HASH_REGEX);
|
|
548
|
-
if (!hashMatch) {
|
|
549
|
-
return null;
|
|
550
|
-
}
|
|
551
|
-
const horizonUrl = resolveHorizonUrl(options.network);
|
|
552
|
-
const salt = await fetchCreateContractSalt(horizonUrl, hashMatch[1], options.fetchImpl);
|
|
553
|
-
if (!salt) {
|
|
554
|
-
return null;
|
|
555
|
-
}
|
|
556
|
-
return resolveContractIdFromDeploySalt({
|
|
557
|
-
salt,
|
|
558
|
-
source: options.source,
|
|
559
|
-
network: options.network,
|
|
560
|
-
cwd: options.cwd,
|
|
561
|
-
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
562
|
-
});
|
|
563
|
-
}
|
|
640
|
+
import path6 from "path";
|
|
564
641
|
|
|
565
642
|
// src/contracts/dependency-graph.ts
|
|
566
643
|
function buildDependencyGraph(contracts) {
|
|
@@ -611,19 +688,9 @@ function assertSafeSourceAccount(source) {
|
|
|
611
688
|
"Pass a Stellar CLI identity alias, for example: --source alice"
|
|
612
689
|
);
|
|
613
690
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
CaatingaErrorCode.UNSAFE_SOURCE_ACCOUNT,
|
|
618
|
-
"Use a Stellar CLI identity alias instead, for example: --source alice"
|
|
619
|
-
);
|
|
620
|
-
}
|
|
621
|
-
if (isLikelyPublicKeySource(source)) {
|
|
622
|
-
throw new CaatingaError(
|
|
623
|
-
`Public account address cannot sign transactions: ${source}`,
|
|
624
|
-
CaatingaErrorCode.UNSAFE_SOURCE_ACCOUNT,
|
|
625
|
-
"Use a Stellar CLI identity with a secret key. Example: stellar keys generate alice --fund --network testnet, then --source alice"
|
|
626
|
-
);
|
|
691
|
+
const unsafeSource = validateSourceShape(source);
|
|
692
|
+
if (unsafeSource) {
|
|
693
|
+
throw unsafeSource;
|
|
627
694
|
}
|
|
628
695
|
return source;
|
|
629
696
|
}
|
|
@@ -651,17 +718,32 @@ async function deployContract(options) {
|
|
|
651
718
|
await checkBinary("stellar", "Install Stellar CLI before running caatinga deploy.", {
|
|
652
719
|
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
653
720
|
});
|
|
654
|
-
await
|
|
721
|
+
const wasmPath = await resolveWasmArtifactPath(contract.wasmPath);
|
|
722
|
+
const contractWithWasm = {
|
|
723
|
+
...contract,
|
|
724
|
+
wasmPath
|
|
725
|
+
};
|
|
726
|
+
let staleWasmWarning;
|
|
727
|
+
if (options.checkStaleWasm !== false) {
|
|
728
|
+
const stale = await isWasmOlderThanSources({
|
|
729
|
+
wasmPath,
|
|
730
|
+
contractPath: contract.sourcePath
|
|
731
|
+
});
|
|
732
|
+
if (stale) {
|
|
733
|
+
staleWasmWarning = formatStaleWasmWarning(contract.name);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
655
736
|
const artifactsBefore = await readArtifacts(cwd);
|
|
656
737
|
const existing = artifactsBefore.networks[network.name]?.contracts[contract.name];
|
|
657
738
|
if (existing?.contractId && !options.force) {
|
|
658
739
|
return {
|
|
659
|
-
contract,
|
|
740
|
+
contract: contractWithWasm,
|
|
660
741
|
network,
|
|
661
742
|
contractId: existing.contractId,
|
|
662
|
-
artifactsPath:
|
|
743
|
+
artifactsPath: path6.resolve(cwd, "caatinga.artifacts.json"),
|
|
663
744
|
output: "",
|
|
664
|
-
skipped: true
|
|
745
|
+
skipped: true,
|
|
746
|
+
staleWasmWarning
|
|
665
747
|
};
|
|
666
748
|
}
|
|
667
749
|
const rawDeployArgs = contract.config.deployArgs;
|
|
@@ -692,13 +774,10 @@ async function deployContract(options) {
|
|
|
692
774
|
"contract",
|
|
693
775
|
"deploy",
|
|
694
776
|
"--wasm",
|
|
695
|
-
|
|
777
|
+
wasmPath,
|
|
696
778
|
"--source-account",
|
|
697
779
|
source,
|
|
698
|
-
|
|
699
|
-
network.config.rpcUrl,
|
|
700
|
-
"--network-passphrase",
|
|
701
|
-
network.config.networkPassphrase,
|
|
780
|
+
...buildStellarNetworkArgs(network),
|
|
702
781
|
...constructorArgs
|
|
703
782
|
];
|
|
704
783
|
let output = "";
|
|
@@ -734,7 +813,7 @@ ${error.hint ?? ""}`,
|
|
|
734
813
|
`Contract ID: ${contractId}`
|
|
735
814
|
].filter(Boolean).join("\n");
|
|
736
815
|
}
|
|
737
|
-
const wasmHash = await hashWasm(
|
|
816
|
+
const wasmHash = await hashWasm(wasmPath);
|
|
738
817
|
const dependencyGraph = buildDependencyGraph(options.config.contracts);
|
|
739
818
|
const dependencies = options.dependencies ?? contract.config.dependsOn;
|
|
740
819
|
const nextArtifacts = updateArtifact(
|
|
@@ -754,12 +833,13 @@ ${error.hint ?? ""}`,
|
|
|
754
833
|
);
|
|
755
834
|
const artifactsPath = await writeArtifacts(nextArtifacts, cwd);
|
|
756
835
|
return {
|
|
757
|
-
contract,
|
|
836
|
+
contract: contractWithWasm,
|
|
758
837
|
network,
|
|
759
838
|
contractId,
|
|
760
839
|
artifactsPath,
|
|
761
840
|
output,
|
|
762
|
-
skipped: false
|
|
841
|
+
skipped: false,
|
|
842
|
+
staleWasmWarning
|
|
763
843
|
};
|
|
764
844
|
}
|
|
765
845
|
|
|
@@ -814,6 +894,53 @@ function resolveDeployOrder(input) {
|
|
|
814
894
|
}
|
|
815
895
|
}
|
|
816
896
|
|
|
897
|
+
// src/contracts/verify-dependency-contract.ts
|
|
898
|
+
async function verifyDependencyContract(options) {
|
|
899
|
+
try {
|
|
900
|
+
await runCommand("stellar", [
|
|
901
|
+
"contract",
|
|
902
|
+
"info",
|
|
903
|
+
"interface",
|
|
904
|
+
"--contract-id",
|
|
905
|
+
options.contractId,
|
|
906
|
+
...buildStellarNetworkArgs(options.network)
|
|
907
|
+
], {
|
|
908
|
+
cwd: options.cwd,
|
|
909
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
910
|
+
failureCode: CaatingaErrorCode.DEPENDENCY_CONTRACT_NOT_FOUND
|
|
911
|
+
});
|
|
912
|
+
} catch (error) {
|
|
913
|
+
if (error instanceof CaatingaError && error.code === CaatingaErrorCode.DEPENDENCY_CONTRACT_NOT_FOUND) {
|
|
914
|
+
throw new CaatingaError(
|
|
915
|
+
`Dependency "${options.dependencyName}" is not deployed on "${options.network.name}" (contract ID ${options.contractId}).`,
|
|
916
|
+
CaatingaErrorCode.DEPENDENCY_CONTRACT_NOT_FOUND,
|
|
917
|
+
"Deploy the dependency on this network, fix caatinga.artifacts.json, or omit --verify-deps.",
|
|
918
|
+
error.cause
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
throw error;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
async function verifyDependencyContracts(options) {
|
|
925
|
+
for (const dependencyName of options.dependencies) {
|
|
926
|
+
const contractArtifact = options.artifacts.networks[options.network.name]?.contracts[dependencyName];
|
|
927
|
+
if (!contractArtifact?.contractId) {
|
|
928
|
+
throw new CaatingaError(
|
|
929
|
+
`No dependency artifact found for "${dependencyName}" on "${options.network.name}".`,
|
|
930
|
+
CaatingaErrorCode.CONTRACT_DEPENDENCY_ARTIFACT_NOT_FOUND,
|
|
931
|
+
"Deploy the dependency first or run deploy without --no-deps."
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
await verifyDependencyContract({
|
|
935
|
+
dependencyName,
|
|
936
|
+
contractId: contractArtifact.contractId,
|
|
937
|
+
network: options.network,
|
|
938
|
+
cwd: options.cwd,
|
|
939
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
817
944
|
// src/contracts/deploy-contract-graph.ts
|
|
818
945
|
async function deployContractGraph(options) {
|
|
819
946
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -824,17 +951,33 @@ async function deployContractGraph(options) {
|
|
|
824
951
|
includeDependencies: options.includeDependencies
|
|
825
952
|
});
|
|
826
953
|
const deployedContracts = [];
|
|
954
|
+
const skippedContracts = [];
|
|
955
|
+
const staleWasmWarnings = [];
|
|
827
956
|
for (const contractName of order) {
|
|
828
957
|
const artifacts = await readArtifacts(cwd);
|
|
829
958
|
const existing = artifacts.networks[network.name]?.contracts[contractName];
|
|
830
959
|
const contractConfig = options.config.contracts[contractName];
|
|
960
|
+
if (options.verifyDeps && contractConfig.dependsOn.length > 0) {
|
|
961
|
+
await verifyDependencyContracts({
|
|
962
|
+
dependencies: contractConfig.dependsOn,
|
|
963
|
+
artifacts,
|
|
964
|
+
network,
|
|
965
|
+
cwd,
|
|
966
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
967
|
+
});
|
|
968
|
+
}
|
|
831
969
|
const resolvedDeployArgs = resolveDeployArgs({
|
|
832
970
|
deployArgs: contractConfig.deployArgs,
|
|
833
971
|
artifacts,
|
|
834
972
|
network: network.name
|
|
835
973
|
});
|
|
836
974
|
if (existing?.contractId && !options.force) {
|
|
837
|
-
|
|
975
|
+
skippedContracts.push({
|
|
976
|
+
name: contractName,
|
|
977
|
+
contractId: existing.contractId,
|
|
978
|
+
network: network.name,
|
|
979
|
+
reason: "already-deployed"
|
|
980
|
+
});
|
|
838
981
|
continue;
|
|
839
982
|
}
|
|
840
983
|
const result = await deployContract({
|
|
@@ -845,20 +988,38 @@ async function deployContractGraph(options) {
|
|
|
845
988
|
cwd,
|
|
846
989
|
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
847
990
|
force: options.force,
|
|
991
|
+
checkStaleWasm: options.checkStaleWasm,
|
|
848
992
|
resolvedDeployArgs,
|
|
849
993
|
dependencies: contractConfig.dependsOn
|
|
850
994
|
});
|
|
851
|
-
|
|
995
|
+
if (result.staleWasmWarning) {
|
|
996
|
+
staleWasmWarnings.push({
|
|
997
|
+
contract: contractName,
|
|
998
|
+
message: result.staleWasmWarning
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
if (result.skipped) {
|
|
1002
|
+
skippedContracts.push({
|
|
1003
|
+
name: contractName,
|
|
1004
|
+
contractId: result.contractId,
|
|
1005
|
+
network: network.name,
|
|
1006
|
+
reason: "already-deployed"
|
|
1007
|
+
});
|
|
1008
|
+
} else {
|
|
1009
|
+
deployedContracts.push({ name: contractName, contractId: result.contractId });
|
|
1010
|
+
}
|
|
852
1011
|
}
|
|
853
1012
|
return {
|
|
854
1013
|
network,
|
|
855
|
-
deployedContracts
|
|
1014
|
+
deployedContracts,
|
|
1015
|
+
skippedContracts,
|
|
1016
|
+
staleWasmWarnings
|
|
856
1017
|
};
|
|
857
1018
|
}
|
|
858
1019
|
|
|
859
1020
|
// src/contracts/generate-bindings.ts
|
|
860
1021
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
861
|
-
import
|
|
1022
|
+
import path7 from "path";
|
|
862
1023
|
async function generateBindings(options) {
|
|
863
1024
|
const cwd = options.cwd ?? process.cwd();
|
|
864
1025
|
const network = resolveNetwork(options.config, options.networkName);
|
|
@@ -874,7 +1035,7 @@ async function generateBindings(options) {
|
|
|
874
1035
|
await checkBinary("stellar", "Install Stellar CLI before running caatinga generate.", {
|
|
875
1036
|
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
876
1037
|
});
|
|
877
|
-
const outputDir =
|
|
1038
|
+
const outputDir = path7.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
|
|
878
1039
|
await mkdir2(outputDir, { recursive: true });
|
|
879
1040
|
const result = await runCommand("stellar", [
|
|
880
1041
|
"contract",
|
|
@@ -885,10 +1046,7 @@ async function generateBindings(options) {
|
|
|
885
1046
|
"--output-dir",
|
|
886
1047
|
outputDir,
|
|
887
1048
|
"--overwrite",
|
|
888
|
-
|
|
889
|
-
network.config.rpcUrl,
|
|
890
|
-
"--network-passphrase",
|
|
891
|
-
network.config.networkPassphrase
|
|
1049
|
+
...buildStellarNetworkArgs(network)
|
|
892
1050
|
], {
|
|
893
1051
|
cwd,
|
|
894
1052
|
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
@@ -903,6 +1061,7 @@ async function generateBindings(options) {
|
|
|
903
1061
|
}
|
|
904
1062
|
|
|
905
1063
|
// src/contracts/invoke-contract.ts
|
|
1064
|
+
var INVOKE_SIGNING_FAILURE_REGEX = /xdr processing error: xdr value invalid/i;
|
|
906
1065
|
function parseInvokeTarget(target) {
|
|
907
1066
|
const [contractName, method, extra] = target.split(".");
|
|
908
1067
|
if (!contractName || !method || extra) {
|
|
@@ -931,25 +1090,43 @@ async function invokeContract(options) {
|
|
|
931
1090
|
await checkBinary("stellar", "Install Stellar CLI before running caatinga invoke.", {
|
|
932
1091
|
allowUntestedStellarCli: options.allowUntestedStellarCli
|
|
933
1092
|
});
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
"
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
})
|
|
1093
|
+
let result;
|
|
1094
|
+
try {
|
|
1095
|
+
result = await runCommand("stellar", [
|
|
1096
|
+
"contract",
|
|
1097
|
+
"invoke",
|
|
1098
|
+
"--id",
|
|
1099
|
+
contractArtifact.contractId,
|
|
1100
|
+
"--source-account",
|
|
1101
|
+
source,
|
|
1102
|
+
...buildStellarNetworkArgs(network),
|
|
1103
|
+
"--",
|
|
1104
|
+
target.method,
|
|
1105
|
+
...options.args ?? []
|
|
1106
|
+
], {
|
|
1107
|
+
cwd,
|
|
1108
|
+
allowUntestedStellarCli: options.allowUntestedStellarCli,
|
|
1109
|
+
failureCode: CaatingaErrorCode.INVOKE_FAILED
|
|
1110
|
+
});
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
if (error instanceof CaatingaError && error.code === CaatingaErrorCode.INVOKE_FAILED && INVOKE_SIGNING_FAILURE_REGEX.test(`${error.message}
|
|
1113
|
+
${error.hint ?? ""}`)) {
|
|
1114
|
+
throw new CaatingaError(
|
|
1115
|
+
error.message,
|
|
1116
|
+
error.code,
|
|
1117
|
+
[
|
|
1118
|
+
"Stellar CLI could not sign the invoke transaction (xdr value invalid).",
|
|
1119
|
+
"Stellar CLI 22.x has a known invoke signing bug; upgrade to 23.0.0 or newer (25.2.0 recommended).",
|
|
1120
|
+
" stellar --version",
|
|
1121
|
+
"Then retry with a funded identity, for example:",
|
|
1122
|
+
" stellar keys generate alice --fund --network testnet",
|
|
1123
|
+
" npx caatinga invoke counter.increment --network testnet --source alice"
|
|
1124
|
+
].join("\n"),
|
|
1125
|
+
error
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
throw error;
|
|
1129
|
+
}
|
|
953
1130
|
return {
|
|
954
1131
|
target,
|
|
955
1132
|
network,
|
|
@@ -958,8 +1135,8 @@ async function invokeContract(options) {
|
|
|
958
1135
|
}
|
|
959
1136
|
|
|
960
1137
|
// src/templates/create-project-from-template.ts
|
|
961
|
-
import { cp, mkdir as mkdir3, readFile as readFile3, readdir, stat, writeFile as writeFile2 } from "fs/promises";
|
|
962
|
-
import
|
|
1138
|
+
import { cp, mkdir as mkdir3, readFile as readFile3, readdir as readdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
1139
|
+
import path8 from "path";
|
|
963
1140
|
import { z as z6 } from "zod";
|
|
964
1141
|
|
|
965
1142
|
// src/templates/template-manifest.schema.ts
|
|
@@ -1029,10 +1206,10 @@ function formatTemplateCompatibilityHint(issue) {
|
|
|
1029
1206
|
|
|
1030
1207
|
// src/templates/create-project-from-template.ts
|
|
1031
1208
|
async function createProjectFromTemplate(options) {
|
|
1032
|
-
const targetDir =
|
|
1033
|
-
const templateDir =
|
|
1209
|
+
const targetDir = path8.resolve(options.targetDir);
|
|
1210
|
+
const templateDir = path8.resolve(options.templateDir);
|
|
1034
1211
|
try {
|
|
1035
|
-
await
|
|
1212
|
+
await stat2(templateDir);
|
|
1036
1213
|
} catch {
|
|
1037
1214
|
throw new CaatingaError(
|
|
1038
1215
|
`Template directory was not found: ${templateDir}`,
|
|
@@ -1052,7 +1229,7 @@ async function createProjectFromTemplate(options) {
|
|
|
1052
1229
|
return { targetDir, template: manifest };
|
|
1053
1230
|
}
|
|
1054
1231
|
async function readTemplateManifest(templateDir) {
|
|
1055
|
-
const manifestPath =
|
|
1232
|
+
const manifestPath = path8.join(templateDir, "caatinga.template.json");
|
|
1056
1233
|
try {
|
|
1057
1234
|
const rawManifest = await readFile3(manifestPath, "utf8");
|
|
1058
1235
|
const manifest = TemplateManifestSchema.parse(JSON.parse(rawManifest));
|
|
@@ -1087,10 +1264,10 @@ async function readTemplateManifest(templateDir) {
|
|
|
1087
1264
|
}
|
|
1088
1265
|
}
|
|
1089
1266
|
async function replaceTemplateVariables(dir, projectName) {
|
|
1090
|
-
const entries = await
|
|
1267
|
+
const entries = await readdir2(dir);
|
|
1091
1268
|
await Promise.all(entries.map(async (entry) => {
|
|
1092
|
-
const entryPath =
|
|
1093
|
-
const entryStat = await
|
|
1269
|
+
const entryPath = path8.join(dir, entry);
|
|
1270
|
+
const entryStat = await stat2(entryPath);
|
|
1094
1271
|
if (entryStat.isDirectory()) {
|
|
1095
1272
|
await replaceTemplateVariables(entryPath, projectName);
|
|
1096
1273
|
return;
|
|
@@ -1112,7 +1289,7 @@ function isTextTemplateFile(filePath) {
|
|
|
1112
1289
|
".tsx",
|
|
1113
1290
|
".css",
|
|
1114
1291
|
".html"
|
|
1115
|
-
].includes(
|
|
1292
|
+
].includes(path8.extname(filePath));
|
|
1116
1293
|
}
|
|
1117
1294
|
|
|
1118
1295
|
// src/ci/is-transient-testnet-smoke-failure.ts
|
|
@@ -1170,5 +1347,6 @@ export {
|
|
|
1170
1347
|
runCommand,
|
|
1171
1348
|
toCaatingaError,
|
|
1172
1349
|
updateArtifact,
|
|
1350
|
+
validateSourceShape,
|
|
1173
1351
|
writeArtifacts
|
|
1174
1352
|
};
|