index.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #!/usr/bin/env node
  2. import * as fs from 'node:fs';
  3. import * as path from 'node:path';
  4. import { createOrEmptyTargetDirectory } from './utils/filesystem';
  5. import { getInputs } from './utils/inputAll';
  6. import { getLanguage } from './utils/localization';
  7. import { logBanner, logDone, logStep } from './utils/logs';
  8. import { RenderContext, getRenderContext } from './utils/renderContext';
  9. import { renderTemplate } from './utils/renderTemplates';
  10. import { generateKeypair, patchSolanaDependencies } from './utils/solanaCli';
  11. import { detectAnchorVersion } from './utils/versionAnchor';
  12. import { detectRustVersion } from './utils/versionRust';
  13. import { detectSolanaVersion } from './utils/versionSolana';
  14. import { Version } from './utils/versionCore';
  15. (async function init() {
  16. logBanner();
  17. // Get arguments from CLI and prompt.
  18. const language = getLanguage();
  19. const inputs = await getInputs(language);
  20. // Create or empty the target directory.
  21. createOrEmptyTargetDirectory(
  22. language,
  23. inputs.targetDirectoryName,
  24. inputs.shouldOverride
  25. );
  26. // Detect the Solana version.
  27. const solanaVersionDetected = await logStep(
  28. language.infos.detectSolanaVersion,
  29. () => detectSolanaVersion(language)
  30. );
  31. // Detect the Rust version.
  32. const rustVersionDetected = await logStep(
  33. language.infos.detectRustVersion,
  34. () => detectRustVersion()
  35. );
  36. // Detect the Anchor version.
  37. let anchorVersionDetected: Version | undefined;
  38. if (inputs.programFramework === 'anchor') {
  39. anchorVersionDetected = await logStep(
  40. language.infos.detectAnchorVersion,
  41. () => detectAnchorVersion(language)
  42. );
  43. }
  44. // Generate a keypair if needed.
  45. const programAddress =
  46. inputs.programAddress ??
  47. (await logStep(language.infos.generateKeypair, () => {
  48. const outfile = path.join(
  49. process.cwd(),
  50. inputs.targetDirectoryName,
  51. 'program',
  52. 'keypair.json'
  53. );
  54. return generateKeypair(language, outfile);
  55. }));
  56. // Get the args inputs, prompt inputs and computed values.
  57. const ctx = getRenderContext({
  58. language,
  59. inputs,
  60. programAddress,
  61. solanaVersionDetected,
  62. rustVersionDetected,
  63. anchorVersionDetected,
  64. });
  65. // Render the templates.
  66. await logStep(
  67. language.infos.scaffold.replace(
  68. '$targetDirectory',
  69. inputs.targetDirectoryName
  70. ),
  71. async () => {
  72. renderTemplates(ctx);
  73. await patchSolanaDependencies(ctx);
  74. }
  75. );
  76. // Done.
  77. logDone(ctx);
  78. })().catch((e) => console.error(e));
  79. function renderTemplates(ctx: RenderContext) {
  80. const render = (templateName: string) => {
  81. const directory = path.resolve(ctx.templateDirectory, templateName);
  82. if (!fs.existsSync(directory)) return;
  83. renderTemplate(ctx, directory, ctx.targetDirectory);
  84. };
  85. render('base');
  86. render(`${ctx.programFramework}/base`);
  87. if (ctx.clients.length > 0) {
  88. render('clients/base');
  89. render(`${ctx.programFramework}/clients/base`);
  90. }
  91. ctx.clients.forEach((client) => {
  92. render(`clients/${client}`);
  93. render(`${ctx.programFramework}/clients/${client}`);
  94. });
  95. }