@napi-rs/cli 3.7.4 → 3.8.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/README.md +33 -0
- package/cli.mjs +9 -12
- package/dist/cli.js +9248 -1311
- package/dist/index.cjs +9268 -1331
- package/dist/index.d.cts +175 -157
- package/dist/index.d.ts +175 -157
- package/dist/index.js +9248 -1311
- package/docs/artifacts.md +33 -0
- package/docs/build.md +58 -0
- package/docs/create-npm-dirs.md +32 -0
- package/docs/new.md +39 -0
- package/docs/pre-publish.md +37 -0
- package/docs/rename.md +37 -0
- package/docs/universalize.md +31 -0
- package/docs/version.md +31 -0
- package/docs/wasi.md +161 -0
- package/package.json +11 -10
- package/src/api/__tests__/__snapshots__/templates.spec.ts.md +1019 -114
- package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
- package/src/api/__tests__/artifacts.spec.ts +17 -0
- package/src/api/__tests__/create-npm-dirs.spec.ts +14 -15
- package/src/api/__tests__/new.spec.ts +41 -5
- package/src/api/artifacts.ts +934 -108
- package/src/api/build.ts +1317 -188
- package/src/api/create-npm-dirs.ts +472 -101
- package/src/api/new.ts +354 -35
- package/src/api/pre-publish.ts +2845 -99
- package/src/api/rename.ts +1638 -124
- package/src/api/templates/js-binding.ts +216 -38
- package/src/api/templates/load-wasi-template.ts +1641 -111
- package/src/api/templates/wasi-worker-template.ts +32 -3
- package/src/commands/rename.ts +8 -3
- package/src/def/artifacts.ts +2 -2
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +2 -2
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/misc.spec.ts +124 -3
- package/src/utils/__tests__/version.spec.ts +47 -1
- package/src/utils/config.ts +15 -2
- package/src/utils/metadata.ts +155 -47
- package/src/utils/misc.ts +6079 -0
- package/src/utils/target.ts +66 -8
- package/src/utils/typegen.ts +1223 -63
- package/src/utils/version.ts +96 -0
package/src/api/new.ts
CHANGED
|
@@ -13,19 +13,24 @@ import {
|
|
|
13
13
|
} from '../def/new.js'
|
|
14
14
|
import {
|
|
15
15
|
AVAILABLE_TARGETS,
|
|
16
|
+
CLI_VERSION,
|
|
16
17
|
debugFactory,
|
|
17
18
|
DEFAULT_TARGETS,
|
|
19
|
+
getWasiTarget,
|
|
18
20
|
mkdirAsync,
|
|
19
21
|
parseTriple,
|
|
20
22
|
readdirAsync,
|
|
21
23
|
statAsync,
|
|
24
|
+
wasiTargetHasThreads,
|
|
22
25
|
type SupportedPackageManager,
|
|
23
26
|
} from '../utils/index.js'
|
|
24
27
|
import {
|
|
25
28
|
napiEngineRequirement,
|
|
26
29
|
SUPPORTED_NAPI_VERSIONS,
|
|
30
|
+
restrictWasiNodeEngine,
|
|
27
31
|
} from '../utils/version.js'
|
|
28
32
|
import { renameProject } from './rename.js'
|
|
33
|
+
import { createCjsBinding } from './templates/index.js'
|
|
29
34
|
|
|
30
35
|
// Template imports removed as we're now using external templates
|
|
31
36
|
|
|
@@ -38,7 +43,117 @@ const TEMPLATE_REPOS = {
|
|
|
38
43
|
pnpm: 'https://github.com/napi-rs/package-template-pnpm',
|
|
39
44
|
} as const
|
|
40
45
|
|
|
41
|
-
const
|
|
46
|
+
const TEMPLATE_LOCKFILES: Record<SupportedPackageManager, string> = {
|
|
47
|
+
yarn: 'yarn.lock',
|
|
48
|
+
pnpm: 'pnpm-lock.yaml',
|
|
49
|
+
}
|
|
50
|
+
const WASI_CI_ARTIFACT_PATTERNS = [
|
|
51
|
+
'index.js',
|
|
52
|
+
'browser.js',
|
|
53
|
+
'*.wasi*.cjs',
|
|
54
|
+
'*.wasi*.d.cts',
|
|
55
|
+
'*.wasi*-browser.js',
|
|
56
|
+
'*.wasi*-deferred.js',
|
|
57
|
+
'*.wasi*-deferred.d.ts',
|
|
58
|
+
'wasi-worker*.mjs',
|
|
59
|
+
]
|
|
60
|
+
// Exported for tests.
|
|
61
|
+
export const GENERATED_WASI_BINDING =
|
|
62
|
+
/(?:\.(?:wasi|wasip\d+)(?:-browser|-deferred)?\.(?:cjs|js|d\.[cm]?ts)|wasi-worker(?:-browser)?\.mjs)/
|
|
63
|
+
const TYPE_DEF_FILE = /\.d\.[cm]?ts$/
|
|
64
|
+
const GLOB_PATTERN = /[*?[\]{}]/
|
|
65
|
+
|
|
66
|
+
function createWasiBrowserEntry(
|
|
67
|
+
packageName: string,
|
|
68
|
+
platformArchABI: string,
|
|
69
|
+
enableTypeDef: boolean,
|
|
70
|
+
) {
|
|
71
|
+
const packageSpecifier = `${packageName}-${platformArchABI}`
|
|
72
|
+
return (
|
|
73
|
+
`export * from '${packageSpecifier}'\n` +
|
|
74
|
+
(enableTypeDef ? '' : `export { default } from '${packageSpecifier}'\n`)
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function stripTypeConditions(
|
|
79
|
+
value: unknown,
|
|
80
|
+
typeDefPaths: Set<string>,
|
|
81
|
+
): unknown {
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
const entries = value
|
|
84
|
+
.map((entry) => stripTypeConditions(entry, typeDefPaths))
|
|
85
|
+
.filter((entry) => entry !== undefined)
|
|
86
|
+
return entries.length > 0 ? entries : undefined
|
|
87
|
+
}
|
|
88
|
+
if (typeof value !== 'object' || value === null) {
|
|
89
|
+
return value
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const result: Record<string, unknown> = {}
|
|
93
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
94
|
+
if (key === 'types') {
|
|
95
|
+
if (typeof entry === 'string') {
|
|
96
|
+
typeDefPaths.add(entry)
|
|
97
|
+
}
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
const stripped = stripTypeConditions(entry, typeDefPaths)
|
|
101
|
+
if (stripped !== undefined) {
|
|
102
|
+
result[key] = stripped
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return Object.keys(result).length > 0 ? result : undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function removeTypeDefOutput(
|
|
109
|
+
packageJson: Record<string, any>,
|
|
110
|
+
packageDir: string,
|
|
111
|
+
) {
|
|
112
|
+
const typeDefPaths = new Set<string>(['index.d.ts'])
|
|
113
|
+
for (const field of ['types', 'typings']) {
|
|
114
|
+
if (typeof packageJson[field] === 'string') {
|
|
115
|
+
typeDefPaths.add(packageJson[field])
|
|
116
|
+
}
|
|
117
|
+
delete packageJson[field]
|
|
118
|
+
}
|
|
119
|
+
delete packageJson.typesVersions
|
|
120
|
+
|
|
121
|
+
if (packageJson.exports !== undefined) {
|
|
122
|
+
const exports = stripTypeConditions(packageJson.exports, typeDefPaths)
|
|
123
|
+
if (exports === undefined) {
|
|
124
|
+
delete packageJson.exports
|
|
125
|
+
} else {
|
|
126
|
+
packageJson.exports = exports
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (Array.isArray(packageJson.files)) {
|
|
131
|
+
packageJson.files = packageJson.files.filter((file: unknown) => {
|
|
132
|
+
if (typeof file !== 'string' || !TYPE_DEF_FILE.test(file)) {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
typeDefPaths.add(file)
|
|
136
|
+
return false
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (const typeDefPath of typeDefPaths) {
|
|
141
|
+
const relativePath = typeDefPath.replace(/^\.\//, '')
|
|
142
|
+
if (!TYPE_DEF_FILE.test(relativePath) || GLOB_PATTERN.test(relativePath)) {
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
145
|
+
const absolutePath = path.resolve(packageDir, relativePath)
|
|
146
|
+
const relativeToPackage = path.relative(packageDir, absolutePath)
|
|
147
|
+
if (
|
|
148
|
+
relativeToPackage === '' ||
|
|
149
|
+
relativeToPackage.startsWith(`..${path.sep}`) ||
|
|
150
|
+
path.isAbsolute(relativeToPackage)
|
|
151
|
+
) {
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
await fs.rm(absolutePath, { force: true })
|
|
155
|
+
}
|
|
156
|
+
}
|
|
42
157
|
|
|
43
158
|
async function checkGitCommand(): Promise<boolean> {
|
|
44
159
|
return new Promise<boolean>((resolve) => {
|
|
@@ -109,7 +224,7 @@ async function downloadTemplate(
|
|
|
109
224
|
async function copyDirectory(
|
|
110
225
|
src: string,
|
|
111
226
|
dest: string,
|
|
112
|
-
|
|
227
|
+
hasWasiTargets: boolean,
|
|
113
228
|
): Promise<void> {
|
|
114
229
|
await mkdirAsync(dest, { recursive: true })
|
|
115
230
|
const entries = await fs.readdir(src, { withFileTypes: true })
|
|
@@ -124,15 +239,12 @@ async function copyDirectory(
|
|
|
124
239
|
}
|
|
125
240
|
|
|
126
241
|
if (entry.isDirectory()) {
|
|
127
|
-
await copyDirectory(srcPath, destPath,
|
|
242
|
+
await copyDirectory(srcPath, destPath, hasWasiTargets)
|
|
128
243
|
} else {
|
|
129
244
|
if (
|
|
130
|
-
|
|
131
|
-
(entry.name
|
|
132
|
-
|
|
133
|
-
entry.name.endsWith('wasi-worker-browser.mjs') ||
|
|
134
|
-
entry.name.endsWith('wasi-worker.mjs') ||
|
|
135
|
-
entry.name === 'browser.js')
|
|
245
|
+
entry.name === 'browser.js' ||
|
|
246
|
+
GENERATED_WASI_BINDING.test(entry.name) ||
|
|
247
|
+
(hasWasiTargets && entry.name === 'index.js')
|
|
136
248
|
) {
|
|
137
249
|
continue
|
|
138
250
|
}
|
|
@@ -144,19 +256,83 @@ async function copyDirectory(
|
|
|
144
256
|
async function filterTargetsInPackageJson(
|
|
145
257
|
filePath: string,
|
|
146
258
|
enabledTargets: string[],
|
|
259
|
+
enableTypeDef: boolean,
|
|
260
|
+
packageManager: SupportedPackageManager,
|
|
147
261
|
): Promise<void> {
|
|
148
262
|
const content = await fs.readFile(filePath, 'utf-8')
|
|
149
263
|
const packageJson = JSON.parse(content)
|
|
150
|
-
const
|
|
264
|
+
const wasiTargets = enabledTargets
|
|
265
|
+
.map(parseTriple)
|
|
266
|
+
.filter((target) => target.platform === 'wasi')
|
|
267
|
+
const includeWasiBindings = wasiTargets.length > 0
|
|
268
|
+
const includeThreadlessWasi = wasiTargets.some(
|
|
269
|
+
(target) => !wasiTargetHasThreads(target),
|
|
270
|
+
)
|
|
151
271
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
272
|
+
// The external templates may not yet list newly supported targets. The
|
|
273
|
+
// requested target set is authoritative rather than a filter over the
|
|
274
|
+
// template's current contents.
|
|
275
|
+
packageJson.napi ??= {}
|
|
276
|
+
packageJson.napi.targets = enabledTargets
|
|
277
|
+
|
|
278
|
+
if (includeThreadlessWasi) {
|
|
279
|
+
packageJson.devDependencies ??= {}
|
|
280
|
+
packageJson.devDependencies['@napi-rs/cli'] = `^${CLI_VERSION}`
|
|
281
|
+
// Template lockfiles can pin an older CLI that predates this target even
|
|
282
|
+
// when package.json's range is updated. The first install must resolve a
|
|
283
|
+
// lockfile from the generated manifest.
|
|
284
|
+
await fs.rm(
|
|
285
|
+
path.join(path.dirname(filePath), TEMPLATE_LOCKFILES[packageManager]),
|
|
286
|
+
{ force: true },
|
|
156
287
|
)
|
|
157
288
|
}
|
|
158
289
|
|
|
159
|
-
if (!
|
|
290
|
+
if (!enableTypeDef) {
|
|
291
|
+
await removeTypeDefOutput(packageJson, path.dirname(filePath))
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (includeWasiBindings) {
|
|
295
|
+
packageJson.browser = 'browser.js'
|
|
296
|
+
packageJson.files ??= []
|
|
297
|
+
if (!packageJson.files.includes('browser.js')) {
|
|
298
|
+
packageJson.files.push('browser.js')
|
|
299
|
+
}
|
|
300
|
+
const browserTarget =
|
|
301
|
+
wasiTargets.find(
|
|
302
|
+
(target) => getWasiTarget(target)?.flavor === 'single',
|
|
303
|
+
) ?? wasiTargets[0]
|
|
304
|
+
await fs.writeFile(
|
|
305
|
+
path.join(path.dirname(filePath), 'browser.js'),
|
|
306
|
+
createWasiBrowserEntry(
|
|
307
|
+
packageJson.name,
|
|
308
|
+
browserTarget.platformArchABI,
|
|
309
|
+
enableTypeDef,
|
|
310
|
+
),
|
|
311
|
+
)
|
|
312
|
+
if (!enableTypeDef) {
|
|
313
|
+
const wasiFlavors = [
|
|
314
|
+
...wasiTargets.filter(wasiTargetHasThreads),
|
|
315
|
+
...wasiTargets.filter((target) => !wasiTargetHasThreads(target)),
|
|
316
|
+
].map((target) => target.platformArchABI)
|
|
317
|
+
packageJson.main = 'index.js'
|
|
318
|
+
if (
|
|
319
|
+
!packageJson.files.includes('index.js') &&
|
|
320
|
+
!packageJson.files.includes('./index.js')
|
|
321
|
+
) {
|
|
322
|
+
packageJson.files.push('index.js')
|
|
323
|
+
}
|
|
324
|
+
await fs.writeFile(
|
|
325
|
+
path.join(path.dirname(filePath), 'index.js'),
|
|
326
|
+
createCjsBinding(
|
|
327
|
+
packageJson.napi.binaryName,
|
|
328
|
+
packageJson.napi.packageName ?? packageJson.name,
|
|
329
|
+
[],
|
|
330
|
+
packageJson.version,
|
|
331
|
+
wasiFlavors,
|
|
332
|
+
),
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
160
336
|
if (
|
|
161
337
|
packageJson.browser === 'browser.js' ||
|
|
162
338
|
packageJson.browser === './browser.js'
|
|
@@ -172,6 +348,49 @@ async function filterTargetsInPackageJson(
|
|
|
172
348
|
}
|
|
173
349
|
|
|
174
350
|
await fs.writeFile(filePath, JSON.stringify(packageJson, null, 2) + '\n')
|
|
351
|
+
await updateGeneratedWasiAttributes(
|
|
352
|
+
path.join(path.dirname(filePath), '.gitattributes'),
|
|
353
|
+
packageJson.napi.binaryName,
|
|
354
|
+
wasiTargets,
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async function updateGeneratedWasiAttributes(
|
|
359
|
+
filePath: string,
|
|
360
|
+
binaryName: string,
|
|
361
|
+
wasiTargets: ReturnType<typeof parseTriple>[],
|
|
362
|
+
) {
|
|
363
|
+
if (!existsSync(filePath)) {
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const lines = (await fs.readFile(filePath, 'utf8'))
|
|
368
|
+
.split('\n')
|
|
369
|
+
.filter((line) => !GENERATED_WASI_BINDING.test(line))
|
|
370
|
+
const generatedFiles = new Set<string>()
|
|
371
|
+
for (const target of wasiTargets) {
|
|
372
|
+
const suffix = target.platformArchABI.replace(/^wasm32-/, '')
|
|
373
|
+
generatedFiles.add(`${binaryName}.${suffix}.cjs`)
|
|
374
|
+
generatedFiles.add(`${binaryName}.${suffix}.d.cts`)
|
|
375
|
+
generatedFiles.add(`${binaryName}.${suffix}-browser.js`)
|
|
376
|
+
if (getWasiTarget(target)?.flavor === 'threads') {
|
|
377
|
+
generatedFiles.add('wasi-worker.mjs')
|
|
378
|
+
generatedFiles.add('wasi-worker-browser.mjs')
|
|
379
|
+
} else {
|
|
380
|
+
generatedFiles.add(`${binaryName}.${suffix}-deferred.js`)
|
|
381
|
+
generatedFiles.add(`${binaryName}.${suffix}-deferred.d.ts`)
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (generatedFiles.size > 0) {
|
|
385
|
+
while (lines[lines.length - 1] === '') {
|
|
386
|
+
lines.pop()
|
|
387
|
+
}
|
|
388
|
+
lines.push(
|
|
389
|
+
'',
|
|
390
|
+
...[...generatedFiles].map((file) => `${file} linguist-detectable=false`),
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
await fs.writeFile(filePath, `${lines.join('\n')}\n`)
|
|
175
394
|
}
|
|
176
395
|
|
|
177
396
|
async function updateCargoTomlTypeDef(
|
|
@@ -289,16 +508,70 @@ async function filterTargetsInGithubActions(
|
|
|
289
508
|
const platform = parseTriple(target).platform
|
|
290
509
|
return platform === 'darwin' || platform === 'win32'
|
|
291
510
|
})
|
|
511
|
+
const wasiTargets = enabledTargets.filter((target) => getWasiTarget(target))
|
|
292
512
|
|
|
293
513
|
// Filter the matrix configurations in the build job
|
|
294
514
|
if (yaml?.jobs?.build?.strategy?.matrix?.settings) {
|
|
295
|
-
yaml.jobs.build.strategy.matrix.settings
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
515
|
+
const settings = yaml.jobs.build.strategy.matrix.settings
|
|
516
|
+
const wasiTemplate = settings.find(
|
|
517
|
+
(setting: any) => setting.target && getWasiTarget(setting.target),
|
|
518
|
+
)
|
|
519
|
+
const wasiTemplateTarget =
|
|
520
|
+
typeof wasiTemplate?.target === 'string' ? wasiTemplate.target : undefined
|
|
521
|
+
const wasiTargetComparison = wasiTemplateTarget
|
|
522
|
+
? new RegExp(
|
|
523
|
+
`matrix\\.settings\\.target\\s*(==|!=)\\s*(['"])${wasiTemplateTarget.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\2`,
|
|
524
|
+
)
|
|
525
|
+
: undefined
|
|
526
|
+
const filteredSettings = settings.filter((setting: any) => {
|
|
527
|
+
if (setting.target && getWasiTarget(setting.target)) {
|
|
528
|
+
return false
|
|
529
|
+
}
|
|
530
|
+
if (setting.target) {
|
|
531
|
+
return enabledTargets.includes(setting.target)
|
|
532
|
+
}
|
|
533
|
+
return true
|
|
534
|
+
})
|
|
535
|
+
if (wasiTargets.length > 0 && !wasiTemplate) {
|
|
536
|
+
throw new Error('Template CI is missing a WASI build matrix entry')
|
|
537
|
+
}
|
|
538
|
+
for (const target of wasiTargets) {
|
|
539
|
+
const setting = { ...wasiTemplate }
|
|
540
|
+
const templateTarget = setting.target
|
|
541
|
+
setting.target = target
|
|
542
|
+
if (typeof setting.build === 'string') {
|
|
543
|
+
setting.build = setting.build.replaceAll(templateTarget, target)
|
|
544
|
+
}
|
|
545
|
+
filteredSettings.push(setting)
|
|
546
|
+
}
|
|
547
|
+
yaml.jobs.build.strategy.matrix.settings = filteredSettings
|
|
548
|
+
|
|
549
|
+
for (const step of yaml.jobs.build.steps ?? []) {
|
|
550
|
+
const operator =
|
|
551
|
+
typeof step.if === 'string' && wasiTargetComparison
|
|
552
|
+
? step.if.match(wasiTargetComparison)?.[1]
|
|
553
|
+
: undefined
|
|
554
|
+
if (operator === '!=') {
|
|
555
|
+
step.if = "${{ !startsWith(matrix.settings.target, 'wasm32-') }}"
|
|
556
|
+
} else if (operator === '==') {
|
|
557
|
+
step.if = "${{ startsWith(matrix.settings.target, 'wasm32-') }}"
|
|
558
|
+
}
|
|
559
|
+
if (
|
|
560
|
+
wasiTargets.length > 0 &&
|
|
561
|
+
typeof step.uses === 'string' &&
|
|
562
|
+
step.uses.startsWith('actions/upload-artifact@') &&
|
|
563
|
+
typeof step.with?.path === 'string' &&
|
|
564
|
+
step.with.path.includes('.wasm')
|
|
565
|
+
) {
|
|
566
|
+
const existingPatterns = step.with.path
|
|
567
|
+
.split('\n')
|
|
568
|
+
.map((pattern: string) => pattern.trim())
|
|
569
|
+
.filter(Boolean)
|
|
570
|
+
step.with.path = [
|
|
571
|
+
...new Set([...existingPatterns, ...WASI_CI_ARTIFACT_PATTERNS]),
|
|
572
|
+
].join('\n')
|
|
573
|
+
}
|
|
574
|
+
}
|
|
302
575
|
}
|
|
303
576
|
|
|
304
577
|
const jobsToRemove: string[] = []
|
|
@@ -342,8 +615,38 @@ async function filterTargetsInGithubActions(
|
|
|
342
615
|
}
|
|
343
616
|
}
|
|
344
617
|
|
|
345
|
-
if (
|
|
618
|
+
if (wasiTargets.length === 0) {
|
|
346
619
|
jobsToRemove.push('test-wasi')
|
|
620
|
+
} else if (yaml.jobs?.['test-wasi']) {
|
|
621
|
+
const wasiJob = yaml.jobs['test-wasi']
|
|
622
|
+
if (wasiTargets.length > 1) {
|
|
623
|
+
wasiJob.strategy = {
|
|
624
|
+
'fail-fast': false,
|
|
625
|
+
matrix: {
|
|
626
|
+
target: wasiTargets,
|
|
627
|
+
},
|
|
628
|
+
}
|
|
629
|
+
wasiJob.name = 'Test WASI target - ${{ matrix.target }}'
|
|
630
|
+
}
|
|
631
|
+
const downloadStep = wasiJob.steps?.find(
|
|
632
|
+
(step: any) =>
|
|
633
|
+
typeof step.uses === 'string' &&
|
|
634
|
+
step.uses.startsWith('actions/download-artifact@'),
|
|
635
|
+
)
|
|
636
|
+
if (downloadStep?.with) {
|
|
637
|
+
downloadStep.with.name =
|
|
638
|
+
wasiTargets.length === 1
|
|
639
|
+
? `bindings-${wasiTargets[0]}`
|
|
640
|
+
: 'bindings-${{ matrix.target }}'
|
|
641
|
+
}
|
|
642
|
+
for (const step of wasiJob.steps ?? []) {
|
|
643
|
+
if (
|
|
644
|
+
step.env &&
|
|
645
|
+
Object.prototype.hasOwnProperty.call(step.env, 'NAPI_RS_FORCE_WASI')
|
|
646
|
+
) {
|
|
647
|
+
step.env.NAPI_RS_FORCE_WASI = 'true'
|
|
648
|
+
}
|
|
649
|
+
}
|
|
347
650
|
}
|
|
348
651
|
|
|
349
652
|
if (!enabledTargets.includes('x86_64-unknown-freebsd')) {
|
|
@@ -423,17 +726,21 @@ function processOptions(options: RawNewOptions) {
|
|
|
423
726
|
throw new Error('At least one target must be enabled')
|
|
424
727
|
}
|
|
425
728
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
729
|
+
const requestedTargets = options.targets.map((target) => ({
|
|
730
|
+
target,
|
|
731
|
+
parsed: parseTriple(target),
|
|
732
|
+
}))
|
|
733
|
+
options.targets = requestedTargets.map(({ parsed }) => parsed.triple)
|
|
734
|
+
const outputTargets = new Map<string, string>()
|
|
735
|
+
for (const { target, parsed } of requestedTargets) {
|
|
736
|
+
const { platformArchABI } = parsed
|
|
737
|
+
const previous = outputTargets.get(platformArchABI)
|
|
738
|
+
if (previous) {
|
|
739
|
+
throw new Error(
|
|
740
|
+
`Targets ${previous} and ${target} produce the same ${platformArchABI} artifact set. Choose one target spelling.`,
|
|
435
741
|
)
|
|
436
742
|
}
|
|
743
|
+
outputTargets.set(platformArchABI, target)
|
|
437
744
|
}
|
|
438
745
|
|
|
439
746
|
return applyDefaultNewOptions(options) as NewOptions
|
|
@@ -471,7 +778,7 @@ export async function newProject(userOptions: RawNewOptions) {
|
|
|
471
778
|
await copyDirectory(
|
|
472
779
|
templatePath,
|
|
473
780
|
options.path,
|
|
474
|
-
options.targets.
|
|
781
|
+
options.targets.some((target) => getWasiTarget(target) !== undefined),
|
|
475
782
|
)
|
|
476
783
|
|
|
477
784
|
// Rename project using the rename API
|
|
@@ -493,7 +800,12 @@ export async function newProject(userOptions: RawNewOptions) {
|
|
|
493
800
|
// Filter targets in package.json
|
|
494
801
|
const packageJsonPath = path.join(options.path, 'package.json')
|
|
495
802
|
if (existsSync(packageJsonPath)) {
|
|
496
|
-
await filterTargetsInPackageJson(
|
|
803
|
+
await filterTargetsInPackageJson(
|
|
804
|
+
packageJsonPath,
|
|
805
|
+
options.targets,
|
|
806
|
+
options.enableTypeDef,
|
|
807
|
+
packageManager,
|
|
808
|
+
)
|
|
497
809
|
}
|
|
498
810
|
|
|
499
811
|
// Filter targets in GitHub Actions CI
|
|
@@ -519,7 +831,14 @@ export async function newProject(userOptions: RawNewOptions) {
|
|
|
519
831
|
if (!pkgJson.engines) {
|
|
520
832
|
pkgJson.engines = {}
|
|
521
833
|
}
|
|
522
|
-
|
|
834
|
+
const nodeEngineRequirement = napiEngineRequirement(
|
|
835
|
+
options.minNodeApiVersion,
|
|
836
|
+
)
|
|
837
|
+
pkgJson.engines.node = options.targets.every(
|
|
838
|
+
(target) => parseTriple(target).platform === 'wasi',
|
|
839
|
+
)
|
|
840
|
+
? restrictWasiNodeEngine(nodeEngineRequirement)
|
|
841
|
+
: nodeEngineRequirement
|
|
523
842
|
|
|
524
843
|
// Update license if different from template
|
|
525
844
|
if (options.license && pkgJson.license !== options.license) {
|