@caatinga/core 2.0.2 → 2.2.0

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.cjs CHANGED
@@ -30,6 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ BINDING_MARKER_FILENAME: () => BINDING_MARKER_FILENAME,
34
+ BindingMarkerSchema: () => BindingMarkerSchema,
33
35
  CAATINGA_CORE_VERSION: () => CAATINGA_CORE_VERSION,
34
36
  CaatingaArtifactsSchema: () => CaatingaArtifactsSchema,
35
37
  CaatingaConfigSchema: () => CaatingaConfigSchema,
@@ -43,13 +45,18 @@ __export(index_exports, {
43
45
  buildDependencyGraph: () => buildDependencyGraph,
44
46
  checkBinary: () => checkBinary,
45
47
  checkStellarCliVersion: () => checkStellarCliVersion,
48
+ collectProjectStatus: () => collectProjectStatus,
46
49
  createInitialArtifacts: () => createInitialArtifacts,
47
50
  createProjectFromTemplate: () => createProjectFromTemplate,
48
51
  defineConfig: () => defineConfig,
49
52
  deployContract: () => deployContract,
50
53
  deployContractGraph: () => deployContractGraph,
54
+ evaluateBindingFreshness: () => evaluateBindingFreshness,
55
+ evaluateBindingsFreshness: () => evaluateBindingsFreshness,
51
56
  evaluateStellarCliCompatibility: () => evaluateStellarCliCompatibility,
57
+ formatCaatingaError: () => formatCaatingaError,
52
58
  generateBindings: () => generateBindings,
59
+ generateBindingsGraph: () => generateBindingsGraph,
53
60
  invokeContract: () => invokeContract,
54
61
  isTransientTestnetSmokeFailure: () => isTransientTestnetSmokeFailure,
55
62
  loadConfig: () => loadConfig,
@@ -57,6 +64,7 @@ __export(index_exports, {
57
64
  parseInvokeTarget: () => parseInvokeTarget,
58
65
  parseStellarCliVersion: () => parseStellarCliVersion,
59
66
  readArtifacts: () => readArtifacts,
67
+ readBindingMarker: () => readBindingMarker,
60
68
  resolveContract: () => resolveContract,
61
69
  resolveDeployArgs: () => resolveDeployArgs,
62
70
  resolveDeployOrder: () => resolveDeployOrder,
@@ -65,7 +73,8 @@ __export(index_exports, {
65
73
  toCaatingaError: () => toCaatingaError,
66
74
  updateArtifact: () => updateArtifact,
67
75
  validateSourceShape: () => validateSourceShape,
68
- writeArtifacts: () => writeArtifacts
76
+ writeArtifacts: () => writeArtifacts,
77
+ writeBindingMarker: () => writeBindingMarker
69
78
  });
70
79
  module.exports = __toCommonJS(index_exports);
71
80
 
@@ -98,6 +107,7 @@ var CaatingaErrorCode = {
98
107
  DEPLOY_ARG_PLACEHOLDER_UNRESOLVED: "CAATINGA_DEPLOY_ARG_PLACEHOLDER_UNRESOLVED",
99
108
  BINDING_CLIENT_NOT_FOUND: "CAATINGA_BINDING_CLIENT_NOT_FOUND",
100
109
  BINDING_METHOD_NOT_FOUND: "CAATINGA_BINDING_METHOD_NOT_FOUND",
110
+ PLACEHOLDER_BINDING: "CAATINGA_PLACEHOLDER_BINDING",
101
111
  XDR_BUILD_FAILED: "CAATINGA_XDR_BUILD_FAILED",
102
112
  XDR_PREPARE_FAILED: "CAATINGA_XDR_PREPARE_FAILED",
103
113
  XDR_SIGN_FAILED: "CAATINGA_XDR_SIGN_FAILED",
@@ -142,8 +152,40 @@ function toCaatingaError(error) {
142
152
  return new CaatingaError("An unexpected error occurred.", CaatingaErrorCode.UNEXPECTED_ERROR);
143
153
  }
144
154
 
155
+ // src/errors/format-caatinga-error.ts
156
+ function formatCaatingaError(error) {
157
+ if (error instanceof CaatingaError) {
158
+ const lines = [`[${error.code}] ${error.message}`];
159
+ if (error.hint) {
160
+ lines.push("", error.hint);
161
+ }
162
+ const detail = formatCause(error.cause);
163
+ if (detail) {
164
+ lines.push("", `Details: ${detail}`);
165
+ }
166
+ return lines.join("\n");
167
+ }
168
+ return error instanceof Error ? error.message : String(error);
169
+ }
170
+ function formatCause(cause) {
171
+ if (cause === void 0 || cause === null) {
172
+ return "";
173
+ }
174
+ if (cause instanceof Error) {
175
+ return cause.message;
176
+ }
177
+ if (typeof cause === "string") {
178
+ return cause;
179
+ }
180
+ try {
181
+ return JSON.stringify(cause);
182
+ } catch {
183
+ return String(cause);
184
+ }
185
+ }
186
+
145
187
  // src/version.ts
146
- var CAATINGA_CORE_VERSION = "2.0.2";
188
+ var CAATINGA_CORE_VERSION = "2.2.0";
147
189
 
148
190
  // src/config/config.schema.ts
149
191
  var import_zod = require("zod");
@@ -309,18 +351,6 @@ function updateArtifact(artifacts, networkName, contractName, contractArtifact,
309
351
  };
310
352
  }
311
353
 
312
- // src/networks/networks.ts
313
- var WELL_KNOWN_NETWORKS = {
314
- testnet: {
315
- rpcUrl: "https://soroban-testnet.stellar.org",
316
- networkPassphrase: "Test SDF Network ; September 2015"
317
- },
318
- mainnet: {
319
- rpcUrl: "https://mainnet.sorobanrpc.com",
320
- networkPassphrase: "Public Global Stellar Network ; September 2015"
321
- }
322
- };
323
-
324
354
  // src/networks/resolve-network.ts
325
355
  function resolveNetwork(config, networkName) {
326
356
  const name = networkName ?? config.defaultNetwork;
@@ -335,6 +365,174 @@ function resolveNetwork(config, networkName) {
335
365
  return { name, config: network };
336
366
  }
337
367
 
368
+ // src/bindings/binding-freshness.ts
369
+ var import_promises5 = require("fs/promises");
370
+ var import_node_path5 = __toESM(require("path"), 1);
371
+
372
+ // src/bindings/binding-marker.ts
373
+ var import_promises4 = require("fs/promises");
374
+ var import_node_path4 = __toESM(require("path"), 1);
375
+ var import_zod5 = require("zod");
376
+ var BINDING_MARKER_FILENAME = ".caatinga-bindings.json";
377
+ var BindingMarkerSchema = import_zod5.z.object({
378
+ version: import_zod5.z.literal(1),
379
+ contractId: import_zod5.z.string().min(1),
380
+ wasmHash: import_zod5.z.string().min(1),
381
+ network: import_zod5.z.string().min(1),
382
+ generatedAt: import_zod5.z.string().datetime()
383
+ });
384
+ async function writeBindingMarker(outputDir, marker) {
385
+ const markerPath = import_node_path4.default.join(outputDir, BINDING_MARKER_FILENAME);
386
+ await (0, import_promises4.writeFile)(markerPath, `${JSON.stringify(marker, null, 2)}
387
+ `, "utf8");
388
+ }
389
+ async function readBindingMarker(outputDir) {
390
+ const markerPath = import_node_path4.default.join(outputDir, BINDING_MARKER_FILENAME);
391
+ let raw;
392
+ try {
393
+ raw = await (0, import_promises4.readFile)(markerPath, "utf8");
394
+ } catch {
395
+ return null;
396
+ }
397
+ try {
398
+ return BindingMarkerSchema.parse(JSON.parse(raw));
399
+ } catch {
400
+ return null;
401
+ }
402
+ }
403
+
404
+ // src/bindings/binding-freshness.ts
405
+ async function listGeneratedEntries(outputDir) {
406
+ try {
407
+ const entries = await (0, import_promises5.readdir)(outputDir);
408
+ return entries.filter((entry) => entry !== BINDING_MARKER_FILENAME);
409
+ } catch {
410
+ return null;
411
+ }
412
+ }
413
+ async function evaluateBindingFreshness(options) {
414
+ const cwd = options.cwd ?? process.cwd();
415
+ const outputDir = import_node_path5.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
416
+ const contractArtifact = options.artifacts.networks[options.networkName]?.contracts[options.contractName];
417
+ if (!contractArtifact) {
418
+ return {
419
+ contractName: options.contractName,
420
+ status: "missing",
421
+ outputDir,
422
+ marker: null,
423
+ reason: `not deployed on "${options.networkName}"`
424
+ };
425
+ }
426
+ const generatedEntries = await listGeneratedEntries(outputDir);
427
+ if (generatedEntries === null || generatedEntries.length === 0) {
428
+ return {
429
+ contractName: options.contractName,
430
+ status: "missing",
431
+ outputDir,
432
+ marker: null,
433
+ reason: "no generated bindings found"
434
+ };
435
+ }
436
+ const marker = await readBindingMarker(outputDir);
437
+ if (!marker) {
438
+ return {
439
+ contractName: options.contractName,
440
+ status: "unknown",
441
+ outputDir,
442
+ marker: null,
443
+ reason: "bindings exist but have no provenance marker \u2014 rerun caatinga generate to record it"
444
+ };
445
+ }
446
+ if (marker.contractId !== contractArtifact.contractId) {
447
+ return {
448
+ contractName: options.contractName,
449
+ status: "stale",
450
+ outputDir,
451
+ marker,
452
+ reason: "contractId changed since last generate"
453
+ };
454
+ }
455
+ if (marker.wasmHash !== contractArtifact.wasmHash) {
456
+ return {
457
+ contractName: options.contractName,
458
+ status: "stale",
459
+ outputDir,
460
+ marker,
461
+ reason: "wasmHash changed since last generate"
462
+ };
463
+ }
464
+ return {
465
+ contractName: options.contractName,
466
+ status: "fresh",
467
+ outputDir,
468
+ marker
469
+ };
470
+ }
471
+ async function evaluateBindingsFreshness(options) {
472
+ const contractNames = Object.keys(
473
+ options.artifacts.networks[options.networkName]?.contracts ?? {}
474
+ );
475
+ const results = [];
476
+ for (const contractName of contractNames) {
477
+ results.push(await evaluateBindingFreshness({ ...options, contractName }));
478
+ }
479
+ return results;
480
+ }
481
+
482
+ // src/artifacts/project-status.ts
483
+ async function collectProjectStatus(options) {
484
+ const cwd = options.cwd ?? process.cwd();
485
+ const artifacts = await readArtifacts(cwd);
486
+ let networkNames;
487
+ if (options.networkName) {
488
+ networkNames = [resolveNetwork(options.config, options.networkName).name];
489
+ } else {
490
+ const fromArtifacts = Object.keys(artifacts.networks);
491
+ const fallback = options.config.defaultNetwork ?? "testnet";
492
+ networkNames = fromArtifacts.length > 0 ? fromArtifacts : [fallback];
493
+ if (!networkNames.includes(fallback) && options.config.networks[fallback]) {
494
+ networkNames.push(fallback);
495
+ }
496
+ }
497
+ const networks = [];
498
+ for (const networkName of networkNames) {
499
+ const contracts = [];
500
+ for (const name of Object.keys(options.config.contracts)) {
501
+ const artifact = artifacts.networks[networkName]?.contracts[name];
502
+ const bindings = await evaluateBindingFreshness({
503
+ config: options.config,
504
+ artifacts,
505
+ networkName,
506
+ contractName: name,
507
+ cwd
508
+ });
509
+ contracts.push({
510
+ name,
511
+ deployed: Boolean(artifact),
512
+ contractId: artifact?.contractId,
513
+ wasmHash: artifact?.wasmHash,
514
+ deployedAt: artifact?.deployedAt,
515
+ dependencies: artifact?.dependencies ?? options.config.contracts[name].dependsOn ?? [],
516
+ bindings
517
+ });
518
+ }
519
+ networks.push({ network: networkName, contracts });
520
+ }
521
+ return { project: options.config.project, networks };
522
+ }
523
+
524
+ // src/networks/networks.ts
525
+ var WELL_KNOWN_NETWORKS = {
526
+ testnet: {
527
+ rpcUrl: "https://soroban-testnet.stellar.org",
528
+ networkPassphrase: "Test SDF Network ; September 2015"
529
+ },
530
+ mainnet: {
531
+ rpcUrl: "https://mainnet.sorobanrpc.com",
532
+ networkPassphrase: "Public Global Stellar Network ; September 2015"
533
+ }
534
+ };
535
+
338
536
  // src/shell/run-command.ts
339
537
  var import_execa = require("execa");
340
538
 
@@ -656,7 +854,7 @@ function validateSourceShape(source) {
656
854
  }
657
855
 
658
856
  // src/contracts/resolve-contract.ts
659
- var import_node_path4 = __toESM(require("path"), 1);
857
+ var import_node_path6 = __toESM(require("path"), 1);
660
858
  function resolveContract(config, contractName, cwd = process.cwd()) {
661
859
  const contract = config.contracts[contractName];
662
860
  if (!contract) {
@@ -669,15 +867,15 @@ function resolveContract(config, contractName, cwd = process.cwd()) {
669
867
  return {
670
868
  name: contractName,
671
869
  config: contract,
672
- sourcePath: import_node_path4.default.resolve(cwd, contract.path),
673
- wasmPath: import_node_path4.default.resolve(cwd, contract.wasm)
870
+ sourcePath: import_node_path6.default.resolve(cwd, contract.path),
871
+ wasmPath: import_node_path6.default.resolve(cwd, contract.wasm)
674
872
  };
675
873
  }
676
874
 
677
875
  // src/contracts/wasm.ts
678
876
  var import_node_crypto = require("crypto");
679
- var import_promises4 = require("fs/promises");
680
- var import_node_path5 = __toESM(require("path"), 1);
877
+ var import_promises6 = require("fs/promises");
878
+ var import_node_path7 = __toESM(require("path"), 1);
681
879
  var LEGACY_RUST_WASM_TARGET = "wasm32-unknown-unknown";
682
880
  var CURRENT_RUST_WASM_TARGET = "wasm32v1-none";
683
881
  function toCurrentWasmTargetPath(wasmPath) {
@@ -700,12 +898,12 @@ function wasmNotFoundError(configuredWasmPath, options) {
700
898
  );
701
899
  }
702
900
  function toConfigRelativeWasmPath(absoluteWasmPath) {
703
- const relative = import_node_path5.default.relative(process.cwd(), absoluteWasmPath);
704
- return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(import_node_path5.default.sep).join("/")}`;
901
+ const relative = import_node_path7.default.relative(process.cwd(), absoluteWasmPath);
902
+ return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(import_node_path7.default.sep).join("/")}`;
705
903
  }
706
904
  async function resolveWasmArtifactPath(configuredWasmPath) {
707
905
  try {
708
- await (0, import_promises4.access)(configuredWasmPath);
906
+ await (0, import_promises6.access)(configuredWasmPath);
709
907
  return configuredWasmPath;
710
908
  } catch {
711
909
  const currentTargetPath = toCurrentWasmTargetPath(configuredWasmPath);
@@ -713,7 +911,7 @@ async function resolveWasmArtifactPath(configuredWasmPath) {
713
911
  throw wasmNotFoundError(configuredWasmPath);
714
912
  }
715
913
  try {
716
- await (0, import_promises4.access)(currentTargetPath);
914
+ await (0, import_promises6.access)(currentTargetPath);
717
915
  return currentTargetPath;
718
916
  } catch {
719
917
  throw wasmNotFoundError(configuredWasmPath, { migratedPath: currentTargetPath });
@@ -721,20 +919,20 @@ async function resolveWasmArtifactPath(configuredWasmPath) {
721
919
  }
722
920
  }
723
921
  async function hashWasm(wasmPath) {
724
- const bytes = await (0, import_promises4.readFile)(wasmPath);
922
+ const bytes = await (0, import_promises6.readFile)(wasmPath);
725
923
  return (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
726
924
  }
727
925
  async function getNewestMtimeInDirectory(directory) {
728
926
  try {
729
- await (0, import_promises4.access)(directory);
927
+ await (0, import_promises6.access)(directory);
730
928
  } catch {
731
929
  return void 0;
732
930
  }
733
931
  let newest = 0;
734
932
  async function walk(dir) {
735
- const entries = await (0, import_promises4.readdir)(dir, { withFileTypes: true });
933
+ const entries = await (0, import_promises6.readdir)(dir, { withFileTypes: true });
736
934
  for (const entry of entries) {
737
- const entryPath = import_node_path5.default.join(dir, entry.name);
935
+ const entryPath = import_node_path7.default.join(dir, entry.name);
738
936
  if (entry.isDirectory()) {
739
937
  await walk(entryPath);
740
938
  continue;
@@ -742,7 +940,7 @@ async function getNewestMtimeInDirectory(directory) {
742
940
  if (!entry.isFile()) {
743
941
  continue;
744
942
  }
745
- const fileStat = await (0, import_promises4.stat)(entryPath);
943
+ const fileStat = await (0, import_promises6.stat)(entryPath);
746
944
  newest = Math.max(newest, fileStat.mtimeMs);
747
945
  }
748
946
  }
@@ -750,14 +948,14 @@ async function getNewestMtimeInDirectory(directory) {
750
948
  return newest > 0 ? newest : void 0;
751
949
  }
752
950
  async function isWasmOlderThanSources(input) {
753
- const srcDir = import_node_path5.default.join(input.contractPath, "src");
951
+ const srcDir = import_node_path7.default.join(input.contractPath, "src");
754
952
  const newestSourceMtime = await getNewestMtimeInDirectory(srcDir);
755
953
  if (newestSourceMtime === void 0) {
756
954
  return false;
757
955
  }
758
956
  let wasmStat;
759
957
  try {
760
- wasmStat = await (0, import_promises4.stat)(input.wasmPath);
958
+ wasmStat = await (0, import_promises6.stat)(input.wasmPath);
761
959
  } catch {
762
960
  return false;
763
961
  }
@@ -823,7 +1021,7 @@ async function buildContract(options) {
823
1021
  }
824
1022
 
825
1023
  // src/contracts/deploy-contract.ts
826
- var import_node_path6 = __toESM(require("path"), 1);
1024
+ var import_node_path8 = __toESM(require("path"), 1);
827
1025
 
828
1026
  // src/contracts/dependency-graph.ts
829
1027
  function buildDependencyGraph(contracts) {
@@ -924,7 +1122,7 @@ async function deployContract(options) {
924
1122
  contract: contractWithWasm,
925
1123
  network,
926
1124
  contractId: existing.contractId,
927
- artifactsPath: import_node_path6.default.resolve(cwd, "caatinga.artifacts.json"),
1125
+ artifactsPath: import_node_path8.default.resolve(cwd, "caatinga.artifacts.json"),
928
1126
  output: "",
929
1127
  skipped: true,
930
1128
  staleWasmWarning
@@ -1200,17 +1398,17 @@ async function deployContractGraph(options) {
1200
1398
  }
1201
1399
 
1202
1400
  // src/contracts/generate-bindings.ts
1203
- var import_promises5 = require("fs/promises");
1204
- var import_node_path7 = __toESM(require("path"), 1);
1401
+ var import_promises7 = require("fs/promises");
1402
+ var import_node_path9 = __toESM(require("path"), 1);
1205
1403
  function toBindingImportPath(bindingsOutput, contractName) {
1206
- const normalized = bindingsOutput.replace(/^\.\//, "").split(import_node_path7.default.sep).join("/");
1207
- return `./${import_node_path7.default.posix.join(normalized, contractName, "src", "index.js")}`;
1404
+ const normalized = bindingsOutput.replace(/^\.\//, "").split(import_node_path9.default.sep).join("/");
1405
+ return `./${import_node_path9.default.posix.join(normalized, contractName, "src", "index.js")}`;
1208
1406
  }
1209
1407
  async function removeLegacyBindingStub(cwd, bindingsOutput, contractName) {
1210
- const legacyPath = import_node_path7.default.resolve(cwd, bindingsOutput, `${contractName}.ts`);
1408
+ const legacyPath = import_node_path9.default.resolve(cwd, bindingsOutput, `${contractName}.ts`);
1211
1409
  try {
1212
- await (0, import_promises5.access)(legacyPath);
1213
- await (0, import_promises5.unlink)(legacyPath);
1410
+ await (0, import_promises7.access)(legacyPath);
1411
+ await (0, import_promises7.unlink)(legacyPath);
1214
1412
  return true;
1215
1413
  } catch {
1216
1414
  return false;
@@ -1229,8 +1427,8 @@ async function generateBindings(options) {
1229
1427
  );
1230
1428
  }
1231
1429
  await checkBinary("stellar", "Install Stellar CLI before running caatinga generate.");
1232
- const outputDir = import_node_path7.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
1233
- await (0, import_promises5.mkdir)(outputDir, { recursive: true });
1430
+ const outputDir = import_node_path9.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
1431
+ await (0, import_promises7.mkdir)(outputDir, { recursive: true });
1234
1432
  const result = await runCommand("stellar", [
1235
1433
  "contract",
1236
1434
  "bindings",
@@ -1250,16 +1448,59 @@ async function generateBindings(options) {
1250
1448
  options.config.frontend.bindingsOutput,
1251
1449
  options.contractName
1252
1450
  );
1451
+ const marker = {
1452
+ version: 1,
1453
+ contractId: contractArtifact.contractId,
1454
+ wasmHash: contractArtifact.wasmHash,
1455
+ network: network.name,
1456
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
1457
+ };
1458
+ await writeBindingMarker(outputDir, marker);
1253
1459
  return {
1254
1460
  contractName: options.contractName,
1255
1461
  network,
1256
1462
  outputDir,
1257
1463
  importPath: toBindingImportPath(options.config.frontend.bindingsOutput, options.contractName),
1258
1464
  legacyStubRemoved,
1465
+ marker,
1259
1466
  output: result.all || result.stdout
1260
1467
  };
1261
1468
  }
1262
1469
 
1470
+ // src/contracts/generate-bindings-graph.ts
1471
+ async function generateBindingsGraph(options) {
1472
+ const cwd = options.cwd ?? process.cwd();
1473
+ const network = resolveNetwork(options.config, options.networkName);
1474
+ let targets;
1475
+ if (options.contractName) {
1476
+ targets = [options.contractName];
1477
+ } else if (options.contractNames && options.contractNames.length > 0) {
1478
+ targets = options.contractNames;
1479
+ } else {
1480
+ const artifacts = await readArtifacts(cwd);
1481
+ targets = Object.keys(artifacts.networks[network.name]?.contracts ?? {});
1482
+ if (targets.length === 0) {
1483
+ throw new CaatingaError(
1484
+ `No deployed contracts found on "${network.name}".`,
1485
+ CaatingaErrorCode.ARTIFACT_NOT_FOUND,
1486
+ "Run caatinga deploy before generating bindings, or pass a contract name."
1487
+ );
1488
+ }
1489
+ }
1490
+ const results = [];
1491
+ for (const contractName of targets) {
1492
+ results.push(
1493
+ await generateBindings({
1494
+ config: options.config,
1495
+ contractName,
1496
+ networkName: network.name,
1497
+ cwd
1498
+ })
1499
+ );
1500
+ }
1501
+ return { network, results };
1502
+ }
1503
+
1263
1504
  // src/contracts/invoke-contract.ts
1264
1505
  var INVOKE_SIGNING_FAILURE_REGEX = /xdr processing error: xdr value invalid/i;
1265
1506
  function parseInvokeTarget(target) {
@@ -1332,33 +1573,33 @@ ${error.hint ?? ""}`)) {
1332
1573
  }
1333
1574
 
1334
1575
  // src/templates/create-project-from-template.ts
1335
- var import_promises6 = require("fs/promises");
1336
- var import_node_path8 = __toESM(require("path"), 1);
1337
- var import_zod6 = require("zod");
1576
+ var import_promises8 = require("fs/promises");
1577
+ var import_node_path10 = __toESM(require("path"), 1);
1578
+ var import_zod7 = require("zod");
1338
1579
 
1339
1580
  // src/templates/template-manifest.schema.ts
1340
- var import_zod5 = require("zod");
1581
+ var import_zod6 = require("zod");
1341
1582
  var import_semver3 = __toESM(require("semver"), 1);
1342
1583
  var CURRENT_TEMPLATE_VERSION = 1;
1343
- var TemplateManifestSchema = import_zod5.z.object({
1344
- name: import_zod5.z.string().min(1),
1345
- version: import_zod5.z.string().min(1),
1346
- description: import_zod5.z.string().optional(),
1347
- caatinga: import_zod5.z.object({
1348
- compatibleCore: import_zod5.z.string().min(1),
1349
- templateVersion: import_zod5.z.number().int().positive()
1584
+ var TemplateManifestSchema = import_zod6.z.object({
1585
+ name: import_zod6.z.string().min(1),
1586
+ version: import_zod6.z.string().min(1),
1587
+ description: import_zod6.z.string().optional(),
1588
+ caatinga: import_zod6.z.object({
1589
+ compatibleCore: import_zod6.z.string().min(1),
1590
+ templateVersion: import_zod6.z.number().int().positive()
1350
1591
  }),
1351
- frontend: import_zod5.z.object({
1352
- framework: import_zod5.z.enum(["vite-react", "next", "astro"]),
1353
- packageManager: import_zod5.z.enum(["npm", "pnpm", "yarn", "bun"]).default("npm")
1592
+ frontend: import_zod6.z.object({
1593
+ framework: import_zod6.z.enum(["vite-react", "next", "astro"]),
1594
+ packageManager: import_zod6.z.enum(["npm", "pnpm", "yarn", "bun"]).default("npm")
1354
1595
  }),
1355
- contracts: import_zod5.z.object({
1356
- path: import_zod5.z.string(),
1357
- default: import_zod5.z.string().optional()
1596
+ contracts: import_zod6.z.object({
1597
+ path: import_zod6.z.string(),
1598
+ default: import_zod6.z.string().optional()
1358
1599
  }),
1359
- files: import_zod5.z.object({
1360
- config: import_zod5.z.string().default("caatinga.config.ts"),
1361
- artifacts: import_zod5.z.string().default("caatinga.artifacts.json")
1600
+ files: import_zod6.z.object({
1601
+ config: import_zod6.z.string().default("caatinga.config.ts"),
1602
+ artifacts: import_zod6.z.string().default("caatinga.artifacts.json")
1362
1603
  })
1363
1604
  });
1364
1605
  function defaultCompatibleCoreRange(coreVersion = CAATINGA_CORE_VERSION) {
@@ -1409,10 +1650,10 @@ var TEMPLATE_COPY_EXCLUDED_DIRS = /* @__PURE__ */ new Set([
1409
1650
  ".git"
1410
1651
  ]);
1411
1652
  async function createProjectFromTemplate(options) {
1412
- const targetDir = import_node_path8.default.resolve(options.targetDir);
1413
- const templateDir = import_node_path8.default.resolve(options.templateDir);
1653
+ const targetDir = import_node_path10.default.resolve(options.targetDir);
1654
+ const templateDir = import_node_path10.default.resolve(options.templateDir);
1414
1655
  try {
1415
- await (0, import_promises6.stat)(templateDir);
1656
+ await (0, import_promises8.stat)(templateDir);
1416
1657
  } catch {
1417
1658
  throw new CaatingaError(
1418
1659
  `Template directory was not found: ${templateDir}`,
@@ -1421,8 +1662,8 @@ async function createProjectFromTemplate(options) {
1421
1662
  );
1422
1663
  }
1423
1664
  const manifest = await readTemplateManifest(templateDir);
1424
- await (0, import_promises6.mkdir)(targetDir, { recursive: true });
1425
- await (0, import_promises6.cp)(templateDir, targetDir, {
1665
+ await (0, import_promises8.mkdir)(targetDir, { recursive: true });
1666
+ await (0, import_promises8.cp)(templateDir, targetDir, {
1426
1667
  recursive: true,
1427
1668
  force: false,
1428
1669
  errorOnExist: true,
@@ -1445,9 +1686,9 @@ async function ensureArtifacts(targetDir, projectName) {
1445
1686
  }
1446
1687
  }
1447
1688
  async function readTemplateManifest(templateDir) {
1448
- const manifestPath = import_node_path8.default.join(templateDir, "caatinga.template.json");
1689
+ const manifestPath = import_node_path10.default.join(templateDir, "caatinga.template.json");
1449
1690
  try {
1450
- const rawManifest = await (0, import_promises6.readFile)(manifestPath, "utf8");
1691
+ const rawManifest = await (0, import_promises8.readFile)(manifestPath, "utf8");
1451
1692
  const manifest = TemplateManifestSchema.parse(JSON.parse(rawManifest));
1452
1693
  const compatibilityIssue = getTemplateCompatibilityIssue(manifest);
1453
1694
  if (compatibilityIssue) {
@@ -1469,7 +1710,7 @@ async function readTemplateManifest(templateDir) {
1469
1710
  if (error instanceof CaatingaError) {
1470
1711
  throw error;
1471
1712
  }
1472
- if (error instanceof SyntaxError || error instanceof import_zod6.z.ZodError) {
1713
+ if (error instanceof SyntaxError || error instanceof import_zod7.z.ZodError) {
1473
1714
  throw new CaatingaError(
1474
1715
  "Template manifest is invalid.",
1475
1716
  CaatingaErrorCode.INVALID_TEMPLATE_MANIFEST,
@@ -1480,10 +1721,10 @@ async function readTemplateManifest(templateDir) {
1480
1721
  }
1481
1722
  }
1482
1723
  async function replaceTemplateVariables(dir, projectName) {
1483
- const entries = await (0, import_promises6.readdir)(dir);
1724
+ const entries = await (0, import_promises8.readdir)(dir);
1484
1725
  await Promise.all(entries.map(async (entry) => {
1485
- const entryPath = import_node_path8.default.join(dir, entry);
1486
- const entryStat = await (0, import_promises6.stat)(entryPath);
1726
+ const entryPath = import_node_path10.default.join(dir, entry);
1727
+ const entryStat = await (0, import_promises8.stat)(entryPath);
1487
1728
  if (entryStat.isDirectory()) {
1488
1729
  await replaceTemplateVariables(entryPath, projectName);
1489
1730
  return;
@@ -1491,16 +1732,16 @@ async function replaceTemplateVariables(dir, projectName) {
1491
1732
  if (!isTextTemplateFile(entryPath)) {
1492
1733
  return;
1493
1734
  }
1494
- const content = await (0, import_promises6.readFile)(entryPath, "utf8");
1495
- await (0, import_promises6.writeFile)(entryPath, content.replaceAll("__PROJECT_NAME__", projectName), "utf8");
1735
+ const content = await (0, import_promises8.readFile)(entryPath, "utf8");
1736
+ await (0, import_promises8.writeFile)(entryPath, content.replaceAll("__PROJECT_NAME__", projectName), "utf8");
1496
1737
  }));
1497
1738
  }
1498
1739
  function shouldCopyTemplateEntry(templateDir, source) {
1499
- const relativePath = import_node_path8.default.relative(templateDir, source);
1740
+ const relativePath = import_node_path10.default.relative(templateDir, source);
1500
1741
  if (!relativePath || relativePath === ".") {
1501
1742
  return true;
1502
1743
  }
1503
- return !relativePath.split(import_node_path8.default.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
1744
+ return !relativePath.split(import_node_path10.default.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
1504
1745
  }
1505
1746
  function isTextTemplateFile(filePath) {
1506
1747
  return [
@@ -1512,7 +1753,7 @@ function isTextTemplateFile(filePath) {
1512
1753
  ".tsx",
1513
1754
  ".css",
1514
1755
  ".html"
1515
- ].includes(import_node_path8.default.extname(filePath));
1756
+ ].includes(import_node_path10.default.extname(filePath));
1516
1757
  }
1517
1758
 
1518
1759
  // src/ci/is-transient-testnet-smoke-failure.ts
@@ -1537,6 +1778,8 @@ function isTransientTestnetSmokeFailure(logText) {
1537
1778
  }
1538
1779
  // Annotate the CommonJS export names for ESM import in node:
1539
1780
  0 && (module.exports = {
1781
+ BINDING_MARKER_FILENAME,
1782
+ BindingMarkerSchema,
1540
1783
  CAATINGA_CORE_VERSION,
1541
1784
  CaatingaArtifactsSchema,
1542
1785
  CaatingaConfigSchema,
@@ -1550,13 +1793,18 @@ function isTransientTestnetSmokeFailure(logText) {
1550
1793
  buildDependencyGraph,
1551
1794
  checkBinary,
1552
1795
  checkStellarCliVersion,
1796
+ collectProjectStatus,
1553
1797
  createInitialArtifacts,
1554
1798
  createProjectFromTemplate,
1555
1799
  defineConfig,
1556
1800
  deployContract,
1557
1801
  deployContractGraph,
1802
+ evaluateBindingFreshness,
1803
+ evaluateBindingsFreshness,
1558
1804
  evaluateStellarCliCompatibility,
1805
+ formatCaatingaError,
1559
1806
  generateBindings,
1807
+ generateBindingsGraph,
1560
1808
  invokeContract,
1561
1809
  isTransientTestnetSmokeFailure,
1562
1810
  loadConfig,
@@ -1564,6 +1812,7 @@ function isTransientTestnetSmokeFailure(logText) {
1564
1812
  parseInvokeTarget,
1565
1813
  parseStellarCliVersion,
1566
1814
  readArtifacts,
1815
+ readBindingMarker,
1567
1816
  resolveContract,
1568
1817
  resolveDeployArgs,
1569
1818
  resolveDeployOrder,
@@ -1572,5 +1821,6 @@ function isTransientTestnetSmokeFailure(logText) {
1572
1821
  toCaatingaError,
1573
1822
  updateArtifact,
1574
1823
  validateSourceShape,
1575
- writeArtifacts
1824
+ writeArtifacts,
1825
+ writeBindingMarker
1576
1826
  });