Skip to content

Commit

Permalink
refactor(cli): remove fs-extra and find-up (#4450)
Browse files Browse the repository at this point in the history
* refactor(cli): remove fs-extra

* chore: changeset

* chore: tweaks

* chore: tweaks
  • Loading branch information
tmm authored Dec 9, 2024
1 parent 1ddb373 commit 7b9a6bb
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 185 deletions.
6 changes: 6 additions & 0 deletions .changeset/plenty-ligers-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"create-wagmi": patch
"@wagmi/cli": patch
---

Removed internal usage of `fs-extra`.
4 changes: 1 addition & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@
"dotenv": "^16.3.1",
"dotenv-expand": "^10.0.0",
"esbuild": "^0.19.0",
"escalade": "3.2.0",
"execa": "^8.0.1",
"fdir": "^6.1.1",
"find-up": "^6.3.0",
"fs-extra": "^11.2.0",
"nanospinner": "1.2.2",
"pathe": "^1.1.2",
"picocolors": "^1.0.0",
Expand All @@ -86,7 +85,6 @@
},
"devDependencies": {
"@types/dedent": "^0.7.2",
"@types/fs-extra": "^11.0.4",
"@types/node": "^20.12.10",
"fixturez": "^1.1.0",
"msw": "^2.4.9"
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/generate.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import dedent from 'dedent'
import { readFile } from 'fs-extra'
import { resolve } from 'pathe'
import { afterEach, beforeEach, expect, test, vi } from 'vitest'

import { readFile } from 'node:fs/promises'
import { createFixture, typecheck, watchConsole } from '../../test/utils.js'
import { generate } from './generate.js'

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/generate.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { mkdir, writeFile } from 'node:fs/promises'
import type { Abi } from 'abitype'
import { Abi as AbiSchema } from 'abitype/zod'
import { camelCase } from 'change-case'
import type { ChokidarOptions, FSWatcher } from 'chokidar'
import { watch } from 'chokidar'
import { default as dedent } from 'dedent'
import { default as fs } from 'fs-extra'
import { basename, dirname, resolve } from 'pathe'
import pc from 'picocolors'
import { type Address, getAddress } from 'viem'
Expand Down Expand Up @@ -396,9 +396,9 @@ async function writeContracts({
// Format and write output
const cwd = process.cwd()
const outPath = resolve(cwd, filename)
await fs.ensureDir(dirname(outPath))
await mkdir(dirname(outPath), { recursive: true })
const formatted = await format(code)
await fs.writeFile(outPath, formatted)
await writeFile(outPath, formatted)
}

function getBannerContent({ name }: { name: string }) {
Expand Down
26 changes: 13 additions & 13 deletions packages/cli/src/commands/init.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { default as fs } from 'fs-extra'
import { existsSync } from 'node:fs'
import { mkdir, readFile } from 'node:fs/promises'
import { resolve } from 'pathe'
import { afterEach, beforeEach, expect, test, vi } from 'vitest'

import { createFixture, watchConsole } from '../../test/utils.js'
import { defaultConfig } from '../config.js'

import { init } from './init.js'

let console: ReturnType<typeof watchConsole>
Expand All @@ -23,8 +23,8 @@ test('creates config file', async () => {

const configFile = await init()

expect(fs.existsSync(configFile)).toBeTruthy()
expect(await fs.readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
expect(existsSync(configFile)).toBeTruthy()
expect(await readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
"// @ts-check
/** @type {import('@wagmi/cli').Config} */
Expand Down Expand Up @@ -53,8 +53,8 @@ test('parameters: config', async () => {
config: 'foo.config.ts',
})

expect(fs.existsSync(configFile)).toBeTruthy()
expect(await fs.readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
expect(existsSync(configFile)).toBeTruthy()
expect(await readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
"// @ts-check
/** @type {import('@wagmi/cli').Config} */
Expand Down Expand Up @@ -90,8 +90,8 @@ test('parameters: content', async () => {
},
})

expect(fs.existsSync(configFile)).toBeTruthy()
expect(await fs.readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
expect(existsSync(configFile)).toBeTruthy()
expect(await readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
"import { defineConfig } from '@wagmi/cli'
export default defineConfig({
Expand All @@ -114,14 +114,14 @@ test('parameters: root', async () => {
const { dir } = await createFixture()
const spy = vi.spyOn(process, 'cwd')
spy.mockImplementation(() => dir)
fs.mkdir(resolve(dir, 'foo'))
mkdir(resolve(dir, 'foo'))

const configFile = await init({
root: 'foo/',
})

expect(fs.existsSync(configFile)).toBeTruthy()
expect(await fs.readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
expect(existsSync(configFile)).toBeTruthy()
expect(await readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
"// @ts-check
/** @type {import('@wagmi/cli').Config} */
Expand Down Expand Up @@ -152,8 +152,8 @@ test('behavior: creates config file in TypeScript format', async () => {

const configFile = await init()

expect(fs.existsSync(configFile)).toBeTruthy()
expect(await fs.readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
expect(existsSync(configFile)).toBeTruthy()
expect(await readFile(configFile, 'utf-8')).toMatchInlineSnapshot(`
"import { defineConfig } from '@wagmi/cli'
export default defineConfig({
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { writeFile } from 'node:fs/promises'
import dedent from 'dedent'
import { default as fs } from 'fs-extra'
import { relative, resolve } from 'pathe'
import pc from 'picocolors'
import { z } from 'zod'
Expand Down Expand Up @@ -85,7 +85,7 @@ export async function init(options: Init = {}) {
}

const formatted = await format(content)
await fs.writeFile(outPath, formatted)
await writeFile(outPath, formatted)
spinner.success()
logger.success(
`Config created at ${pc.gray(relative(process.cwd(), outPath))}`,
Expand Down
64 changes: 39 additions & 25 deletions packages/cli/src/plugins/fetch.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mkdir, rm, writeFile } from 'node:fs/promises'
import { homedir } from 'node:os'
import { default as fs } from 'fs-extra'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'

Expand Down Expand Up @@ -72,26 +72,33 @@ test('aborts request', () => {

test('reads from cache', async () => {
const cacheDir = `${homedir}/.wagmi-cli/plugins/fetch/cache`
await fs.ensureDir(cacheDir)
await mkdir(cacheDir, { recursive: true })

const contract = {
name: 'WagmiMintExample',
address: timeoutAddress,
} as const
const cacheKey = JSON.stringify(contract)
const cacheFilePath = `${cacheDir}/${cacheKey}.json`
await fs.writeJSON(cacheFilePath, {
abi: [
await writeFile(
cacheFilePath,
JSON.stringify(
{
inputs: [],
name: 'mint',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
abi: [
{
inputs: [],
name: 'mint',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
],
timestamp: Date.now() + 30_000,
},
],
timestamp: Date.now() + 30_000,
})
null,
2,
),
)

await expect(
fetch({
Expand All @@ -117,31 +124,38 @@ test('reads from cache', async () => {
]
`)

await fs.rm(cacheDir, { recursive: true })
await rm(cacheDir, { recursive: true })
})

test('fails and reads from cache', async () => {
const cacheDir = `${homedir}/.wagmi-cli/plugins/fetch/cache`
await fs.ensureDir(cacheDir)
await mkdir(cacheDir, { recursive: true })

const contract = {
name: 'WagmiMintExample',
address: timeoutAddress,
} as const
const cacheKey = JSON.stringify(contract)
const cacheFilePath = `${cacheDir}/${cacheKey}.json`
await fs.writeJSON(cacheFilePath, {
abi: [
await writeFile(
cacheFilePath,
JSON.stringify(
{
inputs: [],
name: 'mint',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
abi: [
{
inputs: [],
name: 'mint',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
],
timestamp: Date.now() - 30_000,
},
],
timestamp: Date.now() - 30_000,
})
null,
2,
),
)

await expect(
fetch({
Expand All @@ -168,5 +182,5 @@ test('fails and reads from cache', async () => {
]
`)

await fs.rm(cacheDir, { recursive: true })
await rm(cacheDir, { recursive: true })
})
15 changes: 10 additions & 5 deletions packages/cli/src/plugins/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { homedir } from 'node:os'
import { default as fs } from 'fs-extra'
import { join } from 'pathe'

import type { Abi } from 'abitype'
Expand Down Expand Up @@ -70,14 +70,16 @@ export function fetch(config: FetchConfig): FetchResult {
return {
async contracts() {
const cacheDir = join(homedir(), '.wagmi-cli/plugins/fetch/cache')
await fs.ensureDir(cacheDir)
await mkdir(cacheDir, { recursive: true })

const timestamp = Date.now() + cacheDuration
const contracts = []
for (const contract of contractConfigs) {
const cacheKey = getCacheKey({ contract })
const cacheFilePath = join(cacheDir, `${cacheKey}.json`)
const cachedFile = await fs.readJSON(cacheFilePath).catch(() => null)
const cachedFile = JSON.parse(
await readFile(cacheFilePath, 'utf8').catch(() => 'null'),
)

let abi: Abi | undefined
if (cachedFile?.timestamp > Date.now()) abi = cachedFile.abi
Expand All @@ -97,11 +99,14 @@ export function fetch(config: FetchConfig): FetchResult {
clearTimeout(timeout)

abi = await parse({ response })
await fs.writeJSON(cacheFilePath, { abi, timestamp })
await writeFile(
cacheFilePath,
`${JSON.stringify({ abi, timestamp }, undefined, 2)}\n`,
)
} catch (error) {
try {
// Attempt to read from cache if fetch fails.
abi = (await fs.readJSON(cacheFilePath)).abi
abi = JSON.parse(await readFile(cacheFilePath, 'utf8')).abi
} catch {}
if (!abi) throw error
}
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/plugins/foundry.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { existsSync } from 'node:fs'
import { readFile } from 'node:fs/promises'
import dedent from 'dedent'
import { execa, execaCommandSync } from 'execa'
import { fdir } from 'fdir'
import { default as fs } from 'fs-extra'

import { basename, extname, join, resolve } from 'pathe'
import pc from 'picocolors'
import { z } from 'zod'
Expand Down Expand Up @@ -125,7 +125,7 @@ export function foundry(config: FoundryConfig = {}): FoundryResult {
}

async function getContract(artifactPath: string) {
const artifact = await fs.readJSON(artifactPath)
const artifact = await JSON.parse(await readFile(artifactPath, 'utf8'))
return {
abi: artifact.abi,
address: (deployments as Record<string, ContractConfig['address']>)[
Expand Down Expand Up @@ -173,7 +173,7 @@ export function foundry(config: FoundryConfig = {}): FoundryResult {
async contracts() {
if (clean) await execa(forgeExecutable, ['clean', '--root', project])
if (build) await execa(forgeExecutable, ['build', '--root', project])
if (!fs.pathExistsSync(artifactsDirectory))
if (!existsSync(artifactsDirectory))
throw new Error('Artifacts not found.')

const artifactPaths = await getArtifactPaths(artifactsDirectory)
Expand All @@ -188,7 +188,7 @@ export function foundry(config: FoundryConfig = {}): FoundryResult {
name: 'Foundry',
async validate() {
// Check that project directory exists
if (!(await fs.pathExists(project)))
if (!existsSync(project))
throw new Error(`Foundry project ${pc.gray(config.project)} not found.`)

// Ensure forge is installed
Expand Down
9 changes: 5 additions & 4 deletions packages/cli/src/plugins/hardhat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { existsSync } from 'node:fs'
import { readFile } from 'node:fs/promises'
import { execa } from 'execa'
import { fdir } from 'fdir'
import { default as fs } from 'fs-extra'
import { basename, extname, join, resolve } from 'pathe'
import pc from 'picocolors'

Expand Down Expand Up @@ -84,7 +85,7 @@ export function hardhat(config: HardhatConfig): HardhatResult {
}

async function getContract(artifactPath: string) {
const artifact = await fs.readJSON(artifactPath)
const artifact = await JSON.parse(await readFile(artifactPath, 'utf8'))
return {
abi: artifact.abi,
address: deployments[artifact.contractName],
Expand Down Expand Up @@ -126,7 +127,7 @@ export function hardhat(config: HardhatConfig): HardhatResult {
).split(' ')
await execa(command!, options, { cwd: project })
}
if (!fs.pathExistsSync(artifactsDirectory))
if (!existsSync(artifactsDirectory))
throw new Error('Artifacts not found.')

const artifactPaths = await getArtifactPaths(artifactsDirectory)
Expand All @@ -141,7 +142,7 @@ export function hardhat(config: HardhatConfig): HardhatResult {
name: 'Hardhat',
async validate() {
// Check that project directory exists
if (!(await fs.pathExists(project)))
if (!existsSync(project))
throw new Error(`Hardhat project ${pc.gray(project)} not found.`)

// Check that `hardhat` is installed
Expand Down
Loading

0 comments on commit 7b9a6bb

Please sign in to comment.