tshy 1.0.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +39 -0
- package/.github/workflows/typedoc.yml +50 -0
- package/LICENSE.md +63 -0
- package/README.md +235 -0
- package/dist/esm/bins.d.ts +3 -0
- package/dist/esm/bins.d.ts.map +1 -0
- package/dist/esm/bins.js +18 -0
- package/dist/esm/bins.js.map +1 -0
- package/dist/esm/build.d.ts +2 -0
- package/dist/esm/build.d.ts.map +1 -0
- package/dist/esm/build.js +56 -0
- package/dist/esm/build.js.map +1 -0
- package/dist/esm/config.d.ts +4 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +85 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/dialects.d.ts +3 -0
- package/dist/esm/dialects.d.ts.map +1 -0
- package/dist/esm/dialects.js +3 -0
- package/dist/esm/dialects.js.map +1 -0
- package/dist/esm/exports.d.ts +4 -0
- package/dist/esm/exports.d.ts.map +1 -0
- package/dist/esm/exports.js +89 -0
- package/dist/esm/exports.js.map +1 -0
- package/dist/esm/fail.d.ts +2 -0
- package/dist/esm/fail.d.ts.map +1 -0
- package/dist/esm/fail.js +7 -0
- package/dist/esm/fail.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.d.ts +4 -0
- package/dist/esm/package.d.ts.map +1 -0
- package/dist/esm/package.js +16 -0
- package/dist/esm/package.js.map +1 -0
- package/dist/esm/polyfills.d.ts +3 -0
- package/dist/esm/polyfills.d.ts.map +1 -0
- package/dist/esm/polyfills.js +13 -0
- package/dist/esm/polyfills.js.map +1 -0
- package/dist/esm/set-folder-dialect.d.ts +4 -0
- package/dist/esm/set-folder-dialect.d.ts.map +1 -0
- package/dist/esm/set-folder-dialect.js +9 -0
- package/dist/esm/set-folder-dialect.js.map +1 -0
- package/dist/esm/sources.d.ts +3 -0
- package/dist/esm/sources.d.ts.map +1 -0
- package/dist/esm/sources.js +19 -0
- package/dist/esm/sources.js.map +1 -0
- package/dist/esm/tsconfig.d.ts +2 -0
- package/dist/esm/tsconfig.d.ts.map +1 -0
- package/dist/esm/tsconfig.js +55 -0
- package/dist/esm/tsconfig.js.map +1 -0
- package/dist/esm/types.d.ts +38 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/write-package.d.ts +3 -0
- package/dist/esm/write-package.d.ts.map +1 -0
- package/dist/esm/write-package.js +6 -0
- package/dist/esm/write-package.js.map +1 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +92 -0
- package/docs/assets/main.js +59 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1383 -0
- package/docs/functions/bins.default.html +60 -0
- package/docs/functions/fail.fail.html +67 -0
- package/docs/functions/set_folder_dialect.default.html +67 -0
- package/docs/functions/write_package.default.html +60 -0
- package/docs/index.html +172 -0
- package/docs/modules/bins.html +61 -0
- package/docs/modules/build.html +54 -0
- package/docs/modules/config.html +61 -0
- package/docs/modules/dialects.html +61 -0
- package/docs/modules/exports.html +61 -0
- package/docs/modules/fail.html +61 -0
- package/docs/modules/index.html +54 -0
- package/docs/modules/package.html +61 -0
- package/docs/modules/polyfills.html +61 -0
- package/docs/modules/set_folder_dialect.html +61 -0
- package/docs/modules/sources.html +61 -0
- package/docs/modules/tsconfig.html +54 -0
- package/docs/modules/types.html +65 -0
- package/docs/modules/write_package.html +61 -0
- package/docs/types/types.Dialect.html +56 -0
- package/docs/types/types.Export.html +72 -0
- package/docs/types/types.Package.html +73 -0
- package/docs/types/types.TshyConfig.html +63 -0
- package/docs/types/types.TshyExport.html +56 -0
- package/docs/variables/config.default.html +56 -0
- package/docs/variables/dialects.default.html +56 -0
- package/docs/variables/exports.default.html +56 -0
- package/docs/variables/package.default.html +56 -0
- package/docs/variables/polyfills.default.html +56 -0
- package/docs/variables/sources.default.html +56 -0
- package/package.json +71 -0
- package/scripts/fixup.sh +5 -0
- package/src/bins.ts +15 -0
- package/src/build.ts +64 -0
- package/src/config.ts +117 -0
- package/src/dialects.ts +2 -0
- package/src/exports.ts +105 -0
- package/src/fail.ts +5 -0
- package/src/index.ts +17 -0
- package/src/package.ts +18 -0
- package/src/polyfills.ts +21 -0
- package/src/set-folder-dialect.ts +16 -0
- package/src/sources.ts +20 -0
- package/src/tsconfig.ts +65 -0
- package/src/types.ts +43 -0
- package/src/write-package.ts +6 -0
- package/tsconfig/esm.json +7 -0
- package/tsconfig.json +17 -0
- package/typedoc.json +7 -0
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tshy",
|
|
3
|
+
"version": "1.0.0-0",
|
|
4
|
+
"description": "TypeScript HYbridizer - Hybrid (CommonJS/ESM) TypeScript node package builder",
|
|
5
|
+
"author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
|
|
6
|
+
"license": "BlueOak-1.0.0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": "./dist/esm/index.js",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"chalk": "^5.3.0",
|
|
11
|
+
"foreground-child": "^3.1.1",
|
|
12
|
+
"mkdirp": "^3.0.1",
|
|
13
|
+
"rimraf": "^5.0.1",
|
|
14
|
+
"sync-content": "^1.0.2",
|
|
15
|
+
"typescript": "5.2"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"postversion": "npm publish",
|
|
19
|
+
"prepublishOnly": "git push origin --follow-tags",
|
|
20
|
+
"prepare": "tsc -p tsconfig/esm.json && bash scripts/fixup.sh",
|
|
21
|
+
"pretest": "npm run prepare",
|
|
22
|
+
"presnap": "npm run prepare",
|
|
23
|
+
"format": "prettier --write . --loglevel warn --ignore-path ../../.prettierignore --cache",
|
|
24
|
+
"typedoc": "typedoc"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": "16 >=16.17 || 18 >=18.16.0 || >=20.6.1"
|
|
28
|
+
},
|
|
29
|
+
"repository": "https://github.com/isaacs/tshy",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"typescript",
|
|
32
|
+
"tsc",
|
|
33
|
+
"hybrid",
|
|
34
|
+
"esm",
|
|
35
|
+
"commonjs",
|
|
36
|
+
"build"
|
|
37
|
+
],
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^20.6.0",
|
|
40
|
+
"typedoc": "^0.25.1"
|
|
41
|
+
},
|
|
42
|
+
"prettier": {
|
|
43
|
+
"semi": false,
|
|
44
|
+
"printWidth": 70,
|
|
45
|
+
"tabWidth": 2,
|
|
46
|
+
"useTabs": false,
|
|
47
|
+
"singleQuote": true,
|
|
48
|
+
"jsxSingleQuote": false,
|
|
49
|
+
"bracketSameLine": true,
|
|
50
|
+
"arrowParens": "avoid",
|
|
51
|
+
"endOfLine": "lf"
|
|
52
|
+
},
|
|
53
|
+
"tshy": {
|
|
54
|
+
"dialects": [
|
|
55
|
+
"esm"
|
|
56
|
+
],
|
|
57
|
+
"exports": {
|
|
58
|
+
"./package.json": "./package.json",
|
|
59
|
+
".": "./src/index.ts"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"exports": {
|
|
63
|
+
"./package.json": "./package.json",
|
|
64
|
+
".": {
|
|
65
|
+
"import": {
|
|
66
|
+
"types": "./dist/esm/index.d.ts",
|
|
67
|
+
"default": "./dist/esm/index.js"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/scripts/fixup.sh
ADDED
package/src/bins.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// chmod bins after build
|
|
2
|
+
import { chmodSync } from 'fs'
|
|
3
|
+
import { resolve } from 'path'
|
|
4
|
+
import pkg from './package.js'
|
|
5
|
+
export default () => {
|
|
6
|
+
const { bin } = pkg
|
|
7
|
+
if (!bin) return
|
|
8
|
+
if (typeof bin === 'string') {
|
|
9
|
+
chmodSync(resolve(bin), 0o755)
|
|
10
|
+
} else {
|
|
11
|
+
for (const v of Object.values(bin)) {
|
|
12
|
+
chmodSync(resolve(v), 0o755)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/build.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { spawnSync, SpawnSyncReturns } from 'node:child_process'
|
|
3
|
+
import { renameSync } from 'node:fs'
|
|
4
|
+
import { relative, resolve } from 'node:path/posix'
|
|
5
|
+
import { rimrafSync } from 'rimraf'
|
|
6
|
+
import { syncContentSync } from 'sync-content'
|
|
7
|
+
import bins from './bins.js'
|
|
8
|
+
import dialects from './dialects.js'
|
|
9
|
+
import { fail } from './fail.js'
|
|
10
|
+
import polyfills from './polyfills.js'
|
|
11
|
+
import setFolderDialect from './set-folder-dialect.js'
|
|
12
|
+
import './tsconfig.js'
|
|
13
|
+
import writePackage from './write-package.js'
|
|
14
|
+
|
|
15
|
+
const buildFail = (res: SpawnSyncReturns<Buffer>) => {
|
|
16
|
+
setFolderDialect('src')
|
|
17
|
+
fail('build failed')
|
|
18
|
+
console.error(res)
|
|
19
|
+
process.exit(1)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
rimrafSync('.tshy-build-tmp')
|
|
23
|
+
|
|
24
|
+
if (dialects.includes('esm')) {
|
|
25
|
+
setFolderDialect('src', 'esm')
|
|
26
|
+
const res = spawnSync('tsc -p .tshy/esm.json', {
|
|
27
|
+
shell: true,
|
|
28
|
+
stdio: 'inherit',
|
|
29
|
+
})
|
|
30
|
+
setFolderDialect('src')
|
|
31
|
+
if (res.status || res.signal) buildFail(res)
|
|
32
|
+
setFolderDialect('.tshy-build-tmp/esm', 'esm')
|
|
33
|
+
console.error(chalk.cyan.bold('built esm'))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (dialects.includes('commonjs')) {
|
|
37
|
+
setFolderDialect('src', 'commonjs')
|
|
38
|
+
const res = spawnSync('tsc -p .tshy/commonjs.json', {
|
|
39
|
+
shell: true,
|
|
40
|
+
stdio: 'inherit',
|
|
41
|
+
})
|
|
42
|
+
setFolderDialect('src')
|
|
43
|
+
if (res.status || res.signal) buildFail(res)
|
|
44
|
+
setFolderDialect('.tshy-build-tmp/commonjs', 'commonjs')
|
|
45
|
+
console.error(chalk.cyan.bold('built commonjs'), res)
|
|
46
|
+
// apply polyfills
|
|
47
|
+
for (const [f, t] of polyfills.entries()) {
|
|
48
|
+
const stemFrom = resolve(
|
|
49
|
+
'.tshy-build-tmp/commonjs',
|
|
50
|
+
relative(resolve('src'), resolve(f))
|
|
51
|
+
).replace(/\.cts$/, '')
|
|
52
|
+
const stemTo = resolve(
|
|
53
|
+
'.tshy-build-tmp/commonjs',
|
|
54
|
+
relative(resolve('src'), resolve(t))
|
|
55
|
+
).replace(/\.ts$/, '')
|
|
56
|
+
renameSync(`${stemFrom}.cjs`, `${stemTo}.js`)
|
|
57
|
+
renameSync(`${stemFrom}.d.cts`, `${stemTo}.d.ts`)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
syncContentSync('.tshy-build-tmp', 'dist')
|
|
62
|
+
rimrafSync('.tshy-build-tmp')
|
|
63
|
+
bins()
|
|
64
|
+
writePackage()
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// get the config and package and stuff
|
|
2
|
+
|
|
3
|
+
import { fail } from './fail.js'
|
|
4
|
+
import { Dialect, Package, TshyConfig, TshyExport } from './types.js'
|
|
5
|
+
|
|
6
|
+
const validConfig = (e: any): e is TshyConfig =>
|
|
7
|
+
!!e &&
|
|
8
|
+
typeof e === 'object' &&
|
|
9
|
+
(e.exports === undefined || validExports(e['exports'])) &&
|
|
10
|
+
(e.dialects === undefined || validDialects(e['dialects']))
|
|
11
|
+
|
|
12
|
+
const isDialect = (d: any): d is Dialect =>
|
|
13
|
+
d === 'commonjs' || d === 'esm'
|
|
14
|
+
|
|
15
|
+
const validDialects = (
|
|
16
|
+
d: any
|
|
17
|
+
): d is Exclude<TshyConfig['dialects'], undefined> =>
|
|
18
|
+
!!d && Array.isArray(d) && !d.some(d => !isDialect(d))
|
|
19
|
+
|
|
20
|
+
const validExports = (
|
|
21
|
+
e: any
|
|
22
|
+
): e is Exclude<TshyConfig['exports'], undefined> => {
|
|
23
|
+
if (!e) return false
|
|
24
|
+
if (typeof e !== 'object') return false
|
|
25
|
+
for (const [sub, exp] of Object.entries(e)) {
|
|
26
|
+
if (sub !== '.' && !sub.startsWith('./')) {
|
|
27
|
+
fail(
|
|
28
|
+
`tshy.exports key must be "." or start with "./", got: ${sub}`
|
|
29
|
+
)
|
|
30
|
+
process.exit(1)
|
|
31
|
+
}
|
|
32
|
+
if (typeof exp === 'string') {
|
|
33
|
+
e[sub] = addDot(exp)
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
if (typeof exp !== 'object' || !exp || Array.isArray(exp)) {
|
|
37
|
+
fail(
|
|
38
|
+
`tshy.exports ${sub} value must be string or import/require object, ` +
|
|
39
|
+
`got: ${JSON.stringify(exp)}`
|
|
40
|
+
)
|
|
41
|
+
process.exit(1)
|
|
42
|
+
}
|
|
43
|
+
const { import: i, require: r } = exp as Exclude<
|
|
44
|
+
TshyExport,
|
|
45
|
+
string
|
|
46
|
+
>
|
|
47
|
+
if (!i && !e) {
|
|
48
|
+
fail(
|
|
49
|
+
`tshy.exports ${sub} needs require or import, ` +
|
|
50
|
+
`got: ${JSON.stringify(exp)}`
|
|
51
|
+
)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
if (
|
|
55
|
+
(i !== undefined && typeof i !== 'string') ||
|
|
56
|
+
(r !== undefined && typeof r !== 'string')
|
|
57
|
+
) {
|
|
58
|
+
fail(
|
|
59
|
+
`tshy.exports ${sub} import/require must be strings, ` +
|
|
60
|
+
`got: ${JSON.stringify(exp)}`
|
|
61
|
+
)
|
|
62
|
+
process.exit(1)
|
|
63
|
+
}
|
|
64
|
+
if (
|
|
65
|
+
(i !== undefined && join(i).startsWith('src/')) ||
|
|
66
|
+
(r !== undefined && join(r).startsWith('src/'))
|
|
67
|
+
) {
|
|
68
|
+
fail(
|
|
69
|
+
`tshy.exports ${sub} in src/ must be string paths, ` +
|
|
70
|
+
`got: ${JSON.stringify(exp)}`
|
|
71
|
+
)
|
|
72
|
+
process.exit(1)
|
|
73
|
+
}
|
|
74
|
+
e[sub] = {}
|
|
75
|
+
if (e[sub].types) e[sub].types = addDot(e[sub].types)
|
|
76
|
+
if (e[sub].import) e[sub].types = addDot(e[sub].import)
|
|
77
|
+
if (e[sub].require) e[sub].types = addDot(e[sub].require)
|
|
78
|
+
}
|
|
79
|
+
if (e.dialects) {
|
|
80
|
+
if (!validDialects(e.dialects)) {
|
|
81
|
+
fail(
|
|
82
|
+
`tshy.dialects must be array containing 'esm' and/or 'commonjs', ` +
|
|
83
|
+
`got: ${JSON.stringify(e.dialects)}`
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const addDot = (s: string) => `./${join(s)}`
|
|
91
|
+
|
|
92
|
+
const getConfig = (
|
|
93
|
+
pkg: Package,
|
|
94
|
+
sources: Set<string>
|
|
95
|
+
): TshyConfig => {
|
|
96
|
+
const tshy: TshyConfig = validConfig(pkg.tshy) ? pkg.tshy : {}
|
|
97
|
+
if (tshy.exports) return tshy
|
|
98
|
+
const e: Exclude<TshyConfig['exports'], undefined> = {
|
|
99
|
+
'./package.json': './package.json',
|
|
100
|
+
}
|
|
101
|
+
for (const i of sources) {
|
|
102
|
+
if (/^\.\/src\/index\.[^\.]+$/.test(i)) {
|
|
103
|
+
e['.'] = i
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
pkg.tshy = tshy
|
|
108
|
+
tshy.exports = e
|
|
109
|
+
return tshy
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
import { join } from 'path/posix'
|
|
113
|
+
import pkg from './package.js'
|
|
114
|
+
import sources from './sources.js'
|
|
115
|
+
|
|
116
|
+
const config: TshyConfig = getConfig(pkg, sources)
|
|
117
|
+
export default config
|
package/src/dialects.ts
ADDED
package/src/exports.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { relative, resolve } from 'node:path/posix'
|
|
2
|
+
import config from './config.js'
|
|
3
|
+
import dialects from './dialects.js'
|
|
4
|
+
import polyfills from './polyfills.js'
|
|
5
|
+
import { Export, TshyConfig, TshyExport } from './types.js'
|
|
6
|
+
|
|
7
|
+
const getImpTarget = (
|
|
8
|
+
s: string | TshyExport | undefined
|
|
9
|
+
): string | undefined => {
|
|
10
|
+
if (s === undefined) return undefined
|
|
11
|
+
if (typeof s === 'string') {
|
|
12
|
+
const imp = s.endsWith('.cts') ? undefined : s
|
|
13
|
+
return !imp || !imp.startsWith('./src/')
|
|
14
|
+
? imp
|
|
15
|
+
: dialects.includes('esm')
|
|
16
|
+
? `./dist/esm/${relative(
|
|
17
|
+
resolve('./src'),
|
|
18
|
+
resolve(imp)
|
|
19
|
+
).replace(/\.(m?)tsx?$/, '.$1js')}`
|
|
20
|
+
: undefined
|
|
21
|
+
}
|
|
22
|
+
if (s && typeof s === 'object') {
|
|
23
|
+
return getImpTarget(s.import)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const getReqTarget = (
|
|
28
|
+
s: string | TshyExport | undefined,
|
|
29
|
+
polyfills: Map<string, string>
|
|
30
|
+
): string | undefined => {
|
|
31
|
+
if (s === undefined) return undefined
|
|
32
|
+
if (typeof s === 'string') {
|
|
33
|
+
const req = s.endsWith('.mts') ? undefined : s
|
|
34
|
+
return !req || !req.startsWith('./src/')
|
|
35
|
+
? req
|
|
36
|
+
: dialects.includes('commonjs')
|
|
37
|
+
? `./dist/commonjs/${relative(
|
|
38
|
+
resolve('./src'),
|
|
39
|
+
resolve(polyfills.get(req) || req)
|
|
40
|
+
).replace(/\.(m?)tsx?$/, '.$1js')}`
|
|
41
|
+
: undefined
|
|
42
|
+
}
|
|
43
|
+
if (s && typeof s === 'object') {
|
|
44
|
+
return getReqTarget(s.require, polyfills)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const getExports = (
|
|
49
|
+
c: TshyConfig,
|
|
50
|
+
polyfills: Map<string, string>
|
|
51
|
+
): Record<string, Export> => {
|
|
52
|
+
if (!c.exports) {
|
|
53
|
+
fail('no exports on tshy config (is there code in ./src?)')
|
|
54
|
+
process.exit(1)
|
|
55
|
+
}
|
|
56
|
+
const e: Record<string, Export> = {}
|
|
57
|
+
for (const [sub, s] of Object.entries(c.exports)) {
|
|
58
|
+
const impTarget = getImpTarget(s)
|
|
59
|
+
const reqTarget = getReqTarget(s, polyfills)
|
|
60
|
+
|
|
61
|
+
// only possible for exports outside of ./src
|
|
62
|
+
const types = typeof s !== 'string' && s.types
|
|
63
|
+
|
|
64
|
+
if (typeof s !== 'string' || !s.startsWith('./src/')) {
|
|
65
|
+
if (impTarget === reqTarget) {
|
|
66
|
+
if (impTarget === undefined) continue
|
|
67
|
+
if (types) {
|
|
68
|
+
e[sub] = {
|
|
69
|
+
import: impTarget,
|
|
70
|
+
require: reqTarget,
|
|
71
|
+
types,
|
|
72
|
+
}
|
|
73
|
+
} else if (impTarget !== undefined) e[sub] = impTarget
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
if (types) {
|
|
77
|
+
e[sub] = {
|
|
78
|
+
types,
|
|
79
|
+
import: impTarget,
|
|
80
|
+
require: reqTarget,
|
|
81
|
+
}
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const exp: Export = (e[sub] = {})
|
|
87
|
+
if (impTarget) {
|
|
88
|
+
exp.import = {
|
|
89
|
+
types: impTarget.replace(/\.(m?)js$/, '.d.$1ts'),
|
|
90
|
+
default: impTarget,
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (reqTarget) {
|
|
94
|
+
exp.require = {
|
|
95
|
+
types: reqTarget.replace(/\.(c?)js$/, '.d.$1ts'),
|
|
96
|
+
default: reqTarget,
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return e
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
import { fail } from './fail.js'
|
|
104
|
+
import pkg from './package.js'
|
|
105
|
+
export default pkg.exports = getExports(config, polyfills)
|
package/src/fail.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import chalk from 'chalk'
|
|
4
|
+
|
|
5
|
+
import './exports.js'
|
|
6
|
+
import pkg from './package.js'
|
|
7
|
+
|
|
8
|
+
const { exports: exp, tshy } = pkg
|
|
9
|
+
|
|
10
|
+
console.error(chalk.yellow.bold('building'))
|
|
11
|
+
console.error(chalk.cyan.dim('tshy config'), tshy)
|
|
12
|
+
console.error(chalk.cyan.dim('exports'), exp)
|
|
13
|
+
|
|
14
|
+
// have our config, time to build
|
|
15
|
+
await import('./build.js')
|
|
16
|
+
|
|
17
|
+
console.log(chalk.bold.green('success!'))
|
package/src/package.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// get the package.json data for the cwd
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from 'fs'
|
|
4
|
+
import { fail } from './fail.js'
|
|
5
|
+
import { Package } from './types.js'
|
|
6
|
+
|
|
7
|
+
const readPkg = (): Package => {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(readFileSync('package.json', 'utf8'))
|
|
10
|
+
} catch (er) {
|
|
11
|
+
fail('failed to read package.json', er as Error)
|
|
12
|
+
process.exit(1)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const pkg = readPkg()
|
|
17
|
+
pkg.type = 'module'
|
|
18
|
+
export default pkg
|
package/src/polyfills.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// the modules like -cjs.cts that override a module at .ts
|
|
2
|
+
import sources from './sources.js'
|
|
3
|
+
import chalk from 'chalk'
|
|
4
|
+
|
|
5
|
+
const getPolyfills = (sources: Set<string>): Map<string, string> =>
|
|
6
|
+
new Map(
|
|
7
|
+
[...sources]
|
|
8
|
+
.filter(
|
|
9
|
+
f =>
|
|
10
|
+
f.endsWith('-cjs.cts') &&
|
|
11
|
+
sources.has(f.replace(/-cjs\.cts$/, '.ts'))
|
|
12
|
+
)
|
|
13
|
+
.map(f => [f, f.replace(/-cjs\.cts$/, '.ts')])
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
const polyfills = getPolyfills(sources)
|
|
17
|
+
if (polyfills.size) {
|
|
18
|
+
console.error(chalk.cyan.dim('polyfills detected'), polyfills)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default getPolyfills(sources)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { writeFileSync } from 'fs'
|
|
2
|
+
import { rimrafSync } from 'rimraf'
|
|
3
|
+
import { Dialect } from './types.js'
|
|
4
|
+
|
|
5
|
+
const writeDialectPJ = (f: string, mode?: Dialect) =>
|
|
6
|
+
mode
|
|
7
|
+
? writeFileSync(
|
|
8
|
+
f,
|
|
9
|
+
JSON.stringify({
|
|
10
|
+
type: mode === 'commonjs' ? 'commonjs' : 'module',
|
|
11
|
+
})
|
|
12
|
+
)
|
|
13
|
+
: rimrafSync(f)
|
|
14
|
+
|
|
15
|
+
export default (where: string, mode?: Dialect) =>
|
|
16
|
+
writeDialectPJ(`${where}/package.json`, mode)
|
package/src/sources.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// get the list of sources in ./src
|
|
2
|
+
|
|
3
|
+
import { readdirSync } from 'fs'
|
|
4
|
+
import { join } from 'path/posix'
|
|
5
|
+
|
|
6
|
+
const getSources = (dir = 'src'): string[] => {
|
|
7
|
+
const sources: string[] = []
|
|
8
|
+
const entries = readdirSync(dir, { withFileTypes: true })
|
|
9
|
+
for (const e of entries) {
|
|
10
|
+
const j = `./${join(dir, e.name)}`
|
|
11
|
+
if (e.isFile()) sources.push(j)
|
|
12
|
+
else if (e.isDirectory()) {
|
|
13
|
+
sources.push(...getSources(j))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return sources
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const sources = new Set(getSources())
|
|
20
|
+
export default sources
|
package/src/tsconfig.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { existsSync, writeFileSync } from 'fs'
|
|
3
|
+
import { mkdirpSync } from 'mkdirp'
|
|
4
|
+
|
|
5
|
+
// the commonjs build needs to exclude anything that will be polyfilled
|
|
6
|
+
import polyfills from './polyfills.js'
|
|
7
|
+
|
|
8
|
+
const recommended: Record<string, any> = {
|
|
9
|
+
compilerOptions: {
|
|
10
|
+
jsx: 'react',
|
|
11
|
+
declaration: true,
|
|
12
|
+
declarationMap: true,
|
|
13
|
+
inlineSources: true,
|
|
14
|
+
esModuleInterop: true,
|
|
15
|
+
forceConsistentCasingInFileNames: true,
|
|
16
|
+
moduleResolution: 'nodenext',
|
|
17
|
+
resolveJsonModule: true,
|
|
18
|
+
skipLibCheck: true,
|
|
19
|
+
sourceMap: true,
|
|
20
|
+
strict: true,
|
|
21
|
+
target: 'es2022',
|
|
22
|
+
module: 'nodenext',
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const build: Record<string, any> = {
|
|
27
|
+
extends: '../tsconfig.json',
|
|
28
|
+
compilerOptions: {
|
|
29
|
+
rootDir: '../src',
|
|
30
|
+
target: 'es2022',
|
|
31
|
+
module: 'nodenext',
|
|
32
|
+
moduleResolution: 'nodenext',
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const commonjs: Record<string, any> = {
|
|
37
|
+
extends: './build.json',
|
|
38
|
+
include: ['../src/**/*.ts', '../src/**/*.cts', '../src/**/*.tsx'],
|
|
39
|
+
exclude: [...polyfills.values()].map(f => `.${f}`),
|
|
40
|
+
compilerOptions: {
|
|
41
|
+
outDir: '../.tshy-build-tmp/commonjs',
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const esm: Record<string, any> = {
|
|
46
|
+
extends: './build.json',
|
|
47
|
+
include: ['../src/**/*.ts', '../src/**/*.cts', '../src/**/*.tsx'],
|
|
48
|
+
compilerOptions: {
|
|
49
|
+
outDir: '../.tshy-build-tmp/esm',
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
mkdirpSync('.tshy')
|
|
54
|
+
const writeConfig = (name: string, data: Record<string, any>) =>
|
|
55
|
+
writeFileSync(
|
|
56
|
+
`.tshy/${name}.json`,
|
|
57
|
+
JSON.stringify(data, null, 2) + '\n'
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
console.error(chalk.cyan.dim('writing tsconfig files...'))
|
|
61
|
+
if (!existsSync('tsconfig.json'))
|
|
62
|
+
writeConfig('../tsconfig', recommended)
|
|
63
|
+
writeConfig('build', build)
|
|
64
|
+
writeConfig('commonjs', commonjs)
|
|
65
|
+
writeConfig('esm', esm)
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type TshyConfig = {
|
|
2
|
+
exports?: Record<string, TshyExport>
|
|
3
|
+
dialects?: Dialect[]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type Dialect = 'commonjs' | 'esm'
|
|
7
|
+
|
|
8
|
+
export type TshyExport =
|
|
9
|
+
| string
|
|
10
|
+
| ({ types?: string; import?: string; require?: string } & (
|
|
11
|
+
| { import: string }
|
|
12
|
+
| { require: string }
|
|
13
|
+
))
|
|
14
|
+
|
|
15
|
+
export type Package = {
|
|
16
|
+
name: string
|
|
17
|
+
version: string
|
|
18
|
+
type?: 'module'
|
|
19
|
+
bin?: string | Record<string, string>
|
|
20
|
+
exports: Record<string, Export>
|
|
21
|
+
tshy?: TshyConfig
|
|
22
|
+
[k: string]: any
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// VERY limited subset of the datatypes "exports" can be
|
|
26
|
+
// but we're only writing our flavor, so it's fine.
|
|
27
|
+
export type Export =
|
|
28
|
+
| string
|
|
29
|
+
| { import?: string; require?: string; types?: string }
|
|
30
|
+
| {
|
|
31
|
+
import?:
|
|
32
|
+
| string
|
|
33
|
+
| {
|
|
34
|
+
types: string
|
|
35
|
+
default: string
|
|
36
|
+
}
|
|
37
|
+
require?:
|
|
38
|
+
| string
|
|
39
|
+
| {
|
|
40
|
+
types: string
|
|
41
|
+
default: string
|
|
42
|
+
}
|
|
43
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react",
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"inlineSources": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"moduleResolution": "nodenext",
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"target": "es2022",
|
|
15
|
+
"module": "nodenext"
|
|
16
|
+
}
|
|
17
|
+
}
|