Skip to content

Commit 4c3df49

Browse files
committed
refactor: clean up init script utils
1 parent c67b929 commit 4c3df49

28 files changed

+695
-463
lines changed

.changeset/sixty-roses-learn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'create-solana-dapp': patch
3+
---
4+
5+
clean up init script utils
Lines changed: 14 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,41 @@
11
import { log } from '@clack/prompts'
2-
import { join } from 'node:path'
3-
import { ensureTargetPath } from './ensure-target-path'
42
import { GetArgsResult } from './get-args-result'
5-
import { deleteInitScript, getInitScript, InitScript } from './get-init-script'
63
import { getPackageJson } from './get-package-json'
4+
import { initScriptDelete } from './init-script-delete'
5+
import { initScriptInstructions } from './init-script-instructions'
6+
import { initScriptRename } from './init-script-rename'
7+
import { initScriptKey } from './init-script-schema'
78
import { initScriptVersion } from './init-script-version'
8-
import { searchAndReplace } from './search-and-replace'
99
import { Task, taskFail } from './vendor/clack-tasks'
10-
import { namesValues } from './vendor/names'
1110

1211
export function createAppTaskRunInitScript(args: GetArgsResult): Task {
1312
return {
1413
enabled: !args.skipInit,
1514
title: 'Running init script',
1615
task: async (result) => {
1716
try {
18-
const init = getInitScript(args.targetDirectory)
17+
const { contents } = getPackageJson(args.targetDirectory)
18+
const init = contents[initScriptKey]
1919
if (!init) {
20-
return result({ message: 'Repository does not have an init script' })
20+
return result({ message: 'Init script not found' })
2121
}
2222
if (args.verbose) {
23-
log.warn(`Running init script`)
23+
log.warn(`Init script started`)
2424
}
2525

2626
await initScriptVersion(init.versions, args.verbose)
27-
if (args.verbose) {
28-
log.warn(`initCheckVersion done`)
29-
}
30-
await initRename(args, init, args.verbose)
31-
if (args.verbose) {
32-
log.warn(`initRename done`)
33-
}
3427

35-
const instructions: string[] = (initInstructions(init) ?? [])
28+
await initScriptRename(args, init.rename, args.verbose)
29+
30+
const instructions: string[] = initScriptInstructions(init.instructions, args.verbose)
3631
?.filter(Boolean)
3732
.map((msg) => msg.replace('{pm}', args.packageManager))
3833

39-
if (args.verbose) {
40-
log.warn(`initInstructions done`)
41-
}
42-
deleteInitScript(args.targetDirectory)
43-
if (args.verbose) {
44-
log.warn(`deleteInitScript done`)
45-
}
46-
return result({ message: 'Executed init script', instructions })
34+
initScriptDelete(args)
35+
return result({ message: 'Init script done', instructions })
4736
} catch (error) {
48-
taskFail(`init: Error running init script: ${error}`)
37+
taskFail(`Error running init script: ${error}`)
4938
}
5039
},
5140
}
5241
}
53-
54-
async function initRename(args: GetArgsResult, init: InitScript, verbose: boolean) {
55-
const { contents } = getPackageJson(args.targetDirectory)
56-
// Rename template from package.json to project name throughout the whole project
57-
if (contents.name) {
58-
await searchAndReplace(args.targetDirectory, [contents.name], [args.name], false, verbose)
59-
}
60-
61-
// Return early if there are no renames defined in the init script
62-
if (!init?.rename) {
63-
return
64-
}
65-
66-
// Loop through each word in the rename object
67-
for (const from of Object.keys(init.rename)) {
68-
// Get the 'to' property from the rename object
69-
const to = init.rename[from].to.replace('{{name}}', args.name.replace(/-/g, ''))
70-
71-
// Get the name matrix for the 'from' and the 'to' value
72-
const fromNames = namesValues(from)
73-
const toNames = namesValues(to)
74-
75-
for (const path of init.rename[from].paths) {
76-
const targetPath = join(args.targetDirectory, path)
77-
if (!(await ensureTargetPath(targetPath))) {
78-
console.error(`init-script.rename: target does not exist ${targetPath}`)
79-
continue
80-
}
81-
await searchAndReplace(join(args.targetDirectory, path), fromNames, toNames, args.dryRun)
82-
}
83-
}
84-
}
85-
86-
function initInstructions(init: InitScript) {
87-
return init?.instructions?.length === 0 ? [] : init?.instructions
88-
}

src/utils/create-app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export async function createApp(args: GetArgsResult) {
1111
createAppTaskCloneTemplate(args),
1212
// Install the dependencies
1313
createAppTaskInstallDependencies(args),
14-
// Run the init script define in package.json .init property
14+
// Run the (optional) init script defined in package.json
1515
createAppTaskRunInitScript(args),
1616
// Initialize git repository
1717
createAppTaskInitializeGit(args),

src/utils/get-init-script.ts

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/utils/get-package-json.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { existsSync, readFileSync } from 'node:fs'
22
import { z } from 'zod'
33
import { getPackageJsonPath } from './get-package-json-path'
4+
import { initScriptKey, InitScriptSchema } from './init-script-schema'
45

56
export function getPackageJson(targetDirectory: string): { path: string; contents: PackageJson } {
67
const path = getPackageJsonPath(targetDirectory)
@@ -26,6 +27,7 @@ const PackageJsonSchema = z
2627
.object({
2728
name: z.string().optional(),
2829
scripts: z.record(z.string()).optional(),
30+
[initScriptKey]: InitScriptSchema.optional(),
2931
})
3032
.passthrough()
3133

src/utils/get-version-command.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const commandMap: Record<string, { command: string; name: string; regex: RegExp }> = {
2+
adb: {
3+
command: 'adb --version',
4+
name: 'Adb ',
5+
regex: /Version (\d+\.\d+\.\d+)/,
6+
},
7+
anchor: {
8+
command: 'anchor --version',
9+
name: 'Anchor',
10+
regex: /anchor-cli (\d+\.\d+\.\d+)/,
11+
},
12+
avm: {
13+
command: 'avm --version',
14+
name: 'AVM ',
15+
regex: /avm (\d+\.\d+\.\d+)/,
16+
},
17+
rust: {
18+
command: 'rustc --version',
19+
name: 'Rust ',
20+
regex: /rustc (\d+\.\d+\.\d+)/,
21+
},
22+
solana: {
23+
command: 'solana --version',
24+
name: 'Solana',
25+
regex: /solana-cli (\d+\.\d+\.\d+)/,
26+
},
27+
}
28+
29+
export type VersionCommand = keyof typeof commandMap
30+
31+
export function getVersionCommand(command: VersionCommand): { command: string; name: string; regex: RegExp } {
32+
return commandMap[command]
33+
}
34+
35+
export function getVersionCommandNames(): string[] {
36+
return Object.keys(commandMap)
37+
}

src/utils/get-version-urls.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { VersionCommand } from './get-version-command'
2+
3+
type VersionUrls = {
4+
install?: string
5+
update?: string
6+
}
7+
8+
const urls: Record<VersionCommand, VersionUrls> = {
9+
adb: {
10+
install:
11+
'https://docs.expo.dev/get-started/set-up-your-environment/?platform=android&device=physical&mode=development-build&buildEnv=local',
12+
},
13+
anchor: {
14+
install: 'https://www.anchor-lang.com/docs/installation',
15+
update: 'https://www.anchor-lang.com/release-notes/{required}',
16+
},
17+
solana: {
18+
install: 'https://docs.solana.com/cli/install-solana-cli-tools',
19+
},
20+
}
21+
22+
export function getVersionUrls(command: VersionCommand, required: string): VersionUrls {
23+
const { install, update } = urls[command] ?? {}
24+
25+
return install || update
26+
? {
27+
install: install?.replace('{required}', required),
28+
update: (update ?? install)?.replace('{required}', required),
29+
}
30+
: {}
31+
}

src/utils/get-version.ts

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,8 @@
1+
import { getVersionCommand, VersionCommand } from './get-version-command'
12
import { parseVersion } from './parse-version'
23

3-
export const versionCommands: Record<string, { command: string; name: string; regex: RegExp }> = {
4-
adb: {
5-
command: 'adb --version',
6-
name: 'Adb ',
7-
regex: /Version (\d+\.\d+\.\d+)/,
8-
},
9-
anchor: {
10-
command: 'anchor --version',
11-
name: 'Anchor',
12-
regex: /anchor-cli (\d+\.\d+\.\d+)/,
13-
},
14-
avm: {
15-
command: 'avm --version',
16-
name: 'AVM ',
17-
regex: /avm (\d+\.\d+\.\d+)/,
18-
},
19-
rust: {
20-
command: 'rustc --version',
21-
name: 'Rust ',
22-
regex: /rustc (\d+\.\d+\.\d+)/,
23-
},
24-
solana: {
25-
command: 'solana --version',
26-
name: 'Solana',
27-
regex: /solana-cli (\d+\.\d+\.\d+)/,
28-
},
29-
}
30-
31-
export function getVersion(command: keyof typeof versionCommands): string | undefined {
32-
const cmd = versionCommands[command]
4+
export function getVersion(command: VersionCommand): string | undefined {
5+
const cmd = getVersionCommand(command)
336
if (!cmd) {
347
throw new Error(`Unknown command ${command}`)
358
}

src/utils/init-script-delete.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { log } from '@clack/prompts'
2+
import { writeFileSync } from 'node:fs'
3+
import { GetArgsResult } from './get-args-result'
4+
import { getPackageJson } from './get-package-json'
5+
import { initScriptKey } from './init-script-schema'
6+
7+
export function initScriptDelete(args: GetArgsResult) {
8+
const tag = `initScriptDelete`
9+
const { path, contents } = getPackageJson(args.targetDirectory)
10+
delete contents[initScriptKey]
11+
writeFileSync(path, JSON.stringify(contents, undefined, 2) + '\n')
12+
if (args.verbose) {
13+
log.warn(`${tag}: deleted ${initScriptKey} from package.json`)
14+
}
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { log } from '@clack/prompts'
2+
import { InitScriptInstructions } from './init-script-schema'
3+
4+
export function initScriptInstructions(instructions?: InitScriptInstructions, verbose = false): string[] {
5+
const tag = `initScriptInstructions`
6+
if (!instructions || instructions.length === 0) {
7+
if (verbose) {
8+
log.warn(`${tag}: no instructions found`)
9+
}
10+
return []
11+
}
12+
if (verbose) {
13+
log.warn(`${tag}: ${instructions.length} instructions found`)
14+
}
15+
return instructions
16+
}

0 commit comments

Comments
 (0)