Skip to content

Commit

Permalink
✨ Feat: Add support for json configs (#757)
Browse files Browse the repository at this point in the history
## Description

Added support for tevm.json configs for configuring tevm

## Testing

Explain the quality checks that have been done on the code changes

## Additional Information

- [ ] I read the [contributing docs](../docs/contributing.md) (if this
is your first contribution)

Your ENS/address:



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a new configuration option `cacheDir` to specify the
directory for build cache storage.
  - Added support for JSON configurations in Tevm.

- **Bug Fixes**
- Fixed a bug in the `parseJson` function to return type `unknown` for
more flexible JSON parsing.

- **Documentation**
- Updated documentation to reflect the new `cacheDir` option and error
class renaming.

- **Refactor**
- Renamed error class `NoPluginFoundError` to
`NoPluginInTsConfigFoundError` for clearer error messaging.
- Enhanced `loadConfig` function to support loading JSON configurations.
- Adjusted `mergeConfigs` function to handle `debug` and `cacheDir`
properties.

- **Style**
- Updated `vitest.config.ts` to refine the `branches` threshold value
for code coverage.

- **Tests**
- Modified test cases to account for new `cacheDir` property and error
class renaming.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Will Cory <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 17, 2023
1 parent a9be500 commit d1affad
Show file tree
Hide file tree
Showing 31 changed files with 242 additions and 97 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-bats-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tevm/config": minor
---

Added support for json configs in Tevm
5 changes: 5 additions & 0 deletions .changeset/wild-bears-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tevm/effect": patch
---

Fixed bug in @tevm/effect where return type of parseJson was hardcoded instead of unknown
10 changes: 5 additions & 5 deletions bundler/config/docs/classes/loadConfig.LoadConfigError.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,17 @@ Error.constructor

#### Defined in

[bundler/config/src/loadConfig.js:36](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L36)
[bundler/config/src/loadConfig.js:40](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L40)

## Properties

### \_tag

**\_tag**: ``"ConfigFnThrowError"`` \| ``"InvalidConfigError"`` \| ``"FoundryNotFoundError"`` \| ``"FoundryConfigError"`` \| ``"InvalidRemappingsError"`` \| ``"FailedToReadConfigError"`` \| ``"ParseJsonError"`` \| ``"NoPluginFoundError"``
**\_tag**: ``"InvalidConfigError"`` \| ``"FoundryNotFoundError"`` \| ``"FoundryConfigError"`` \| ``"InvalidRemappingsError"`` \| ``"FailedToReadConfigError"`` \| ``"InvalidJsonConfigError"`` \| ``"ParseJsonError"`` \| ``"NoPluginInTsConfigFoundError"``

#### Defined in

[bundler/config/src/loadConfig.js:31](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L31)
[bundler/config/src/loadConfig.js:35](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L35)

___

Expand Down Expand Up @@ -99,15 +99,15 @@ ___

### name

**name**: ``"ConfigFnThrowError"`` \| ``"InvalidConfigError"`` \| ``"FoundryNotFoundError"`` \| ``"FoundryConfigError"`` \| ``"InvalidRemappingsError"`` \| ``"FailedToReadConfigError"`` \| ``"ParseJsonError"`` \| ``"NoPluginFoundError"``
**name**: ``"InvalidConfigError"`` \| ``"FoundryNotFoundError"`` \| ``"FoundryConfigError"`` \| ``"InvalidRemappingsError"`` \| ``"FailedToReadConfigError"`` \| ``"InvalidJsonConfigError"`` \| ``"ParseJsonError"`` \| ``"NoPluginInTsConfigFoundError"``

#### Overrides

Error.name

#### Defined in

[bundler/config/src/loadConfig.js:27](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L27)
[bundler/config/src/loadConfig.js:31](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L31)

___

Expand Down
6 changes: 3 additions & 3 deletions bundler/config/docs/modules/loadConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

### LoadConfigErrorType

Ƭ **LoadConfigErrorType**\<\>: `LoadTsConfigError` \| `GetTevmConfigFromTsConfigError` \| `LoadFoundryConfigError`
Ƭ **LoadConfigErrorType**\<\>: `LoadTsConfigError` \| `GetTevmConfigFromTsConfigError` \| `LoadFoundryConfigError` \| `InvalidJsonConfigError`

#### Defined in

[bundler/config/src/loadConfig.js:16](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L16)
[bundler/config/src/loadConfig.js:20](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L20)

## Functions

Expand Down Expand Up @@ -57,4 +57,4 @@ runPromise(loadConfig('./tsconfig.json')).pipe(

#### Defined in

[bundler/config/src/loadConfig.js:61](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L61)
[bundler/config/src/loadConfig.js:65](https://github.com/evmts/tevm-monorepo/blob/main/bundler/config/src/loadConfig.js#L65)
4 changes: 2 additions & 2 deletions bundler/config/docs/modules/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ When resolved with defaults it is a [ResolvedCompilerConfig](types.md#resolvedco
| `cacheDir?` | `string` | Location of the tevm cache folder |
| `debug?` | `boolean` | If debug is true tevm will write the .d.ts files in the ts server and publish extra debug info to a debug file |
| `foundryProject?` | `boolean` \| `string` | If set to true it will resolve forge remappings and libs Set to "path/to/forge/executable" to use a custom forge executable |
`libs?` | readonly `string`[] | Sets directories to search for solidity imports in Read automatically for forge projects if forge: true |
| `libs?` | readonly `string`[] | Sets directories to search for solidity imports in Read autoamtically for forge projects if forge: true |
| `remappings?` | `ReadonlyRecord`\<`string`\> | Remap the location of contracts |

#### Defined in
Expand Down Expand Up @@ -120,7 +120,7 @@ See [CompilerConfig](types.md#compilerconfig)
| `cacheDir` | `string` | Location of the tevm cache folder |
| `debug?` | `boolean` | If debug is true tevm will write the .d.ts files in the ts server and publish extra debug info to a debug file |
| `foundryProject` | `boolean` \| `string` | If set to true it will resolve forge remappings and libs Set to "path/to/forge/executable" to use a custom forge executable |
`libs` | readonly `string`[] | Sets directories to search for solidity imports in Read automatically for forge projects if forge: true |
| `libs` | readonly `string`[] | Sets directories to search for solidity imports in Read autoamtically for forge projects if forge: true |
| `remappings` | `ReadonlyRecord`\<`string`\> | Remap the location of contracts |

#### Defined in
Expand Down
2 changes: 1 addition & 1 deletion bundler/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"src"
],
"scripts": {
"all": "bun run lint && bun run format && bun run build:dist && bun run build:types && bun run test:run && bun run generate:docs",
"all": "bun run lint && bun run format && bun run build:dist && bun run build:types && bun run dev:run && bun run test:run && bun run generate:docs",
"build": "nx run-many --targets=build:dist,build:types --projects=@tevm/config ",
"build:dist": "bun run tsup",
"build:types": "bun run tsc --emitDeclarationOnly --declaration --declarationMap",
Expand Down
2 changes: 1 addition & 1 deletion bundler/config/rome.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"enabled": true
},
"files": {
"ignore": ["coverage", "node_modules", "dist", "artifacts"]
"ignore": ["coverage", "node_modules", "dist", "artifacts", "src/fixtures"]
},
"formatter": {
"enabled": true,
Expand Down
4 changes: 3 additions & 1 deletion bundler/config/scripts/runFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export const validFixtureNames = [
'configFnThrows',
'invalid',
'invalidJson',
'js',
'legacy',
'legacy-js',
'jsonc',
'withFoundry',
] as const
Expand All @@ -47,6 +48,7 @@ export const validFixtureValidator = z.union([
z.literal(validFixtureNames[4]),
z.literal(validFixtureNames[5]),
z.literal(validFixtureNames[6]),
z.literal(validFixtureNames[7]),
])

const layer = Logger.replace(Logger.defaultLogger, logger)
Expand Down
4 changes: 4 additions & 0 deletions bundler/config/src/fixtures/basic/tevm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"cacheDir": ".cache",
"libs": ["mylib"]
}
1 change: 1 addition & 0 deletions bundler/config/src/fixtures/invalid/tevm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["invalid", "tsconfig.json"]
4 changes: 0 additions & 4 deletions bundler/config/src/fixtures/invalid/tsconfig.json

This file was deleted.

26 changes: 26 additions & 0 deletions bundler/config/src/fixtures/legacy/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"extends": "@tevm/tsconfig/base.json",
"compilerOptions": {
"composite": true,
"outDir": "types",
"skipLibCheck": true,
"plugins": [
{
"name": "@tevm/ts-plugin",
"cacheDir": ".cache",
"libs": [
"mylib"
]
}
],
"paths": {
"@/*": [
"./*"
]
}
},
"include": [
"src",
"src/**/*.json"
]
}
6 changes: 2 additions & 4 deletions bundler/config/src/fixtures/withFoundry/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
"skipLibCheck": true,
"plugins": [
{
"name": "@tevm/ts-plugin",
// should load the remappings
"foundryProject": true
"name": "@tevm/ts-plugin"
}
]
},
"include": [
"src",
"src/**/*.json"
]
}
}
4 changes: 4 additions & 0 deletions bundler/config/src/fixtures/withFoundry/tevm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
// should load the remappings
"foundryProject": true
}
90 changes: 90 additions & 0 deletions bundler/config/src/json/loadJsonConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {
InvalidConfigError,
validateUserConfig,
} from '../config/validateUserConfig.js'
import { parseJson } from '@tevm/effect'
import {
catchTag,
die,
fail,
flatMap,
logDebug,
tap,
try as tryEffect,
} from 'effect/Effect'
import { readFileSync } from 'fs'
import * as path from 'path'

export class FailedToReadConfigError extends Error {
/**
* @type {'FailedToReadConfigError'}
*/
_tag = 'FailedToReadConfigError'
/**
* @param {string} configFilePath
* @param {object} [options]
* @param {unknown} [options.cause]
*/
constructor(configFilePath, options) {
super(`Failed to find ${configFilePath}/tevm.json`, options)
}
}

/**
* TypeError thrown when the user provided config factory is incorrectly typed
* @internal
*/
export class InvalidJsonConfigError extends TypeError {
/**
* @type {'InvalidJsonConfigError'}
* @override
*/
name = 'InvalidJsonConfigError'
/**
* @type {'InvalidJsonConfigError'}
*/
_tag = 'InvalidJsonConfigError'
/**
* @param {object} [options]
* @param {unknown} [options.cause]
*/
constructor(options) {
super('Invalid tsconfig.json detected', options)
}
}

/**
* @typedef {import("@tevm/effect").ParseJsonError | FailedToReadConfigError | InvalidJsonConfigError | InvalidConfigError} LoadJsonConfigError
* @internal
*/

/**
* Synchronously loads a Tevm config from the given path
* @param {string} configFilePath
* @returns {import("effect/Effect").Effect<never, LoadJsonConfigError, import('../types.js').CompilerConfig>} the contents of the tsconfig.json file
* @internal
*/
export const loadJsonConfig = (configFilePath) => {
const tevmConfigPath = path.join(configFilePath, 'tevm.json')
return tryEffect({
try: () => readFileSync(tevmConfigPath, 'utf8'),
catch: (cause) => new FailedToReadConfigError(configFilePath, { cause }),
}).pipe(
flatMap(parseJson),
catchTag('ParseJsonError', (cause) =>
fail(new InvalidJsonConfigError({ cause })),
),
flatMap((cfg) =>
validateUserConfig(
() => /** @type {import('../types.js').CompilerConfig}*/ (cfg),
),
),
// it can't throw. Could clean this up via making validateUserConfig take a config instead of a factory
catchTag('ConfigFnThrowError', (e) => die(e)),
tap((tsConfig) =>
logDebug(
`loading tsconfig from ${configFilePath}: ${JSON.stringify(tsConfig)}`,
),
),
)
}
33 changes: 26 additions & 7 deletions bundler/config/src/loadConfig.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { mergeConfigs, withDefaults } from './config/index.js'
import { loadFoundryConfig } from './foundry/index.js'
import {
InvalidJsonConfigError,
loadJsonConfig,
} from './json/loadJsonConfig.js'
import { getTevmConfigFromTsConfig, loadTsConfig } from './tsconfig/index.js'
import { logAllErrors } from '@tevm/effect'
import {
Expand All @@ -13,7 +17,7 @@ import {
} from 'effect/Effect'

/**
* @typedef {import("./tsconfig/index.js").LoadTsConfigError | import("./tsconfig/index.js").GetTevmConfigFromTsConfigError | import("./foundry/index.js").LoadFoundryConfigError} LoadConfigErrorType
* @typedef {import("./tsconfig/index.js").LoadTsConfigError | import("./tsconfig/index.js").GetTevmConfigFromTsConfigError | import("./foundry/index.js").LoadFoundryConfigError | InvalidJsonConfigError} LoadConfigErrorType
*/

/**
Expand Down Expand Up @@ -59,13 +63,29 @@ ${underlyingError.message}`,
* ```
*/
export const loadConfig = (configFilePath) => {
const userConfigEffect = logDebug(
const tsConfig = logDebug(
`loadConfig: loading tsConfig at ${JSON.stringify(configFilePath)}`,
).pipe(flatMap(() => loadTsConfig(configFilePath)))
const userConfig = logDebug(
`loadConfig: loading userConfig at ${JSON.stringify(configFilePath)}`,
).pipe(
flatMap(() => loadTsConfig(configFilePath)),
flatMap((tsConfig) => getTevmConfigFromTsConfig(tsConfig, configFilePath)),
flatMap(() => loadJsonConfig(configFilePath)),
catchTags({
// for backwards compatibility attempt to read config from tsconfig
FailedToReadConfigError: (e) =>
tsConfig.pipe(
flatMap((tsConfig) =>
getTevmConfigFromTsConfig(tsConfig, configFilePath),
),
catchTags({
// if there is no fallback config we want to throw the original error
NoPluginInTsConfigFoundError: () => fail(e),
LoadTsConfigError: () => fail(e),
}),
),
}),
)
const foundryConfigEffect = flatMap(userConfigEffect, (userConfig) => {
const foundryConfig = flatMap(userConfig, (userConfig) => {
return loadFoundryConfig(userConfig.foundryProject, configFilePath)
})
/**
Expand All @@ -75,7 +95,7 @@ export const loadConfig = (configFilePath) => {
const handleError = (error) => {
return fail(new LoadConfigError(configFilePath, error))
}
return all([userConfigEffect, foundryConfigEffect]).pipe(
return all([userConfig, foundryConfig]).pipe(
tap(([userConfig, foundryConfig]) =>
logDebug(
`loadConfig: Config read CompilerConfigs ${JSON.stringify({
Expand All @@ -101,7 +121,6 @@ export const loadConfig = (configFilePath) => {
FoundryNotFoundError: handleError,
InvalidConfigError: handleError,
InvalidRemappingsError: handleError,
NoPluginFoundError: handleError,
ParseJsonError: handleError,
}),
tap((config) =>
Expand Down
Loading

1 comment on commit d1affad

@vercel
Copy link

@vercel vercel bot commented on d1affad Dec 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

evmts-docs – ./

evmts-docs-evmts.vercel.app
evmts.dev
evmts-docs-git-main-evmts.vercel.app

Please sign in to comment.