Skip to content

Commit 868052e

Browse files
committed
Add Solana version to arg inputs
1 parent 2e21b79 commit 868052e

File tree

9 files changed

+71
-46
lines changed

9 files changed

+71
-46
lines changed

index.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@
33
import * as fs from "node:fs";
44
import * as path from "node:path";
55

6-
import { generateKeypair } from "./utils/generateKeypair";
7-
import {
8-
logBanner,
9-
logDone,
10-
logErrorAndExit,
11-
logStep,
12-
spinner,
13-
} from "./utils/getLogs";
6+
import { logBanner, logDone, logErrorAndExit, logStep } from "./utils/getLogs";
147
import { RenderContext, getRenderContext } from "./utils/getRenderContext";
158
import { renderTemplate } from "./utils/renderTemplates";
9+
import { generateKeypair } from "./utils/solanaCli";
1610

1711
(async function init() {
1812
logBanner();

locales/en-US.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@
4747
"message": "Rust client crate name:"
4848
},
4949
"errors": {
50-
"operationCancelled": "Operation cancelled",
5150
"cannotOverrideDirectory": "Cannot override target directory \"$targetDirectory\". Run with option --force to override.",
51+
"invalidSolanaVersion": "Invalid Solana version: $version.",
52+
"operationCancelled": "Operation cancelled",
53+
"solanaKeygenFailed": "Failed to generate program keypair",
5254
"solanaKeygenNotFound": "Command `solana-keygen` unavailable. Please install the Solana CLI."
5355
},
5456
"defaultToggleOptions": {

locales/fr-FR.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@
5050
"message": "Ajouter TypeScript\u00a0?"
5151
},
5252
"errors": {
53-
"operationCancelled": "Operation annulée",
5453
"cannotOverrideDirectory": "Impossible de remplacer le répertoire cible \"$targetDirectory\". Exécutez avec l'option --force pour remplacer.",
54+
"invalidSolanaVersion": "Version Solana invalide\u00a0: $version.",
55+
"operationCancelled": "Operation annulée",
56+
"solanaKeygenFailed": "La génération de la paire de clés a échoué",
5557
"solanaKeygenNotFound": "Commande `solana-keygen` indisponible. Veuillez installer Solana dans votre terminal."
5658
},
5759
"defaultToggleOptions": {

tsconfig.json

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"extends": "@tsconfig/node20/tsconfig.json",
33
"include": ["index.ts", "utils/**/*"],
44
"compilerOptions": {
5-
"strict": false,
65
"resolveJsonModule": true,
76
"moduleResolution": "Bundler",
87
"module": "ESNext"

utils/getInputs.ts

+24-15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import prompts from "prompts";
55

66
import { Language } from "./getLanguage";
77
import { kebabCase } from "./stringHelpers";
8+
import { toMinorSolanaVersion } from "./solanaCli";
89

910
export const allClients = ["js", "rust"] as const;
1011
export type Client = (typeof allClients)[number];
@@ -13,19 +14,20 @@ export type Inputs = {
1314
jsClient: boolean;
1415
jsClientPackageName: string;
1516
organizationName: string;
16-
programAddress: string;
17+
programAddress?: string;
1718
programCrateName: string;
1819
programFramework: "shank" | "anchor";
1920
programName: string;
2021
rustClient: boolean;
2122
rustClientCrateName: string;
2223
shouldOverride: boolean;
24+
solanaVersion?: string;
2325
targetDirectoryName: string;
2426
useDefaults: boolean;
2527
};
2628

2729
export async function getInputs(language: Language): Promise<Inputs> {
28-
const argInputs = getInputsFromArgs();
30+
const argInputs = getInputsFromArgs(language);
2931
const defaultInputs = getDefaultInputs(argInputs);
3032

3133
if (argInputs.useDefaults) {
@@ -97,8 +99,8 @@ async function getInputsFromPrompts(
9799
message: () => {
98100
const dirForPrompt =
99101
defaultInputs.targetDirectoryName === "."
100-
? language.shouldOverride.dirForPrompts.current
101-
: `${language.shouldOverride.dirForPrompts.target} "${defaultInputs.targetDirectoryName}"`;
102+
? language.shouldOverride.dirForPrompts!.current
103+
: `${language.shouldOverride.dirForPrompts!.target} "${defaultInputs.targetDirectoryName}"`;
102104

103105
return `${dirForPrompt} ${language.shouldOverride.message}`;
104106
},
@@ -140,13 +142,13 @@ async function getInputsFromPrompts(
140142
initial: 0,
141143
choices: [
142144
{
143-
title: language.programFramework.selectOptions.shank.title,
144-
description: language.programFramework.selectOptions.shank.desc,
145+
title: language.programFramework.selectOptions!.shank.title,
146+
description: language.programFramework.selectOptions!.shank.desc,
145147
value: "shank",
146148
},
147149
{
148-
title: language.programFramework.selectOptions.anchor.title,
149-
description: language.programFramework.selectOptions.anchor.desc,
150+
title: language.programFramework.selectOptions!.anchor.title,
151+
description: language.programFramework.selectOptions!.anchor.desc,
150152
value: "anchor",
151153
disabled: true,
152154
},
@@ -165,8 +167,8 @@ async function getInputsFromPrompts(
165167
hint: language.clients.hint,
166168
instructions: language.instructions.multiselect,
167169
choices: allClients.map((client) => ({
168-
title: language.clients.selectOptions[client].title,
169-
description: language.clients.selectOptions[client].desc,
170+
title: language.clients.selectOptions![client].title,
171+
description: language.clients.selectOptions![client].desc,
170172
value: client,
171173
selected: true,
172174
})),
@@ -206,12 +208,12 @@ async function getInputsFromPrompts(
206208

207209
return parsePromptInputs(promptInputs);
208210
} catch (cancelled) {
209-
console.log(cancelled.message);
211+
console.log((cancelled as Error).message);
210212
process.exit(1);
211213
}
212214
}
213215

214-
function getInputsFromArgs(): Partial<Inputs> {
216+
function getInputsFromArgs(language: Language): Partial<Inputs> {
215217
type ArgInputs = {
216218
address?: string;
217219
anchorProgram: boolean;
@@ -221,20 +223,26 @@ function getInputsFromArgs(): Partial<Inputs> {
221223
organizationName?: string;
222224
programName?: string;
223225
shankProgram: boolean;
226+
solanaVersion?: string;
224227
useDefaults: boolean;
225228
targetDirectoryName?: string;
226229
};
227230

228231
function parseArgInputs(argInputs: ArgInputs): Partial<Inputs> {
229232
const inputs = {} as Partial<Inputs>;
230233

231-
if (argInputs.targetDirectoryName)
232-
inputs.targetDirectoryName = argInputs.targetDirectoryName;
233234
if (argInputs.address) inputs.programAddress = argInputs.address;
234235
if (argInputs.organizationName)
235236
inputs.organizationName = kebabCase(argInputs.organizationName);
236237
if (argInputs.programName)
237238
inputs.programName = kebabCase(argInputs.programName);
239+
if (argInputs.solanaVersion)
240+
inputs.solanaVersion = toMinorSolanaVersion(
241+
language,
242+
argInputs.solanaVersion
243+
);
244+
if (argInputs.targetDirectoryName)
245+
inputs.targetDirectoryName = argInputs.targetDirectoryName;
238246
if (argInputs.force) inputs.shouldOverride = true;
239247
if (argInputs.useDefaults) inputs.useDefaults = true;
240248

@@ -267,6 +275,7 @@ function getInputsFromArgs(): Partial<Inputs> {
267275
"no-clients": { type: "boolean" },
268276
org: { type: "string" },
269277
shank: { type: "boolean" },
278+
solana: { type: "string" },
270279
},
271280
strict: false,
272281
});
@@ -280,6 +289,7 @@ function getInputsFromArgs(): Partial<Inputs> {
280289
organizationName: options.org,
281290
programName: positionals[1],
282291
shankProgram: options.shank ?? false,
292+
solanaVersion: options.solana,
283293
useDefaults: options.default ?? false,
284294
targetDirectoryName: positionals[0],
285295
} as ArgInputs);
@@ -302,7 +312,6 @@ export function getDefaultInputs(partialInputs: Partial<Inputs>): Inputs {
302312
jsClient: true,
303313
jsClientPackageName: `@${organizationName}/${programName}`,
304314
organizationName,
305-
programAddress: "MyProgram1111111111111111111111111111111111",
306315
programCrateName,
307316
programFramework: "shank",
308317
programName,

utils/getLanguage.ts

+18-19
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ export interface Language {
2929
jsClientPackageName: LanguageItem;
3030
rustClientCrateName: LanguageItem;
3131
errors: {
32-
operationCancelled: string;
3332
cannotOverrideDirectory: string;
33+
invalidSolanaVersion: string;
34+
operationCancelled: string;
35+
solanaKeygenFailed: string;
3436
solanaKeygenNotFound: string;
3537
};
3638
defaultToggleOptions: {
@@ -56,28 +58,25 @@ export interface Language {
5658
* @returns locale that linked with correct name
5759
*/
5860
function linkLocale(locale: string) {
59-
let linkedLocale: string;
6061
try {
6162
// @ts-ignore
62-
linkedLocale = Intl.getCanonicalLocales(locale)[0];
63+
switch (Intl.getCanonicalLocales(locale)[0]) {
64+
case "zh-TW":
65+
case "zh-HK":
66+
case "zh-MO":
67+
return "zh-Hant";
68+
break;
69+
case "zh-CN":
70+
case "zh-SG":
71+
return "zh-Hans";
72+
break;
73+
default:
74+
return locale;
75+
}
6376
} catch (error) {
64-
console.log(`${error.toString()}\n`);
77+
console.log(`${(error as Error).toString()}\n`);
78+
return locale;
6579
}
66-
switch (linkedLocale) {
67-
case "zh-TW":
68-
case "zh-HK":
69-
case "zh-MO":
70-
linkedLocale = "zh-Hant";
71-
break;
72-
case "zh-CN":
73-
case "zh-SG":
74-
linkedLocale = "zh-Hans";
75-
break;
76-
default:
77-
linkedLocale = locale;
78-
}
79-
80-
return linkedLocale;
8180
}
8281

8382
function getLocale() {

utils/getLogs.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import chalk from "chalk";
2+
3+
// @ts-ignore
24
import gradient from "gradient-string";
35

46
import type { RenderContext } from "./getRenderContext";

utils/runCommands.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export function spawnCommand(
55
args: string[] = [],
66
options?: SpawnOptions
77
): ChildProcess {
8-
return spawn(command, args, options);
8+
return spawn(command, args, { ...options });
99
}
1010

1111
export async function hasCommand(command: string): Promise<boolean> {

utils/generateKeypair.ts utils/solanaCli.ts

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Language } from "./getLanguage";
12
import { RenderContext } from "./getRenderContext";
23
import {
34
spawnCommand,
@@ -28,7 +29,24 @@ export async function generateKeypair(ctx: RenderContext): Promise<string> {
2829

2930
// Update the render context with the generated address.
3031
const address = stdout.join("").match(/pubkey: (\w+)/)?.[1];
32+
if (!address) {
33+
throw new Error(ctx.language.errors.solanaKeygenFailed);
34+
}
35+
3136
ctx.programAddress = address;
3237

3338
return address;
3439
}
40+
41+
export function toMinorSolanaVersion(
42+
language: Language,
43+
version: string
44+
): string {
45+
const validVersion = version.match(/^(\d+\.\d+)/);
46+
if (!validVersion) {
47+
throw new Error(
48+
language.errors.invalidSolanaVersion.replace("$version", version)
49+
);
50+
}
51+
return validVersion[0];
52+
}

0 commit comments

Comments
 (0)