Sfoglia il codice sorgente

Add library names to CLI options (#78)

Loris Leiva 1 anno fa
parent
commit
f360459b0b

+ 5 - 0
.changeset/curly-olives-lie.md

@@ -0,0 +1,5 @@
+---
+"create-solana-program": patch
+---
+
+Add library names to CLI options

+ 5 - 0
README.md

@@ -67,6 +67,11 @@ pnpm create solana-program --solana 1.18
 
 # Force the creation of the program repository even if the directory is not empty.
 pnpm create solana-program --force
+
+# Override the library names.
+pnpm create solana-program --program-crate-name acme-counter
+pnpm create solana-program --rust-client-crate-name acme-counter-client
+pnpm create solana-program --js-client-package-name @acme/counter
 ```
 
 ## Existing Anchor programs

+ 5 - 5
index.ts

@@ -4,16 +4,16 @@ import * as fs from 'node:fs';
 import * as path from 'node:path';
 
 import { createOrEmptyTargetDirectory } from './utils/filesystem';
-import { getInputs } from './utils/inputs';
+import { getInputs } from './utils/inputAll';
 import { getLanguage } from './utils/localization';
 import { logBanner, logDone, logStep } from './utils/logs';
 import { RenderContext, getRenderContext } from './utils/renderContext';
 import { renderTemplate } from './utils/renderTemplates';
 import { generateKeypair, patchSolanaDependencies } from './utils/solanaCli';
-import { detectAnchorVersion } from './utils/version-anchor';
-import { detectRustVersion } from './utils/version-rust';
-import { detectSolanaVersion } from './utils/version-solana';
-import { Version } from './utils/version-core';
+import { detectAnchorVersion } from './utils/versionAnchor';
+import { detectRustVersion } from './utils/versionRust';
+import { detectSolanaVersion } from './utils/versionSolana';
+import { Version } from './utils/versionCore';
 
 (async function init() {
   logBanner();

+ 1 - 1
template/base/Cargo.toml.njk

@@ -9,8 +9,8 @@ members = ["program"]
 {% if programFramework === 'anchor' %}
 [profile.release]
 overflow-checks = true
-{% endif %}
 
+{% endif %}
 [workspace.metadata.cli]
 {% if programFramework === 'anchor' %}
 anchor = "{{ anchorVersion.full }}"

+ 15 - 0
utils/inputAll.ts

@@ -0,0 +1,15 @@
+import { getInputsFromArgs } from './inputArgs';
+import { getDefaultInputs, type Inputs } from './inputCore';
+import { getInputsFromPrompts } from './inputPrompts';
+import type { Language } from './localization';
+
+export async function getInputs(language: Language): Promise<Inputs> {
+  const argInputs = getInputsFromArgs();
+  const defaultInputs = getDefaultInputs(argInputs);
+
+  if (argInputs.useDefaults) {
+    return defaultInputs;
+  }
+
+  return getInputsFromPrompts(language, argInputs);
+}

+ 101 - 0
utils/inputArgs.ts

@@ -0,0 +1,101 @@
+import { parseArgs } from 'node:util';
+
+import { type Inputs } from './inputCore';
+import { kebabCase } from './strings';
+
+type ArgInputs = {
+  address?: string;
+  anchorProgram: boolean;
+  clients: Array<'js' | 'rust'>;
+  force: boolean;
+  jsClientPackageName?: string;
+  noClients: boolean;
+  organizationName?: string;
+  programCrateName?: string;
+  programName?: string;
+  rustClientCrateName?: string;
+  rustVersion?: string;
+  shankProgram: boolean;
+  solanaVersion?: string;
+  useDefaults: boolean;
+  targetDirectoryName?: string;
+};
+
+export function getInputsFromArgs(): Partial<Inputs> {
+  const args = process.argv.slice(2);
+  const { values: options, positionals } = parseArgs({
+    args,
+    options: {
+      address: { type: 'string' },
+      anchor: { type: 'boolean' },
+      client: { type: 'string', multiple: true },
+      default: { type: 'boolean', short: 'd' },
+      force: { type: 'boolean' },
+      'js-client-package-name': { type: 'string' },
+      'no-clients': { type: 'boolean' },
+      org: { type: 'string' },
+      'program-crate-name': { type: 'string' },
+      rust: { type: 'string' },
+      'rust-client-crate-name': { type: 'string' },
+      shank: { type: 'boolean' },
+      solana: { type: 'string' },
+    },
+    strict: false,
+  });
+
+  return parseArgInputs({
+    address: options.address,
+    anchorProgram: options.anchor ?? false,
+    clients: options.client,
+    force: options.force ?? false,
+    jsClientPackageName: options['js-client-package-name'],
+    noClients: options['no-clients'] ?? false,
+    organizationName: options.org,
+    programCrateName: options['program-crate-name'],
+    programName: positionals[1],
+    rustClientCrateName: options['rust-client-crate-name'],
+    rustVersion: options.rust,
+    shankProgram: options.shank ?? false,
+    solanaVersion: options.solana,
+    useDefaults: options.default ?? false,
+    targetDirectoryName: positionals[0],
+  } as ArgInputs);
+}
+
+function parseArgInputs(argInputs: ArgInputs): Partial<Inputs> {
+  const inputs = {} as Partial<Inputs>;
+
+  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.rustVersion) inputs.rustVersion = argInputs.rustVersion;
+  if (argInputs.solanaVersion) inputs.solanaVersion = argInputs.solanaVersion;
+  if (argInputs.targetDirectoryName)
+    inputs.targetDirectoryName = argInputs.targetDirectoryName;
+  if (argInputs.jsClientPackageName)
+    inputs.jsClientPackageName = argInputs.jsClientPackageName;
+  if (argInputs.programCrateName)
+    inputs.programCrateName = argInputs.programCrateName;
+  if (argInputs.rustClientCrateName)
+    inputs.rustClientCrateName = argInputs.rustClientCrateName;
+  if (argInputs.force) inputs.shouldOverride = true;
+  if (argInputs.useDefaults) inputs.useDefaults = true;
+
+  if (argInputs.anchorProgram) {
+    inputs.programFramework = 'anchor';
+  } else if (argInputs.shankProgram) {
+    inputs.programFramework = 'shank';
+  }
+
+  if (argInputs.noClients) {
+    inputs.jsClient = false;
+    inputs.rustClient = false;
+  } else if (argInputs.clients) {
+    inputs.jsClient = argInputs.clients.includes('js');
+    inputs.rustClient = argInputs.clients.includes('rust');
+  }
+
+  return inputs;
+}

+ 80 - 0
utils/inputCore.ts

@@ -0,0 +1,80 @@
+import * as fs from 'node:fs';
+
+import { Language } from './localization';
+import { kebabCase } from './strings';
+
+export const allClients = ['js', 'rust'] as const;
+export type Client = (typeof allClients)[number];
+
+export type Inputs = {
+  jsClient: boolean;
+  jsClientPackageName: string;
+  organizationName: string;
+  programAddress?: string;
+  programCrateName: string;
+  programFramework: 'shank' | 'anchor';
+  programName: string;
+  rustClient: boolean;
+  rustClientCrateName: string;
+  rustVersion?: string;
+  shouldOverride: boolean;
+  solanaVersion?: string;
+  targetDirectoryName: string;
+  useDefaults: boolean;
+};
+
+// export async function getInputs(language: Language): Promise<Inputs> {
+//   const argInputs = getInputsFromArgs();
+//   const defaultInputs = getDefaultInputs(argInputs);
+
+//   if (argInputs.useDefaults) {
+//     return defaultInputs;
+//   }
+
+//   return getInputsFromPrompts(language, argInputs);
+// }
+
+export function getDefaultInputs(partialInputs: Partial<Inputs>): Inputs {
+  const organizationName = kebabCase(
+    partialInputs.organizationName ?? 'solana-program'
+  );
+  const parsedTargetDirectoryName = partialInputs.targetDirectoryName
+    ? partialInputs.targetDirectoryName.split('/').pop()
+    : '';
+  const programName = kebabCase(
+    partialInputs.programName ?? (parsedTargetDirectoryName || 'my-program')
+  );
+  const programCrateName =
+    partialInputs.programCrateName ?? `${organizationName}-${programName}`;
+
+  return {
+    jsClient: true,
+    jsClientPackageName: `@${organizationName}/${programName}`,
+    organizationName,
+    programCrateName,
+    programFramework: 'shank',
+    programName,
+    rustClient: true,
+    rustClientCrateName: `${programCrateName}-client`,
+    shouldOverride: false,
+    targetDirectoryName: programName,
+    useDefaults: false,
+    ...partialInputs,
+  };
+}
+
+function canSkipEmptying(dir: fs.PathLike) {
+  if (!fs.existsSync(dir)) {
+    return true;
+  }
+
+  const files = fs.readdirSync(dir);
+  if (files.length === 0) {
+    return true;
+  }
+  if (files.length === 1 && files[0] === '.git') {
+    return true;
+  }
+
+  return false;
+}

+ 200 - 0
utils/inputPrompts.ts

@@ -0,0 +1,200 @@
+import chalk from 'chalk';
+import * as fs from 'node:fs';
+import prompts from 'prompts';
+
+import { Language } from './localization';
+import { allClients, getDefaultInputs, Inputs } from './inputCore';
+
+type PromptInputs = {
+  programName?: string;
+  shouldOverride?: boolean;
+  organizationName?: string;
+  programCrateName?: string;
+  programFramework?: 'shank' | 'anchor';
+  clients?: Array<'js' | 'rust'>;
+  jsClientPackageName?: string;
+  rustClientCrateName?: string;
+};
+
+export async function getInputsFromPrompts(
+  language: Language,
+  argInputs: Partial<Inputs>
+): Promise<Inputs> {
+  let defaultInputs = getDefaultInputs(argInputs);
+
+  try {
+    const promptInputs: PromptInputs = await prompts(
+      [
+        {
+          name: 'programName',
+          type: argInputs.programName ? null : 'text',
+          message: language.programName.message,
+          initial: () => defaultInputs.programName,
+        },
+        {
+          name: 'shouldOverride',
+          type: (_, values) => {
+            if (argInputs.shouldOverride) return null;
+            defaultInputs = parsePromptInputs(values, argInputs);
+            return canSkipEmptying(defaultInputs.targetDirectoryName)
+              ? null
+              : 'toggle';
+          },
+          message: () => {
+            const dirForPrompt =
+              defaultInputs.targetDirectoryName === '.'
+                ? language.shouldOverride.dirForPrompts!.current
+                : `${language.shouldOverride.dirForPrompts!.target} "${defaultInputs.targetDirectoryName}"`;
+
+            return `${dirForPrompt} ${language.shouldOverride.message}`;
+          },
+          initial: false,
+          active: language.defaultToggleOptions.active,
+          inactive: language.defaultToggleOptions.inactive,
+        },
+        {
+          name: 'overwriteChecker',
+          type: (_, values) => {
+            if (values.shouldOverride === false) {
+              throw new Error(
+                chalk.red('✖') + ` ${language.errors.operationCancelled}`
+              );
+            }
+            return null;
+          },
+        },
+        {
+          name: 'organizationName',
+          type: argInputs.organizationName ? null : 'text',
+          message: language.organizationName.message,
+          initial: () => defaultInputs.organizationName,
+        },
+        {
+          name: 'programCrateName',
+          type: argInputs.programCrateName ? null : 'text',
+          message: language.programCrateName.message,
+          initial: (_, values) => {
+            defaultInputs = parsePromptInputs(values, argInputs);
+            return defaultInputs.programCrateName;
+          },
+        },
+        {
+          name: 'programFramework',
+          type: argInputs.programFramework ? null : 'select',
+          message: language.programFramework.message,
+          hint: language.instructions.select,
+          initial: 0,
+          choices: [
+            {
+              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,
+              value: 'anchor',
+            },
+          ],
+        },
+        {
+          name: 'clients',
+          type: () => {
+            const hasSelectedClients = [
+              argInputs.jsClient,
+              argInputs.rustClient,
+            ].every((client) => typeof client === 'boolean');
+            return hasSelectedClients ? null : 'multiselect';
+          },
+          message: language.clients.message,
+          hint: language.clients.hint,
+          instructions: language.instructions.multiselect,
+          choices: allClients.map((client) => ({
+            title: language.clients.selectOptions![client].title,
+            description: language.clients.selectOptions![client].desc,
+            value: client,
+            selected: true,
+          })),
+        },
+        {
+          name: 'jsClientPackageName',
+          type: (_, values) => {
+            if (argInputs.jsClientPackageName) return null;
+            defaultInputs = parsePromptInputs(values, argInputs);
+            return defaultInputs.jsClient ? 'text' : null;
+          },
+          message: language.jsClientPackageName.message,
+          initial: () => defaultInputs.jsClientPackageName,
+        },
+        {
+          name: 'rustClientCrateName',
+          type: (_, values) => {
+            if (argInputs.rustClientCrateName) return null;
+            defaultInputs = parsePromptInputs(values, argInputs);
+            return defaultInputs.rustClient ? 'text' : null;
+          },
+          message: language.rustClientCrateName.message,
+          initial: () => defaultInputs.rustClientCrateName,
+        },
+      ],
+      {
+        onCancel: () => {
+          throw new Error(
+            chalk.red('✖') + ` ${language.errors.operationCancelled}`
+          );
+        },
+      }
+    );
+
+    // Add a line break after the prompts
+    console.log('');
+
+    return parsePromptInputs(promptInputs, argInputs);
+  } catch (cancelled) {
+    console.log((cancelled as Error).message);
+    process.exit(1);
+  }
+}
+
+function parsePromptInputs(
+  promptInputs: PromptInputs,
+  argInputs: Partial<Inputs>
+): Inputs {
+  const inputs = {} as Partial<Inputs>;
+
+  if (promptInputs.programName) inputs.programName = promptInputs.programName;
+  if (promptInputs.shouldOverride !== undefined)
+    inputs.shouldOverride = promptInputs.shouldOverride;
+  if (promptInputs.organizationName)
+    inputs.organizationName = promptInputs.organizationName;
+  if (promptInputs.programCrateName)
+    inputs.programCrateName = promptInputs.programCrateName;
+  if (promptInputs.programFramework)
+    inputs.programFramework = promptInputs.programFramework;
+  if (promptInputs.clients !== undefined) {
+    inputs.jsClient = promptInputs.clients.includes('js');
+    inputs.rustClient = promptInputs.clients.includes('rust');
+  }
+  if (promptInputs.jsClientPackageName)
+    inputs.jsClientPackageName = promptInputs.jsClientPackageName;
+  if (promptInputs.rustClientCrateName)
+    inputs.rustClientCrateName = promptInputs.rustClientCrateName;
+
+  return getDefaultInputs({ ...argInputs, ...inputs });
+}
+
+function canSkipEmptying(dir: fs.PathLike) {
+  if (!fs.existsSync(dir)) {
+    return true;
+  }
+
+  const files = fs.readdirSync(dir);
+  if (files.length === 0) {
+    return true;
+  }
+  if (files.length === 1 && files[0] === '.git') {
+    return true;
+  }
+
+  return false;
+}

+ 0 - 340
utils/inputs.ts

@@ -1,340 +0,0 @@
-import chalk from 'chalk';
-import * as fs from 'node:fs';
-import { parseArgs } from 'node:util';
-import prompts from 'prompts';
-
-import { Language } from './localization';
-import { kebabCase } from './strings';
-
-export const allClients = ['js', 'rust'] as const;
-export type Client = (typeof allClients)[number];
-
-export type Inputs = {
-  jsClient: boolean;
-  jsClientPackageName: string;
-  organizationName: string;
-  programAddress?: string;
-  programCrateName: string;
-  programFramework: 'shank' | 'anchor';
-  programName: string;
-  rustClient: boolean;
-  rustClientCrateName: string;
-  rustVersion?: string;
-  shouldOverride: boolean;
-  solanaVersion?: string;
-  targetDirectoryName: string;
-  useDefaults: boolean;
-};
-
-export async function getInputs(language: Language): Promise<Inputs> {
-  const argInputs = getInputsFromArgs();
-  const defaultInputs = getDefaultInputs(argInputs);
-
-  if (argInputs.useDefaults) {
-    return defaultInputs;
-  }
-
-  return getInputsFromPrompts(language, argInputs);
-}
-
-async function getInputsFromPrompts(
-  language: Language,
-  argInputs: Partial<Inputs>
-): Promise<Inputs> {
-  type PromptInputs = {
-    programName?: string;
-    shouldOverride?: boolean;
-    organizationName?: string;
-    programCrateName?: string;
-    programFramework?: 'shank' | 'anchor';
-    clients?: Array<'js' | 'rust'>;
-    jsClientPackageName?: string;
-    rustClientCrateName?: string;
-  };
-
-  let defaultInputs = getDefaultInputs(argInputs);
-
-  function parsePromptInputs(promptInputs: PromptInputs): Inputs {
-    const inputs = {} as Partial<Inputs>;
-
-    if (promptInputs.programName) inputs.programName = promptInputs.programName;
-    if (promptInputs.shouldOverride !== undefined)
-      inputs.shouldOverride = promptInputs.shouldOverride;
-    if (promptInputs.organizationName)
-      inputs.organizationName = promptInputs.organizationName;
-    if (promptInputs.programCrateName)
-      inputs.programCrateName = promptInputs.programCrateName;
-    if (promptInputs.programFramework)
-      inputs.programFramework = promptInputs.programFramework;
-    if (promptInputs.clients !== undefined) {
-      inputs.jsClient = promptInputs.clients.includes('js');
-      inputs.rustClient = promptInputs.clients.includes('rust');
-    }
-    if (promptInputs.jsClientPackageName)
-      inputs.jsClientPackageName = promptInputs.jsClientPackageName;
-    if (promptInputs.rustClientCrateName)
-      inputs.rustClientCrateName = promptInputs.rustClientCrateName;
-
-    return getDefaultInputs({ ...argInputs, ...inputs });
-  }
-
-  try {
-    const promptInputs: PromptInputs = await prompts(
-      [
-        {
-          name: 'programName',
-          type: argInputs.programName ? null : 'text',
-          message: language.programName.message,
-          initial: () => defaultInputs.programName,
-        },
-        {
-          name: 'shouldOverride',
-          type: (_, values) => {
-            if (argInputs.shouldOverride) return null;
-            defaultInputs = parsePromptInputs(values);
-            return canSkipEmptying(defaultInputs.targetDirectoryName)
-              ? null
-              : 'toggle';
-          },
-          message: () => {
-            const dirForPrompt =
-              defaultInputs.targetDirectoryName === '.'
-                ? language.shouldOverride.dirForPrompts!.current
-                : `${language.shouldOverride.dirForPrompts!.target} "${defaultInputs.targetDirectoryName}"`;
-
-            return `${dirForPrompt} ${language.shouldOverride.message}`;
-          },
-          initial: false,
-          active: language.defaultToggleOptions.active,
-          inactive: language.defaultToggleOptions.inactive,
-        },
-        {
-          name: 'overwriteChecker',
-          type: (_, values) => {
-            if (values.shouldOverride === false) {
-              throw new Error(
-                chalk.red('✖') + ` ${language.errors.operationCancelled}`
-              );
-            }
-            return null;
-          },
-        },
-        {
-          name: 'organizationName',
-          type: argInputs.organizationName ? null : 'text',
-          message: language.organizationName.message,
-          initial: () => defaultInputs.organizationName,
-        },
-        {
-          name: 'programCrateName',
-          type: argInputs.programCrateName ? null : 'text',
-          message: language.programCrateName.message,
-          initial: (_, values) => {
-            defaultInputs = parsePromptInputs(values);
-            return defaultInputs.programCrateName;
-          },
-        },
-        {
-          name: 'programFramework',
-          type: argInputs.programFramework ? null : 'select',
-          message: language.programFramework.message,
-          hint: language.instructions.select,
-          initial: 0,
-          choices: [
-            {
-              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,
-              value: 'anchor',
-            },
-          ],
-        },
-        {
-          name: 'clients',
-          type: () => {
-            const hasSelectedClients = [
-              argInputs.jsClient,
-              argInputs.rustClient,
-            ].every((client) => typeof client === 'boolean');
-            return hasSelectedClients ? null : 'multiselect';
-          },
-          message: language.clients.message,
-          hint: language.clients.hint,
-          instructions: language.instructions.multiselect,
-          choices: allClients.map((client) => ({
-            title: language.clients.selectOptions![client].title,
-            description: language.clients.selectOptions![client].desc,
-            value: client,
-            selected: true,
-          })),
-        },
-        {
-          name: 'jsClientPackageName',
-          type: (_, values) => {
-            if (argInputs.jsClientPackageName) return null;
-            defaultInputs = parsePromptInputs(values);
-            return defaultInputs.jsClient ? 'text' : null;
-          },
-          message: language.jsClientPackageName.message,
-          initial: () => defaultInputs.jsClientPackageName,
-        },
-        {
-          name: 'rustClientCrateName',
-          type: (_, values) => {
-            if (argInputs.rustClientCrateName) return null;
-            defaultInputs = parsePromptInputs(values);
-            return defaultInputs.rustClient ? 'text' : null;
-          },
-          message: language.rustClientCrateName.message,
-          initial: () => defaultInputs.rustClientCrateName,
-        },
-      ],
-      {
-        onCancel: () => {
-          throw new Error(
-            chalk.red('✖') + ` ${language.errors.operationCancelled}`
-          );
-        },
-      }
-    );
-
-    // Add a line break after the prompts
-    console.log('');
-
-    return parsePromptInputs(promptInputs);
-  } catch (cancelled) {
-    console.log((cancelled as Error).message);
-    process.exit(1);
-  }
-}
-
-function getInputsFromArgs(): Partial<Inputs> {
-  type ArgInputs = {
-    address?: string;
-    anchorProgram: boolean;
-    clients: Array<'js' | 'rust'>;
-    force: boolean;
-    noClients: boolean;
-    organizationName?: string;
-    programName?: string;
-    rustVersion?: string;
-    shankProgram: boolean;
-    solanaVersion?: string;
-    useDefaults: boolean;
-    targetDirectoryName?: string;
-  };
-
-  function parseArgInputs(argInputs: ArgInputs): Partial<Inputs> {
-    const inputs = {} as Partial<Inputs>;
-
-    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.rustVersion) inputs.rustVersion = argInputs.rustVersion;
-    if (argInputs.solanaVersion) inputs.solanaVersion = argInputs.solanaVersion;
-    if (argInputs.targetDirectoryName)
-      inputs.targetDirectoryName = argInputs.targetDirectoryName;
-    if (argInputs.force) inputs.shouldOverride = true;
-    if (argInputs.useDefaults) inputs.useDefaults = true;
-
-    if (argInputs.anchorProgram) {
-      inputs.programFramework = 'anchor';
-    } else if (argInputs.shankProgram) {
-      inputs.programFramework = 'shank';
-    }
-
-    if (argInputs.noClients) {
-      inputs.jsClient = false;
-      inputs.rustClient = false;
-    } else if (argInputs.clients) {
-      inputs.jsClient = argInputs.clients.includes('js');
-      inputs.rustClient = argInputs.clients.includes('rust');
-    }
-
-    return inputs;
-  }
-
-  const args = process.argv.slice(2);
-  const { values: options, positionals } = parseArgs({
-    args,
-    options: {
-      address: { type: 'string' },
-      anchor: { type: 'boolean' },
-      client: { type: 'string', multiple: true },
-      default: { type: 'boolean', short: 'd' },
-      force: { type: 'boolean' },
-      'no-clients': { type: 'boolean' },
-      org: { type: 'string' },
-      rust: { type: 'string' },
-      shank: { type: 'boolean' },
-      solana: { type: 'string' },
-    },
-    strict: false,
-  });
-
-  return parseArgInputs({
-    address: options.address,
-    anchorProgram: options.anchor ?? false,
-    clients: options.client,
-    force: options.force ?? false,
-    noClients: options['no-clients'] ?? false,
-    organizationName: options.org,
-    programName: positionals[1],
-    rustVersion: options.rust,
-    shankProgram: options.shank ?? false,
-    solanaVersion: options.solana,
-    useDefaults: options.default ?? false,
-    targetDirectoryName: positionals[0],
-  } as ArgInputs);
-}
-
-export function getDefaultInputs(partialInputs: Partial<Inputs>): Inputs {
-  const organizationName = kebabCase(
-    partialInputs.organizationName ?? 'solana-program'
-  );
-  const parsedTargetDirectoryName = partialInputs.targetDirectoryName
-    ? partialInputs.targetDirectoryName.split('/').pop()
-    : '';
-  const programName = kebabCase(
-    partialInputs.programName ?? (parsedTargetDirectoryName || 'my-program')
-  );
-  const programCrateName =
-    partialInputs.programCrateName ?? `${organizationName}-${programName}`;
-
-  return {
-    jsClient: true,
-    jsClientPackageName: `@${organizationName}/${programName}`,
-    organizationName,
-    programCrateName,
-    programFramework: 'shank',
-    programName,
-    rustClient: true,
-    rustClientCrateName: `${programCrateName}-client`,
-    shouldOverride: false,
-    targetDirectoryName: programName,
-    useDefaults: false,
-    ...partialInputs,
-  };
-}
-
-function canSkipEmptying(dir: fs.PathLike) {
-  if (!fs.existsSync(dir)) {
-    return true;
-  }
-
-  const files = fs.readdirSync(dir);
-  if (files.length === 0) {
-    return true;
-  }
-  if (files.length === 1 && files[0] === '.git') {
-    return true;
-  }
-
-  return false;
-}

+ 5 - 5
utils/renderContext.ts

@@ -1,16 +1,16 @@
 import * as path from 'node:path';
 
-import { Client, Inputs, allClients } from './inputs';
+import { Client, Inputs, allClients } from './inputCore';
 import { Language } from './localization';
 import {
   PackageManager,
   getPackageManager,
   getPackageManagerCommand,
 } from './packageManager';
-import { ResolvedVersion, Version } from './version-core';
-import { resolveRustVersion } from './version-rust';
-import { resolveAnchorVersion } from './version-anchor';
-import { resolveSolanaVersion } from './version-solana';
+import { ResolvedVersion, Version } from './versionCore';
+import { resolveRustVersion } from './versionRust';
+import { resolveAnchorVersion } from './versionAnchor';
+import { resolveSolanaVersion } from './versionSolana';
 
 export type RenderContext = Omit<
   Inputs,

+ 1 - 1
utils/solanaCli.ts

@@ -6,7 +6,7 @@ import {
   spawnCommand,
   waitForCommand,
 } from './commands';
-import { VersionWithoutPatch } from './version-core';
+import { VersionWithoutPatch } from './versionCore';
 
 export async function patchSolanaDependencies(
   ctx: Pick<RenderContext, 'solanaVersion' | 'targetDirectory'>

+ 1 - 1
utils/version-anchor.ts → utils/versionAnchor.ts

@@ -5,7 +5,7 @@ import {
   getVersionFromStdout,
   ResolvedVersion,
   Version,
-} from './version-core';
+} from './versionCore';
 
 export async function detectAnchorVersion(
   language: Language

+ 0 - 0
utils/version-core.ts → utils/versionCore.ts


+ 1 - 1
utils/version-rust.ts → utils/versionRust.ts

@@ -9,7 +9,7 @@ import {
   ResolvedVersion,
   Version,
   VersionWithoutPatch,
-} from './version-core';
+} from './versionCore';
 
 export async function detectRustVersion(): Promise<Version | undefined> {
   const hasRustc = await hasCommand('rustc');

+ 1 - 1
utils/version-solana.ts → utils/versionSolana.ts

@@ -6,7 +6,7 @@ import {
   getVersionFromStdout,
   ResolvedVersion,
   Version,
-} from './version-core';
+} from './versionCore';
 
 export async function detectSolanaVersion(
   language: Language