utils.mjs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import 'zx/globals';
  2. import { parse as parseToml } from '@iarna/toml';
  3. $.verbose = true;
  4. process.env.FORCE_COLOR = 3;
  5. process.env.CARGO_TERM_COLOR = 'always';
  6. export const workingDirectory = (await $`pwd`.quiet()).toString().trim();
  7. export function getAllProgramIdls() {
  8. return getAllProgramFolders().map((folder) =>
  9. path.join(workingDirectory, folder, 'idl.json')
  10. );
  11. }
  12. export function getExternalProgramOutputDir() {
  13. const config = getCargoMetadata()?.solana?.['external-programs-output'];
  14. return path.join(workingDirectory, config ?? 'target/deploy');
  15. }
  16. export function getExternalProgramAddresses() {
  17. const addresses = getProgramFolders().flatMap(
  18. (folder) => getCargoMetadata(folder)?.solana?.['program-dependencies'] ?? []
  19. );
  20. return Array.from(new Set(addresses));
  21. }
  22. export function getExternalAccountAddresses() {
  23. const addresses = getProgramFolders().flatMap(
  24. (folder) => getCargoMetadata(folder)?.solana?.['account-dependencies'] ?? []
  25. );
  26. return Array.from(new Set(addresses));
  27. }
  28. let didWarnAboutMissingPrograms = false;
  29. export function getProgramFolders() {
  30. let programs;
  31. if (process.env.PROGRAMS) {
  32. try {
  33. programs = JSON.parse(process.env.PROGRAMS);
  34. } catch (error) {
  35. programs = process.env.PROGRAMS.split(/\s+/);
  36. }
  37. } else {
  38. programs = getAllProgramFolders();
  39. }
  40. const filteredPrograms = programs.filter((program) =>
  41. fs.existsSync(path.join(workingDirectory, program))
  42. );
  43. if (
  44. filteredPrograms.length !== programs.length &&
  45. !didWarnAboutMissingPrograms
  46. ) {
  47. didWarnAboutMissingPrograms = true;
  48. programs
  49. .filter((program) => !filteredPrograms.includes(program))
  50. .forEach((program) => {
  51. echo(chalk.yellow(`Program not found: ${workingDirectory}/${program}`));
  52. });
  53. }
  54. return filteredPrograms;
  55. }
  56. export function getAllProgramFolders() {
  57. return getCargo().workspace.members.filter((member) =>
  58. (getCargo(member).lib?.['crate-type'] ?? []).includes('cdylib')
  59. );
  60. }
  61. export function getCargo(folder) {
  62. return parseToml(
  63. fs.readFileSync(
  64. path.join(workingDirectory, folder ? folder : '.', 'Cargo.toml'),
  65. 'utf8'
  66. )
  67. );
  68. }
  69. export function getCargoMetadata(folder) {
  70. const cargo = getCargo(folder);
  71. return folder ? cargo?.package?.metadata : cargo?.workspace?.metadata;
  72. }
  73. export function getSolanaVersion() {
  74. return getCargoMetadata()?.cli?.solana;
  75. }
  76. export function getToolchain(operation) {
  77. return getCargoMetadata()?.toolchains?.[operation];
  78. }
  79. export function getToolchainArgument(operation) {
  80. const channel = getToolchain(operation);
  81. return channel ? `+${channel}` : '';
  82. }
  83. export function cliArguments() {
  84. return process.argv.slice(3);
  85. }
  86. export function popArgument(args, arg) {
  87. const index = args.indexOf(arg);
  88. if (index >= 0) {
  89. args.splice(index, 1);
  90. }
  91. return index >= 0;
  92. }
  93. export function partitionArguments(args, delimiter) {
  94. const index = args.indexOf(delimiter);
  95. return index >= 0
  96. ? [args.slice(0, index), args.slice(index + 1)]
  97. : [args, []];
  98. }
  99. export async function getInstalledSolanaVersion() {
  100. try {
  101. const { stdout } = await $`solana --version`.quiet();
  102. return stdout.match(/(\d+\.\d+\.\d+)/)?.[1];
  103. } catch (error) {
  104. return '';
  105. }
  106. }