Skip to content

Commit

Permalink
fix: use lazily evaluated process.cwd as a default config value (#150)
Browse files Browse the repository at this point in the history
* fix: use lazily evaluated process.cwd as a default config value

* chore: add changeset
  • Loading branch information
antoine-coulon committed Mar 12, 2024
1 parent 078096e commit 04fe22d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 29 deletions.
22 changes: 22 additions & 0 deletions .changeset/metal-pumas-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"skott": patch
---

This patch fixes the eager evaluation of `cwd` default value from the config preventing [process.chdir](https://nodejs.org/api/process.html#processchdirdirectory)
to work as expected when used before invoking skott's API.

```js
process.chdir('/tmp/somewhere');

// skott is now being executed at the root of "/tmp/somewhere"

const instance = await skott();
```

Note: regarding the generated graph relationships, this is pretty much equivalent as doing `skott({ cwd: "/tmp/somewhere" })`, even though
node paths will be relative and won't have the same values as the later still executes skott from the script location
and not from `/tmp/somewhere`. In other words, using `cwd` parameter will have node paths being relative to skott's script location, while using
`process.chdir` will make skott execute the script from the provided directory.

You can find a real example of the difference between node paths using `process.chdir` and `cwd`: https://github.com/antoine-coulon/skott/issues/149#issuecomment-1989451725
by @mattkindy.
61 changes: 32 additions & 29 deletions packages/skott/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,42 +28,45 @@ const decodeGroupBy: D.Decoder<unknown, (input: string) => string | undefined> =
)
};

const config = D.struct({
entrypoint: withDefaultValue(defaultConfig.entrypoint)(D.string),
includeBaseDir: withDefaultValue(defaultConfig.includeBaseDir)(D.boolean),
incremental: withDefaultValue(defaultConfig.incremental)(D.boolean),
circularMaxDepth: withDefaultValue(defaultConfig.circularMaxDepth)(D.number),
dependencyTracking: withDefaultValue(defaultConfig.dependencyTracking)(
D.struct({
thirdParty: D.boolean,
builtin: D.boolean,
typeOnly: D.boolean
})
),
fileExtensions: withDefaultValue(defaultConfig.fileExtensions)(
D.array(D.literal(".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"))
),
tsConfigPath: withDefaultValue(defaultConfig.tsConfigPath)(D.string),
manifestPath: withDefaultValue(defaultConfig.manifestPath)(D.string),
dependencyResolvers: withDefaultValue(defaultConfig.dependencyResolvers)(
D.array(dependencyResolverDecoder())
),
groupBy: withDefaultValue(defaultConfig.groupBy)(decodeGroupBy),
/**
* External runner only config
*/
cwd: withDefaultValue(process.cwd())(D.string),
verbose: withDefaultValue(false)(D.boolean),
ignorePattern: withDefaultValue("")(D.string)
});
const getConfig = () =>
D.struct({
entrypoint: withDefaultValue(defaultConfig.entrypoint)(D.string),
includeBaseDir: withDefaultValue(defaultConfig.includeBaseDir)(D.boolean),
incremental: withDefaultValue(defaultConfig.incremental)(D.boolean),
circularMaxDepth: withDefaultValue(defaultConfig.circularMaxDepth)(
D.number
),
dependencyTracking: withDefaultValue(defaultConfig.dependencyTracking)(
D.struct({
thirdParty: D.boolean,
builtin: D.boolean,
typeOnly: D.boolean
})
),
fileExtensions: withDefaultValue(defaultConfig.fileExtensions)(
D.array(D.literal(".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"))
),
tsConfigPath: withDefaultValue(defaultConfig.tsConfigPath)(D.string),
manifestPath: withDefaultValue(defaultConfig.manifestPath)(D.string),
dependencyResolvers: withDefaultValue(defaultConfig.dependencyResolvers)(
D.array(dependencyResolverDecoder())
),
groupBy: withDefaultValue(defaultConfig.groupBy)(decodeGroupBy),
/**
* External runner only config
*/
cwd: withDefaultValue(process.cwd())(D.string),
verbose: withDefaultValue(false)(D.boolean),
ignorePattern: withDefaultValue("")(D.string)
});

export function decodeInputConfig<T>(
partialConfig: Option.Option<Partial<SkottConfig<T>>>
) {
return pipe(
partialConfig,
Option.getOrNull,
config.decode,
getConfig().decode,
E.fold((decodeError) => {
throw new Error(`Invalid Skott config. Reason: ${D.draw(decodeError)}`);
}, identity)
Expand Down

0 comments on commit 04fe22d

Please sign in to comment.