Sfoglia il codice sorgente

Add Solana version to arg inputs

Loris Leiva 1 anno fa
parent
commit
868052ec07
9 ha cambiato i file con 71 aggiunte e 46 eliminazioni
  1. 2 8
      index.ts
  2. 3 1
      locales/en-US.json
  3. 3 1
      locales/fr-FR.json
  4. 0 1
      tsconfig.json
  5. 24 15
      utils/getInputs.ts
  6. 18 19
      utils/getLanguage.ts
  7. 2 0
      utils/getLogs.ts
  8. 1 1
      utils/runCommands.ts
  9. 18 0
      utils/solanaCli.ts

+ 2 - 8
index.ts

@@ -3,16 +3,10 @@
 import * as fs from "node:fs";
 import * as path from "node:path";
 
-import { generateKeypair } from "./utils/generateKeypair";
-import {
-  logBanner,
-  logDone,
-  logErrorAndExit,
-  logStep,
-  spinner,
-} from "./utils/getLogs";
+import { logBanner, logDone, logErrorAndExit, logStep } from "./utils/getLogs";
 import { RenderContext, getRenderContext } from "./utils/getRenderContext";
 import { renderTemplate } from "./utils/renderTemplates";
+import { generateKeypair } from "./utils/solanaCli";
 
 (async function init() {
   logBanner();

+ 3 - 1
locales/en-US.json

@@ -47,8 +47,10 @@
     "message": "Rust client crate name:"
   },
   "errors": {
-    "operationCancelled": "Operation cancelled",
     "cannotOverrideDirectory": "Cannot override target directory \"$targetDirectory\". Run with option --force to override.",
+    "invalidSolanaVersion": "Invalid Solana version: $version.",
+    "operationCancelled": "Operation cancelled",
+    "solanaKeygenFailed": "Failed to generate program keypair",
     "solanaKeygenNotFound": "Command `solana-keygen` unavailable. Please install the Solana CLI."
   },
   "defaultToggleOptions": {

+ 3 - 1
locales/fr-FR.json

@@ -50,8 +50,10 @@
     "message": "Ajouter TypeScript\u00a0?"
   },
   "errors": {
-    "operationCancelled": "Operation annulée",
     "cannotOverrideDirectory": "Impossible de remplacer le répertoire cible \"$targetDirectory\". Exécutez avec l'option --force pour remplacer.",
+    "invalidSolanaVersion": "Version Solana invalide\u00a0: $version.",
+    "operationCancelled": "Operation annulée",
+    "solanaKeygenFailed": "La génération de la paire de clés a échoué",
     "solanaKeygenNotFound": "Commande `solana-keygen` indisponible. Veuillez installer Solana dans votre terminal."
   },
   "defaultToggleOptions": {

+ 0 - 1
tsconfig.json

@@ -2,7 +2,6 @@
   "extends": "@tsconfig/node20/tsconfig.json",
   "include": ["index.ts", "utils/**/*"],
   "compilerOptions": {
-    "strict": false,
     "resolveJsonModule": true,
     "moduleResolution": "Bundler",
     "module": "ESNext"

+ 24 - 15
utils/getInputs.ts

@@ -5,6 +5,7 @@ import prompts from "prompts";
 
 import { Language } from "./getLanguage";
 import { kebabCase } from "./stringHelpers";
+import { toMinorSolanaVersion } from "./solanaCli";
 
 export const allClients = ["js", "rust"] as const;
 export type Client = (typeof allClients)[number];
@@ -13,19 +14,20 @@ export type Inputs = {
   jsClient: boolean;
   jsClientPackageName: string;
   organizationName: string;
-  programAddress: string;
+  programAddress?: string;
   programCrateName: string;
   programFramework: "shank" | "anchor";
   programName: string;
   rustClient: boolean;
   rustClientCrateName: string;
   shouldOverride: boolean;
+  solanaVersion?: string;
   targetDirectoryName: string;
   useDefaults: boolean;
 };
 
 export async function getInputs(language: Language): Promise<Inputs> {
-  const argInputs = getInputsFromArgs();
+  const argInputs = getInputsFromArgs(language);
   const defaultInputs = getDefaultInputs(argInputs);
 
   if (argInputs.useDefaults) {
@@ -97,8 +99,8 @@ async function getInputsFromPrompts(
           message: () => {
             const dirForPrompt =
               defaultInputs.targetDirectoryName === "."
-                ? language.shouldOverride.dirForPrompts.current
-                : `${language.shouldOverride.dirForPrompts.target} "${defaultInputs.targetDirectoryName}"`;
+                ? language.shouldOverride.dirForPrompts!.current
+                : `${language.shouldOverride.dirForPrompts!.target} "${defaultInputs.targetDirectoryName}"`;
 
             return `${dirForPrompt} ${language.shouldOverride.message}`;
           },
@@ -140,13 +142,13 @@ async function getInputsFromPrompts(
           initial: 0,
           choices: [
             {
-              title: language.programFramework.selectOptions.shank.title,
-              description: language.programFramework.selectOptions.shank.desc,
+              title: language.programFramework.selectOptions!.shank.title,
+              description: language.programFramework.selectOptions!.shank.desc,
               value: "shank",
             },
             {
-              title: language.programFramework.selectOptions.anchor.title,
-              description: language.programFramework.selectOptions.anchor.desc,
+              title: language.programFramework.selectOptions!.anchor.title,
+              description: language.programFramework.selectOptions!.anchor.desc,
               value: "anchor",
               disabled: true,
             },
@@ -165,8 +167,8 @@ async function getInputsFromPrompts(
           hint: language.clients.hint,
           instructions: language.instructions.multiselect,
           choices: allClients.map((client) => ({
-            title: language.clients.selectOptions[client].title,
-            description: language.clients.selectOptions[client].desc,
+            title: language.clients.selectOptions![client].title,
+            description: language.clients.selectOptions![client].desc,
             value: client,
             selected: true,
           })),
@@ -206,12 +208,12 @@ async function getInputsFromPrompts(
 
     return parsePromptInputs(promptInputs);
   } catch (cancelled) {
-    console.log(cancelled.message);
+    console.log((cancelled as Error).message);
     process.exit(1);
   }
 }
 
-function getInputsFromArgs(): Partial<Inputs> {
+function getInputsFromArgs(language: Language): Partial<Inputs> {
   type ArgInputs = {
     address?: string;
     anchorProgram: boolean;
@@ -221,6 +223,7 @@ function getInputsFromArgs(): Partial<Inputs> {
     organizationName?: string;
     programName?: string;
     shankProgram: boolean;
+    solanaVersion?: string;
     useDefaults: boolean;
     targetDirectoryName?: string;
   };
@@ -228,13 +231,18 @@ function getInputsFromArgs(): Partial<Inputs> {
   function parseArgInputs(argInputs: ArgInputs): Partial<Inputs> {
     const inputs = {} as Partial<Inputs>;
 
-    if (argInputs.targetDirectoryName)
-      inputs.targetDirectoryName = argInputs.targetDirectoryName;
     if (argInputs.address) inputs.programAddress = argInputs.address;
     if (argInputs.organizationName)
       inputs.organizationName = kebabCase(argInputs.organizationName);
     if (argInputs.programName)
       inputs.programName = kebabCase(argInputs.programName);
+    if (argInputs.solanaVersion)
+      inputs.solanaVersion = toMinorSolanaVersion(
+        language,
+        argInputs.solanaVersion
+      );
+    if (argInputs.targetDirectoryName)
+      inputs.targetDirectoryName = argInputs.targetDirectoryName;
     if (argInputs.force) inputs.shouldOverride = true;
     if (argInputs.useDefaults) inputs.useDefaults = true;
 
@@ -267,6 +275,7 @@ function getInputsFromArgs(): Partial<Inputs> {
       "no-clients": { type: "boolean" },
       org: { type: "string" },
       shank: { type: "boolean" },
+      solana: { type: "string" },
     },
     strict: false,
   });
@@ -280,6 +289,7 @@ function getInputsFromArgs(): Partial<Inputs> {
     organizationName: options.org,
     programName: positionals[1],
     shankProgram: options.shank ?? false,
+    solanaVersion: options.solana,
     useDefaults: options.default ?? false,
     targetDirectoryName: positionals[0],
   } as ArgInputs);
@@ -302,7 +312,6 @@ export function getDefaultInputs(partialInputs: Partial<Inputs>): Inputs {
     jsClient: true,
     jsClientPackageName: `@${organizationName}/${programName}`,
     organizationName,
-    programAddress: "MyProgram1111111111111111111111111111111111",
     programCrateName,
     programFramework: "shank",
     programName,

+ 18 - 19
utils/getLanguage.ts

@@ -29,8 +29,10 @@ export interface Language {
   jsClientPackageName: LanguageItem;
   rustClientCrateName: LanguageItem;
   errors: {
-    operationCancelled: string;
     cannotOverrideDirectory: string;
+    invalidSolanaVersion: string;
+    operationCancelled: string;
+    solanaKeygenFailed: string;
     solanaKeygenNotFound: string;
   };
   defaultToggleOptions: {
@@ -56,28 +58,25 @@ export interface Language {
  * @returns locale that linked with correct name
  */
 function linkLocale(locale: string) {
-  let linkedLocale: string;
   try {
     // @ts-ignore
-    linkedLocale = Intl.getCanonicalLocales(locale)[0];
+    switch (Intl.getCanonicalLocales(locale)[0]) {
+      case "zh-TW":
+      case "zh-HK":
+      case "zh-MO":
+        return "zh-Hant";
+        break;
+      case "zh-CN":
+      case "zh-SG":
+        return "zh-Hans";
+        break;
+      default:
+        return locale;
+    }
   } catch (error) {
-    console.log(`${error.toString()}\n`);
+    console.log(`${(error as Error).toString()}\n`);
+    return locale;
   }
-  switch (linkedLocale) {
-    case "zh-TW":
-    case "zh-HK":
-    case "zh-MO":
-      linkedLocale = "zh-Hant";
-      break;
-    case "zh-CN":
-    case "zh-SG":
-      linkedLocale = "zh-Hans";
-      break;
-    default:
-      linkedLocale = locale;
-  }
-
-  return linkedLocale;
 }
 
 function getLocale() {

+ 2 - 0
utils/getLogs.ts

@@ -1,4 +1,6 @@
 import chalk from "chalk";
+
+// @ts-ignore
 import gradient from "gradient-string";
 
 import type { RenderContext } from "./getRenderContext";

+ 1 - 1
utils/runCommands.ts

@@ -5,7 +5,7 @@ export function spawnCommand(
   args: string[] = [],
   options?: SpawnOptions
 ): ChildProcess {
-  return spawn(command, args, options);
+  return spawn(command, args, { ...options });
 }
 
 export async function hasCommand(command: string): Promise<boolean> {

+ 18 - 0
utils/generateKeypair.ts → utils/solanaCli.ts

@@ -1,3 +1,4 @@
+import { Language } from "./getLanguage";
 import { RenderContext } from "./getRenderContext";
 import {
   spawnCommand,
@@ -28,7 +29,24 @@ export async function generateKeypair(ctx: RenderContext): Promise<string> {
 
   // Update the render context with the generated address.
   const address = stdout.join("").match(/pubkey: (\w+)/)?.[1];
+  if (!address) {
+    throw new Error(ctx.language.errors.solanaKeygenFailed);
+  }
+
   ctx.programAddress = address;
 
   return address;
 }
+
+export function toMinorSolanaVersion(
+  language: Language,
+  version: string
+): string {
+  const validVersion = version.match(/^(\d+\.\d+)/);
+  if (!validVersion) {
+    throw new Error(
+      language.errors.invalidSolanaVersion.replace("$version", version)
+    );
+  }
+  return validVersion[0];
+}