Skip to content

Commit

Permalink
add "sourceDialects"
Browse files Browse the repository at this point in the history
Fix: #66
  • Loading branch information
isaacs committed Jul 7, 2024
1 parent 297dd5a commit 3b20fff
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 24 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 1.18

- Add `sourceDialects`

# 1.17

- Add `module` field if a top-level `esm` export exists for
Expand Down
34 changes: 28 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,10 +874,12 @@ for code hints in VSCode, neovim, tests, etc.
### Loading from Source
If you are using tshy in a monorepo environment, you can
configure TypeScript (and other tools) to resolve to the _source_
files rather than built artifacts by telling them to use the
`"source"` export condition.
To facilitate jumping directly to source definitions in some
tools, you can define custom `"sourceDialects"` which will be
resolved to the original TypeScript source. These custom dialects
can then be configured to allow build tools (such as tsc) and
editors (such as VS Code and neovim/CoC) to jump directly to
source definitions.
For example, in editors such as VS Code and neovim/CoC that use
the TypeScript language services, you can give them a `tsconfig`
Expand All @@ -886,7 +888,17 @@ that contains this:
```json
{
"compilerOptions": {
"customConditions": ["source"]
"customConditions": ["@my-project/source"]
}
}
```
And then add this to your `package.json` file:
```json
{
"tshy": {
"sourceDialects": ["@my-project/source"]
}
}
```
Expand All @@ -896,7 +908,7 @@ like [`tsx`](https://npm.im/tsx) that can load TypeScript
directly, you can specify it like this:
```bash
node --import=tsx --conditions=source ./script.ts
node --import=tsx --conditions=@my-project/source ./script.ts
```
Other TypeScript-aware tools may have other mechanisms for
Expand All @@ -905,6 +917,16 @@ more information.
See also: "Live Dev", above.
#### Why not just use `"source"` as the target?
Tshy always builds the `"source"` target referencing the location
of the TypeScript file that was built. However, this can cause
problems if tools use this to resolve into dependencies, which
may not ship their TypeScript source.
But if you can configure your tools to _only_ use this import
condition outside of `node_modules`, then it's safe to use.

### Custom `project`

Configure `tshy.project` if you want tshy to extend from a custom
Expand Down
13 changes: 13 additions & 0 deletions src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ const getExports = (
continue
}

/* c8 ignore next - already guarded */
if (s === null) continue

const impTarget = getImpTarget(s, polyfills)
const reqTarget = getReqTarget(s, polyfills)

Expand All @@ -116,10 +119,12 @@ const getExports = (
liveDev ?
{
source,
...getSourceDialects(source, c),
default: target,
}
: {
source,
...getSourceDialects(source, c),
types: target.replace(/\.js$/, '.d.ts'),
default: target,
}
Expand All @@ -142,10 +147,12 @@ const getExports = (
liveDev ?
{
source,
...getSourceDialects(source, c),
default: target,
}
: {
source,
...getSourceDialects(source, c),
types: target.replace(/\.js$/, '.d.ts'),
default: target,
}
Expand Down Expand Up @@ -183,6 +190,12 @@ const getExports = (
return e
}

const getSourceDialects = (source: string, c: TshyConfig) => {
const { sourceDialects } = c
if (!sourceDialects) return {}
return Object.fromEntries(sourceDialects.map(s => [s, source]))
}

export const setMain = (
c: TshyConfig | undefined,
pkg: Package & { exports: ExportsSubpaths },
Expand Down
4 changes: 3 additions & 1 deletion src/tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const {
exclude = [],
} = config

const relativeExclude = exclude.map(e => `../${e.replace(/^\.\//, '')}`)
const relativeExclude = exclude.map(
e => `../${e.replace(/^\.\//, '')}`,
)

const recommended: Record<string, any> = {
compilerOptions: {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type TshyConfigMaybeGlobExports = {
module?: boolean
commonjsDialects?: string[]
esmDialects?: string[]
sourceDialects?: string[]
project?: string
exclude?: string[]
liveDev?: boolean
Expand Down
51 changes: 40 additions & 11 deletions src/valid-extra-dialects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ const arrayOverlap = (
): string | false => {
if (!a || !b) return false
for (const av of a) {
if (b.includes(av)) {
return av
}
if (b.includes(av)) return av
}
return false
}

const validExtraDialectSet = (
e: string[],
which: 'commonjs' | 'esm',
which: 'commonjs' | 'esm' | 'source',
) => {
for (const d of e) {
if (typeof d !== 'string') {
Expand All @@ -31,17 +29,28 @@ const validExtraDialectSet = (
d === 'require' ||
d === 'import' ||
d === 'node' ||
d === 'source' ||
d === 'default'
) {
fail(`${which} must not contain ${d}`)
fail(
`tshy.${which}Dialects must not contain ${JSON.stringify(d)}`,
)
return process.exit(1)
}
}
return true
}

export default ({ commonjsDialects, esmDialects }: TshyConfig) => {
if (commonjsDialects === undefined && esmDialects === undefined) {
export default ({
commonjsDialects,
esmDialects,
sourceDialects,
}: TshyConfig) => {
if (
commonjsDialects === undefined &&
esmDialects === undefined &&
sourceDialects === undefined
) {
return true
}
if (
Expand All @@ -53,11 +62,31 @@ export default ({ commonjsDialects, esmDialects }: TshyConfig) => {
if (esmDialects && !validExtraDialectSet(esmDialects, 'esm')) {
return false
}
const overlap = arrayOverlap(commonjsDialects, esmDialects)
if (overlap) {
if (
sourceDialects &&
!validExtraDialectSet(sourceDialects, 'source')
) {
return false
}
for (const [aname, bname, a, b] of [
[
'commonjsDialects',
'esmDialects',
commonjsDialects,
esmDialects,
],
[
'commonjsDialects',
'sourceDialects',
commonjsDialects,
sourceDialects,
],
['esmDialects', 'sourceDialects', esmDialects, sourceDialects],
] as const) {
const overlap = arrayOverlap(a, b)
if (!overlap) continue
fail(
'commonjsDialects and esmDialects must be unique, ' +
`found ${overlap} in both lists`,
`${aname} and ${bname} must be unique, found ${overlap} in both lists`,
)
return process.exit(1)
}
Expand Down
12 changes: 12 additions & 0 deletions tap-snapshots/test/exports.ts.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Object {
".": Object {
"blah": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/blah/index.d.ts",
"default": "./dist/blah/index.js",
},
Expand All @@ -41,6 +42,7 @@ Object {
"./foo": Object {
"blah": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/blah/foo.d.ts",
"default": "./dist/blah/foo.js",
},
Expand Down Expand Up @@ -77,11 +79,13 @@ Object {
".": Object {
"deno": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/deno/index.d.ts",
"default": "./dist/deno/index.js",
},
"no-overrides": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/no-overrides/index.d.ts",
"default": "./dist/no-overrides/index.js",
},
Expand All @@ -94,11 +98,13 @@ Object {
"./foo": Object {
"deno": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/deno/foo.d.ts",
"default": "./dist/deno/foo.js",
},
"no-overrides": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/no-overrides/foo.d.ts",
"default": "./dist/no-overrides/foo.js",
},
Expand Down Expand Up @@ -145,16 +151,19 @@ Object {
".": Object {
"deno": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/deno/index.d.ts",
"default": "./dist/deno/index.js",
},
"no-overrides": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/no-overrides/index.d.ts",
"default": "./dist/no-overrides/index.js",
},
"blah": Object {
"source": "./src/index.ts",
"my-source": "./src/index.ts",
"types": "./dist/blah/index.d.ts",
"default": "./dist/blah/index.js",
},
Expand All @@ -172,16 +181,19 @@ Object {
"./foo": Object {
"deno": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/deno/foo.d.ts",
"default": "./dist/deno/foo.js",
},
"no-overrides": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/no-overrides/foo.d.ts",
"default": "./dist/no-overrides/foo.js",
},
"blah": Object {
"source": "./src/foo.ts",
"my-source": "./src/foo.ts",
"types": "./dist/blah/foo.d.ts",
"default": "./dist/blah/foo.js",
},
Expand Down
Loading

0 comments on commit 3b20fff

Please sign in to comment.