@ampt/cli 1.0.16 → 1.0.18
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/bin/bin +3 -0
- package/dist/cli.js +162 -162
- package/dist/cli.js.map +2 -2
- package/dist/loader.mjs +267 -0
- package/dist/webapi-polyfill.js +9 -9
- package/dist/webapi-polyfill.js.map +2 -2
- package/dist/workers/hash.js.map +1 -1
- package/package.json +7 -3
package/dist/loader.mjs
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import Module from 'module'
|
|
3
|
+
import { dirname, extname, join, resolve as pathResolve } from 'path'
|
|
4
|
+
import { pathToFileURL, fileURLToPath } from 'url'
|
|
5
|
+
import JoyCon from 'joycon'
|
|
6
|
+
import { addHook } from 'pirates'
|
|
7
|
+
import sourceMapSupport from 'source-map-support'
|
|
8
|
+
import tsconfigLoader from 'tsconfig-paths/lib/tsconfig-loader'
|
|
9
|
+
import { createMatchPath } from 'tsconfig-paths'
|
|
10
|
+
|
|
11
|
+
const ESBUILD_PATH = process.env.ESBUILD_PATH || '/opt/nodejs/node_modules/esbuild'
|
|
12
|
+
const { default: esbuild } = await import(ESBUILD_PATH)
|
|
13
|
+
const { transform, transformSync } = esbuild
|
|
14
|
+
|
|
15
|
+
const baseURL = pathToFileURL(`${process.cwd()}/`).href
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
TODO: consider caching loaded files in to memory if asked, so that we can cache them to negate the need to nft/esbuild?
|
|
19
|
+
at least cache transforms?
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const joyCon = new JoyCon()
|
|
23
|
+
const matcherCache = {}
|
|
24
|
+
|
|
25
|
+
function isDir(path) {
|
|
26
|
+
const stats = fs.statSync(path, { throwIfNoEntry: false })
|
|
27
|
+
if (!stats) {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
return stats.isDirectory()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const bareImportSearchExtensions = ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.mts', '.cts']
|
|
34
|
+
|
|
35
|
+
function bareImportSearch(specifier) {
|
|
36
|
+
for (const ext of [...bareImportSearchExtensions, ...bareImportSearchExtensions.map((ext) => `/index${ext}`)]) {
|
|
37
|
+
const fullPath = `${specifier}${ext}`
|
|
38
|
+
if (fs.existsSync(fullPath)) {
|
|
39
|
+
return fullPath
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function matchPath(specifier, parentPath) {
|
|
45
|
+
// parentPath can be a file or a directory
|
|
46
|
+
const base = isDir(parentPath) ? parentPath : dirname(parentPath || process.cwd())
|
|
47
|
+
|
|
48
|
+
const configs = [joyCon.resolveSync(['tsconfig.json'], base), joyCon.resolveSync(['jsconfig.json'], base)]
|
|
49
|
+
|
|
50
|
+
for (const configPath of configs) {
|
|
51
|
+
if (configPath) {
|
|
52
|
+
let matcher = matcherCache[configPath]
|
|
53
|
+
if (!matcher) {
|
|
54
|
+
const loaded = tsconfigLoader.loadTsconfig(configPath)
|
|
55
|
+
if (loaded) {
|
|
56
|
+
const { baseUrl, paths } = loaded.compilerOptions ?? {}
|
|
57
|
+
|
|
58
|
+
if (paths) {
|
|
59
|
+
const absoluteBaseUrl = baseUrl ? pathResolve(dirname(configPath), baseUrl) : dirname(configPath)
|
|
60
|
+
matcher = createMatchPath(absoluteBaseUrl, paths)
|
|
61
|
+
matcherCache[configPath] = matcher
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (matcher) {
|
|
67
|
+
const matched = matcher(specifier)
|
|
68
|
+
if (matched) {
|
|
69
|
+
if (extensions.has(extname(matched))) {
|
|
70
|
+
return matched
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const bareImportMatch = bareImportSearch(matched)
|
|
74
|
+
if (bareImportMatch) {
|
|
75
|
+
return bareImportMatch
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return matched
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (isBareImport(specifier)) {
|
|
85
|
+
const bareImportMatch = bareImportSearch(join(base, specifier))
|
|
86
|
+
if (bareImportMatch) {
|
|
87
|
+
return bareImportMatch
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const sourceMaps = {}
|
|
93
|
+
|
|
94
|
+
sourceMapSupport.install({
|
|
95
|
+
handleUncaughtExceptions: false,
|
|
96
|
+
environment: 'node',
|
|
97
|
+
retrieveSourceMap(file) {
|
|
98
|
+
if (sourceMaps[file]) {
|
|
99
|
+
return {
|
|
100
|
+
url: file,
|
|
101
|
+
map: sourceMaps[file]
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
const name = `${file}.map`
|
|
105
|
+
if (fs.existsSync(name)) {
|
|
106
|
+
const map = JSON.parse(fs.readFileSync(name).toString('utf8'))
|
|
107
|
+
sourceMaps[file] = map
|
|
108
|
+
return {
|
|
109
|
+
url: file,
|
|
110
|
+
map
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
function isModulePackage(base) {
|
|
119
|
+
const { data = {} } = joyCon.loadSync(['package.json'], base)
|
|
120
|
+
return data.type === 'module'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const extensions = new Set(['.js', '.jsx', '.mjs', '.cjs', '.json', '.node', '.ts', '.tsx', '.mts', '.cts'])
|
|
124
|
+
|
|
125
|
+
function isBareImport(specifier) {
|
|
126
|
+
return (
|
|
127
|
+
(specifier.startsWith('./') ||
|
|
128
|
+
specifier.startsWith('..') ||
|
|
129
|
+
specifier.startsWith('/') ||
|
|
130
|
+
specifier.startsWith('file:///') ||
|
|
131
|
+
specifier.startsWith('file://.')) &&
|
|
132
|
+
!extensions.has(extname(specifier))
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function resolve(specifier, context, defaultResolve) {
|
|
137
|
+
if (specifier === '@serverless/cloud') {
|
|
138
|
+
return defaultResolve('@ampt/cloud', context)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!specifier.startsWith('file://') && !specifier.startsWith('node:')) {
|
|
142
|
+
const { parentURL = baseURL } = context
|
|
143
|
+
const matched = matchPath(specifier, fileURLToPath(parentURL))
|
|
144
|
+
|
|
145
|
+
if (matched) {
|
|
146
|
+
return { shortCircuit: true, url: pathToFileURL(matched).href }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return defaultResolve(specifier, context)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function readTsConfig(forFilePath) {
|
|
154
|
+
const base = isDir(forFilePath) ? forFilePath : dirname(forFilePath || process.cwd())
|
|
155
|
+
for (const configPath of [joyCon.resolveSync(['tsconfig.json'], base), joyCon.resolveSync(['jsconfig.json'], base)]) {
|
|
156
|
+
if (fs.existsSync(configPath)) {
|
|
157
|
+
return fs.readFileSync(configPath).toString('utf8')
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const transformOptions = {
|
|
163
|
+
'.jsx': {
|
|
164
|
+
loader: 'jsx',
|
|
165
|
+
tsconfig: true
|
|
166
|
+
},
|
|
167
|
+
'.ts': {
|
|
168
|
+
loader: 'ts',
|
|
169
|
+
tsconfig: true
|
|
170
|
+
},
|
|
171
|
+
'.tsx': {
|
|
172
|
+
loader: 'tsx',
|
|
173
|
+
tsconfig: true
|
|
174
|
+
},
|
|
175
|
+
'.cts': {
|
|
176
|
+
loader: 'ts',
|
|
177
|
+
esm: false
|
|
178
|
+
},
|
|
179
|
+
'.mts': {
|
|
180
|
+
loader: 'ts',
|
|
181
|
+
esm: true
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function load(sourcefile, context, defaultLoad) {
|
|
186
|
+
const result = await defaultLoad(sourcefile, context)
|
|
187
|
+
|
|
188
|
+
if (sourcefile.startsWith('file://')) {
|
|
189
|
+
const path = fileURLToPath(sourcefile)
|
|
190
|
+
const ext = extname(path)
|
|
191
|
+
const options = transformOptions[ext]
|
|
192
|
+
|
|
193
|
+
if (options) {
|
|
194
|
+
const isESM =
|
|
195
|
+
context.format === 'module' ||
|
|
196
|
+
result.format === 'module' ||
|
|
197
|
+
options.esm === true ||
|
|
198
|
+
(options.esm === undefined && isModulePackage(path))
|
|
199
|
+
|
|
200
|
+
const tsconfigRaw = options.tsconfig ? await readTsConfig(path) : undefined
|
|
201
|
+
|
|
202
|
+
const { code, warnings, map } = await transform(result.source.toString(), {
|
|
203
|
+
sourcefile,
|
|
204
|
+
format: isESM ? 'esm' : 'cjs',
|
|
205
|
+
sourcemap: true,
|
|
206
|
+
sourcesContent: false,
|
|
207
|
+
loader: options.loader,
|
|
208
|
+
target: `node${process.version.slice(1)}`,
|
|
209
|
+
tsconfigRaw
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
sourceMaps[sourcefile] = map
|
|
213
|
+
|
|
214
|
+
if (warnings && warnings.length > 0) {
|
|
215
|
+
for (const warning of warnings) {
|
|
216
|
+
console.log(warning.location)
|
|
217
|
+
console.log(warning.text)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
result.shortCircuit = true
|
|
222
|
+
result.source = code
|
|
223
|
+
result.format = isESM ? 'module' : 'commonjs'
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return result
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function compile(source, sourcefile) {
|
|
231
|
+
const {
|
|
232
|
+
code,
|
|
233
|
+
warnings = [],
|
|
234
|
+
map
|
|
235
|
+
} = transformSync(source, {
|
|
236
|
+
sourcefile,
|
|
237
|
+
format: 'cjs',
|
|
238
|
+
loader: 'ts',
|
|
239
|
+
sourcemap: true,
|
|
240
|
+
sourcesContent: false
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
sourceMaps[sourcefile] = map
|
|
244
|
+
|
|
245
|
+
for (const warning of warnings) {
|
|
246
|
+
console.warn(warning)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return code
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
addHook(compile, {
|
|
253
|
+
exts: ['.ts', '.cts'],
|
|
254
|
+
ignoreNodeModules: false
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
const originalResolveFilename = Module._resolveFilename
|
|
258
|
+
Module._resolveFilename = function (request, parent, ...rest) {
|
|
259
|
+
if (request === '@serverless/cloud') {
|
|
260
|
+
return originalResolveFilename.call(this, '@ampt/cloud', parent, ...rest)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// console.log('resolve filenae', request, parent)
|
|
264
|
+
// todo: why is parent undefined sometimes, and what can we pass to matchPath?
|
|
265
|
+
const matchedPath = parent ? matchPath(request, parent.path) : null
|
|
266
|
+
return originalResolveFilename.call(this, matchedPath || request, parent, ...rest)
|
|
267
|
+
}
|