-
-
Notifications
You must be signed in to change notification settings - Fork 604
Expand file tree
/
Copy pathpatch-ts.js
More file actions
150 lines (125 loc) · 4.04 KB
/
patch-ts.js
File metadata and controls
150 lines (125 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import fs from 'node:fs'
import { exec } from 'node:child_process'
import { promisify } from 'node:util'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
import * as glob from 'glob'
import { hasCoreImports, replaceCoreImports } from '../replaceCoreImports.js'
const execAsync = promisify(exec)
const BUILD_DIR = new URL('../../lib/', import.meta.url)
function searchFilesForPattern(filePattern, searchPattern, errorMessage) {
const filePaths = glob.sync(filePattern, {
cwd: BUILD_DIR,
absolute: true,
})
let matchingFiles = []
try {
matchingFiles = filePaths.filter((path) => {
const fileContents = fs.readFileSync(path, 'utf8')
return fileContents.includes(searchPattern)
})
} catch (error) {
console.error(errorMessage, error)
process.exit(1)
}
return matchingFiles
}
function getRelativePaths(paths) {
const basePath = fileURLToPath(BUILD_DIR)
return paths.map((absolutePath) => path.relative(basePath, absolutePath))
}
async function patchTypeDefs() {
const typeDefsPaths = glob.sync('**/*.d.{ts,mts}', {
cwd: BUILD_DIR,
absolute: true,
})
const typeDefsWithCoreImports = typeDefsPaths
.map((modulePath) => {
const fileContents = fs.readFileSync(modulePath, 'utf8')
/**
* @note Treat all type definition files as ESM because even
* CJS .d.ts use `import` statements.
*/
if (hasCoreImports(fileContents, true)) {
return [modulePath, fileContents]
}
})
.filter(Boolean)
if (typeDefsWithCoreImports.length === 0) {
console.log(
'Found no .d.ts modules containing the "#core" import, skipping...',
)
return process.exit(0)
}
console.log(
'Found %d module(s) with the "#core" import, resolving...',
typeDefsWithCoreImports.length,
)
for (const [typeDefsPath, fileContents] of typeDefsWithCoreImports) {
// Treat ".d.ts" files as ESM to replace "import" statements.
// Force no extension on the ".d.ts" imports.
const nextFileContents = replaceCoreImports(
typeDefsPath,
fileContents,
true,
)
fs.writeFileSync(typeDefsPath, nextFileContents, 'utf8')
console.log('Successfully patched "%s"!', typeDefsPath)
}
console.log(
'Imports resolved in %d file(s), verifying...',
typeDefsWithCoreImports.length,
)
// Next, validate that we left no "#core" imports unresolved.
const modulesWithUnresolvedImports = searchFilesForPattern(
'**/*.d.{ts,mts}',
'#core',
'Failed to validate the .d.ts modules for the presence of the "#core" import. See the original error below.',
)
if (modulesWithUnresolvedImports.length > 0) {
console.error(
`Found .d.ts modules containing unresolved "#core" import after the patching:
${getRelativePaths(modulesWithUnresolvedImports)
.map((p) => ` - ${p}`)
.join('\n')}
`,
)
return process.exit(1)
}
// Ensure that the .d.ts files compile without errors after resolving the "#core" imports.
console.log('Compiling the .d.ts modules with tsc...')
const tscCompilation = await execAsync(
`tsc --noEmit --skipLibCheck ${typeDefsPaths.map((filePath) => `"${filePath}"`).join(' ')}`,
{
cwd: fileURLToPath(BUILD_DIR),
},
)
if (tscCompilation.stderr !== '') {
console.error(
'Failed to compile the .d.ts modules with tsc. See the original error below.',
tscCompilation.stderr,
)
return process.exit(1)
}
// Ensure that CJS .d.ts file never reference .mjs files.
const mjsInCjsResults = searchFilesForPattern(
'**/*.d.ts',
'.mjs',
'Failed to validate the .d.ts modules not referencing ".mjs" files. See the original error below.',
)
if (mjsInCjsResults.length > 0) {
console.error(
`Found .d.ts modules referencing ".mjs" files after patching:
${getRelativePaths(mjsInCjsResults)
.map((p) => ` - ${p}`)
.join('\n')}
`,
)
return process.exit(1)
}
console.log(
'The "#core" imports resolved successfully in %d .d.ts modules! 🎉',
typeDefsWithCoreImports.length,
)
}
patchTypeDefs()