@napi-rs/cli 3.0.0-alpha.1 → 3.0.0-alpha.100
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/cli.mjs +1 -1
- package/dist/api/__tests__/create-npm-dirs.spec.d.ts +1 -0
- package/dist/api/__tests__/new.spec.d.ts +1 -0
- package/dist/api/build.d.ts +2 -2
- package/dist/api/create-npm-dirs.d.ts +5 -0
- package/dist/api/templates/index.d.ts +0 -7
- package/dist/api/templates/js-binding.d.ts +2 -1
- package/dist/api/templates/load-wasi-template.d.ts +2 -0
- package/dist/api/templates/wasi-worker-template.d.ts +2 -0
- package/dist/cli.js +3961 -14
- package/dist/def/artifacts.d.ts +21 -1
- package/dist/def/build.d.ts +167 -4
- package/dist/def/create-npm-dirs.d.ts +10 -0
- package/dist/def/new.d.ts +25 -7
- package/dist/def/pre-publish.d.ts +21 -2
- package/dist/def/rename.d.ts +16 -6
- package/dist/def/universalize.d.ts +10 -0
- package/dist/def/version.d.ts +10 -0
- package/dist/index.cjs +10142 -20524
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3711 -29
- package/dist/utils/__tests__/config.spec.d.ts +1 -0
- package/dist/utils/config.d.ts +70 -6
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/metadata.d.ts +13 -1
- package/dist/utils/misc.d.ts +3 -3
- package/dist/utils/read-config.d.ts +7 -0
- package/dist/utils/target.d.ts +9 -6
- package/dist/utils/typegen.d.ts +4 -1
- package/dist/utils/version.d.ts +2 -1
- package/package.json +60 -24
- package/src/api/__tests__/create-npm-dirs.spec.ts +210 -0
- package/src/api/__tests__/new.spec.ts +429 -0
- package/src/api/artifacts.ts +83 -8
- package/src/api/build.ts +682 -134
- package/src/api/create-npm-dirs.ts +64 -13
- package/src/api/new.ts +389 -125
- package/src/api/pre-publish.ts +27 -16
- package/src/api/rename.ts +103 -17
- package/src/api/templates/index.ts +0 -7
- package/src/api/templates/js-binding.ts +212 -107
- package/src/api/templates/load-wasi-template.ts +216 -0
- package/src/api/templates/wasi-worker-template.ts +122 -0
- package/src/api/universalize.ts +13 -8
- package/src/api/version.ts +5 -2
- package/src/commands/artifacts.ts +2 -2
- package/src/commands/build.ts +1 -1
- package/src/commands/new.ts +46 -49
- package/src/def/artifacts.ts +22 -3
- package/src/def/build.ts +83 -8
- package/src/def/create-npm-dirs.ts +9 -0
- package/src/def/new.ts +28 -3
- package/src/def/pre-publish.ts +24 -3
- package/src/def/rename.ts +11 -2
- package/src/def/universalize.ts +9 -0
- package/src/def/version.ts +9 -0
- package/src/index.ts +2 -0
- package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
- package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
- package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +56 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +703 -164
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/version.spec.ts.md +9 -8
- package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
- package/src/utils/__tests__/config.spec.ts +81 -0
- package/src/utils/__tests__/typegen.spec.ts +19 -4
- package/src/utils/cargo.ts +2 -2
- package/src/utils/config.ts +147 -13
- package/src/utils/index.ts +1 -1
- package/src/utils/log.ts +1 -1
- package/src/utils/metadata.ts +52 -14
- package/src/utils/misc.ts +21 -7
- package/src/utils/read-config.ts +20 -0
- package/src/utils/target.ts +53 -9
- package/src/utils/typegen.ts +100 -40
- package/src/utils/version.ts +11 -9
- package/dist/api/artifacts.js +0 -50
- package/dist/api/build.js +0 -404
- package/dist/api/create-npm-dirs.js +0 -63
- package/dist/api/new.js +0 -154
- package/dist/api/pre-publish.js +0 -157
- package/dist/api/rename.js +0 -28
- package/dist/api/templates/.gitignore.d.ts +0 -1
- package/dist/api/templates/.gitignore.js +0 -198
- package/dist/api/templates/.npmignore.d.ts +0 -1
- package/dist/api/templates/.npmignore.js +0 -14
- package/dist/api/templates/build.rs.d.ts +0 -1
- package/dist/api/templates/build.rs.js +0 -4
- package/dist/api/templates/cargo.toml.d.ts +0 -6
- package/dist/api/templates/cargo.toml.js +0 -25
- package/dist/api/templates/ci-template.d.ts +0 -1
- package/dist/api/templates/ci-template.js +0 -566
- package/dist/api/templates/ci.yml.d.ts +0 -1
- package/dist/api/templates/ci.yml.js +0 -92
- package/dist/api/templates/index.js +0 -8
- package/dist/api/templates/js-binding.js +0 -124
- package/dist/api/templates/lib.rs.d.ts +0 -1
- package/dist/api/templates/lib.rs.js +0 -10
- package/dist/api/templates/package.json.d.ts +0 -8
- package/dist/api/templates/package.json.js +0 -30
- package/dist/api/universalize.js +0 -38
- package/dist/api/version.js +0 -16
- package/dist/commands/artifacts.js +0 -19
- package/dist/commands/build.js +0 -34
- package/dist/commands/create-npm-dirs.js +0 -7
- package/dist/commands/help.js +0 -12
- package/dist/commands/new.js +0 -112
- package/dist/commands/pre-publish.js +0 -8
- package/dist/commands/rename.js +0 -7
- package/dist/commands/universalize.js +0 -7
- package/dist/commands/version.js +0 -7
- package/dist/def/artifacts.js +0 -38
- package/dist/def/build.js +0 -105
- package/dist/def/commands/artifacts.d.ts +0 -15
- package/dist/def/commands/artifacts.js +0 -29
- package/dist/def/commands/build.d.ts +0 -53
- package/dist/def/commands/build.js +0 -105
- package/dist/def/commands/create-npm-dirs.d.ts +0 -15
- package/dist/def/commands/create-npm-dirs.js +0 -29
- package/dist/def/commands/new.d.ts +0 -27
- package/dist/def/commands/new.js +0 -53
- package/dist/def/commands/pre-publish.d.ts +0 -23
- package/dist/def/commands/pre-publish.js +0 -45
- package/dist/def/commands/rename.d.ts +0 -25
- package/dist/def/commands/rename.js +0 -49
- package/dist/def/commands/universalize.d.ts +0 -13
- package/dist/def/commands/universalize.js +0 -25
- package/dist/def/commands/version.d.ts +0 -13
- package/dist/def/commands/version.js +0 -25
- package/dist/def/create-npm-dirs.js +0 -38
- package/dist/def/new.js +0 -66
- package/dist/def/options/artifacts.d.ts +0 -35
- package/dist/def/options/artifacts.js +0 -11
- package/dist/def/options/build.d.ts +0 -97
- package/dist/def/options/build.js +0 -3
- package/dist/def/options/create-npm-dirs.d.ts +0 -35
- package/dist/def/options/create-npm-dirs.js +0 -11
- package/dist/def/options/new.d.ts +0 -79
- package/dist/def/options/new.js +0 -15
- package/dist/def/options/pre-publish.d.ts +0 -65
- package/dist/def/options/pre-publish.js +0 -13
- package/dist/def/options/rename.d.ts +0 -75
- package/dist/def/options/rename.js +0 -11
- package/dist/def/options/universalize.d.ts +0 -28
- package/dist/def/options/universalize.js +0 -10
- package/dist/def/options/version.d.ts +0 -28
- package/dist/def/options/version.js +0 -10
- package/dist/def/pre-publish.js +0 -56
- package/dist/def/rename.js +0 -58
- package/dist/def/universalize.js +0 -33
- package/dist/def/version.js +0 -33
- package/dist/utils/__tests__/target.spec.js +0 -10
- package/dist/utils/__tests__/typegen.spec.js +0 -37
- package/dist/utils/__tests__/version.spec.js +0 -5
- package/dist/utils/cargo.js +0 -33
- package/dist/utils/ci.d.ts +0 -11
- package/dist/utils/ci.js +0 -86
- package/dist/utils/config.js +0 -42
- package/dist/utils/index.js +0 -9
- package/dist/utils/log.js +0 -14
- package/dist/utils/metadata.js +0 -19
- package/dist/utils/misc.js +0 -35
- package/dist/utils/target.js +0 -109
- package/dist/utils/typegen.js +0 -158
- package/dist/utils/version.js +0 -59
- package/src/api/templates/.gitignore.ts +0 -198
- package/src/api/templates/.npmignore.ts +0 -14
- package/src/api/templates/build.rs.ts +0 -4
- package/src/api/templates/cargo.toml.ts +0 -35
- package/src/api/templates/ci-template.ts +0 -566
- package/src/api/templates/ci.yml.ts +0 -116
- package/src/api/templates/lib.rs.ts +0 -10
- package/src/api/templates/package.json.ts +0 -44
- package/src/utils/ci.ts +0 -102
package/src/api/new.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { exec, execSync } from 'node:child_process'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { homedir } from 'node:os'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { promises as fs } from 'node:fs'
|
|
6
|
+
|
|
7
|
+
import { load as yamlLoad, dump as yamlDump } from 'js-yaml'
|
|
2
8
|
|
|
3
9
|
import {
|
|
4
10
|
applyDefaultNewOptions,
|
|
@@ -6,35 +12,289 @@ import {
|
|
|
6
12
|
} from '../def/new.js'
|
|
7
13
|
import {
|
|
8
14
|
AVAILABLE_TARGETS,
|
|
9
|
-
CLI_VERSION,
|
|
10
15
|
debugFactory,
|
|
11
16
|
DEFAULT_TARGETS,
|
|
12
17
|
mkdirAsync,
|
|
13
|
-
|
|
18
|
+
readdirAsync,
|
|
19
|
+
statAsync,
|
|
20
|
+
SupportedPackageManager,
|
|
14
21
|
} from '../utils/index.js'
|
|
15
22
|
import { napiEngineRequirement } from '../utils/version.js'
|
|
23
|
+
import { renameProject } from './rename.js'
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
createBuildRs,
|
|
19
|
-
createCargoToml,
|
|
20
|
-
createGithubActionsCIYml,
|
|
21
|
-
createLibRs,
|
|
22
|
-
createPackageJson,
|
|
23
|
-
gitIgnore,
|
|
24
|
-
npmIgnore,
|
|
25
|
-
} from './templates/index.js'
|
|
25
|
+
// Template imports removed as we're now using external templates
|
|
26
26
|
|
|
27
27
|
const debug = debugFactory('new')
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
type NewOptions = Required<RawNewOptions>
|
|
30
|
+
|
|
31
|
+
const TEMPLATE_REPOS = {
|
|
32
|
+
yarn: 'https://github.com/napi-rs/package-template',
|
|
33
|
+
pnpm: 'https://github.com/napi-rs/package-template-pnpm',
|
|
34
|
+
} as const
|
|
35
|
+
|
|
36
|
+
async function checkGitCommand(): Promise<boolean> {
|
|
37
|
+
try {
|
|
38
|
+
await new Promise((resolve) => {
|
|
39
|
+
const cp = exec('git --version')
|
|
40
|
+
cp.on('error', () => {
|
|
41
|
+
resolve(false)
|
|
42
|
+
})
|
|
43
|
+
cp.on('exit', (code) => {
|
|
44
|
+
if (code === 0) {
|
|
45
|
+
resolve(true)
|
|
46
|
+
} else {
|
|
47
|
+
resolve(false)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
return true
|
|
52
|
+
} catch {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function ensureCacheDir(
|
|
58
|
+
packageManager: SupportedPackageManager,
|
|
59
|
+
): Promise<string> {
|
|
60
|
+
const cacheDir = path.join(homedir(), '.napi-rs', 'template', packageManager)
|
|
61
|
+
await mkdirAsync(cacheDir, { recursive: true })
|
|
62
|
+
return cacheDir
|
|
32
63
|
}
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
async function downloadTemplate(
|
|
66
|
+
packageManager: SupportedPackageManager,
|
|
67
|
+
cacheDir: string,
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
const repoUrl = TEMPLATE_REPOS[packageManager]
|
|
70
|
+
const templatePath = path.join(cacheDir, 'repo')
|
|
71
|
+
|
|
72
|
+
if (existsSync(templatePath)) {
|
|
73
|
+
debug(`Template cache found at ${templatePath}, updating...`)
|
|
74
|
+
try {
|
|
75
|
+
// Fetch latest changes and reset to remote
|
|
76
|
+
await new Promise<void>((resolve, reject) => {
|
|
77
|
+
const cp = exec('git fetch origin', { cwd: templatePath })
|
|
78
|
+
cp.on('error', reject)
|
|
79
|
+
cp.on('exit', (code) => {
|
|
80
|
+
if (code === 0) {
|
|
81
|
+
resolve()
|
|
82
|
+
} else {
|
|
83
|
+
reject(
|
|
84
|
+
new Error(
|
|
85
|
+
`Failed to fetch latest changes, git process exited with code ${code}`,
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
execSync('git reset --hard origin/main', {
|
|
92
|
+
cwd: templatePath,
|
|
93
|
+
stdio: 'ignore',
|
|
94
|
+
})
|
|
95
|
+
debug('Template updated successfully')
|
|
96
|
+
} catch (error) {
|
|
97
|
+
debug(`Failed to update template: ${error}`)
|
|
98
|
+
throw new Error(`Failed to update template from ${repoUrl}: ${error}`)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
debug(`Cloning template from ${repoUrl}...`)
|
|
102
|
+
try {
|
|
103
|
+
execSync(`git clone ${repoUrl} repo`, { cwd: cacheDir, stdio: 'inherit' })
|
|
104
|
+
debug('Template cloned successfully')
|
|
105
|
+
} catch (error) {
|
|
106
|
+
throw new Error(`Failed to clone template from ${repoUrl}: ${error}`)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function copyDirectory(
|
|
112
|
+
src: string,
|
|
113
|
+
dest: string,
|
|
114
|
+
includeWasiBindings: boolean,
|
|
115
|
+
): Promise<void> {
|
|
116
|
+
await mkdirAsync(dest, { recursive: true })
|
|
117
|
+
const entries = await fs.readdir(src, { withFileTypes: true })
|
|
118
|
+
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
const srcPath = path.join(src, entry.name)
|
|
121
|
+
const destPath = path.join(dest, entry.name)
|
|
122
|
+
|
|
123
|
+
// Skip .git directory
|
|
124
|
+
if (entry.name === '.git') {
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
await copyDirectory(srcPath, destPath, includeWasiBindings)
|
|
130
|
+
} else {
|
|
131
|
+
if (
|
|
132
|
+
!includeWasiBindings &&
|
|
133
|
+
(entry.name.endsWith('.wasi-browser.js') ||
|
|
134
|
+
entry.name.endsWith('.wasi.cjs') ||
|
|
135
|
+
entry.name.endsWith('wasi-worker.browser.mjs ') ||
|
|
136
|
+
entry.name.endsWith('wasi-worker.mjs') ||
|
|
137
|
+
entry.name.endsWith('browser.js'))
|
|
138
|
+
) {
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
await fs.copyFile(srcPath, destPath)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function filterTargetsInPackageJson(
|
|
147
|
+
filePath: string,
|
|
148
|
+
enabledTargets: string[],
|
|
149
|
+
): Promise<void> {
|
|
150
|
+
const content = await fs.readFile(filePath, 'utf-8')
|
|
151
|
+
const packageJson = JSON.parse(content)
|
|
152
|
+
|
|
153
|
+
// Filter napi.targets
|
|
154
|
+
if (packageJson.napi?.targets) {
|
|
155
|
+
packageJson.napi.targets = packageJson.napi.targets.filter(
|
|
156
|
+
(target: string) => enabledTargets.includes(target),
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await fs.writeFile(filePath, JSON.stringify(packageJson, null, 2) + '\n')
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function filterTargetsInGithubActions(
|
|
164
|
+
filePath: string,
|
|
165
|
+
enabledTargets: string[],
|
|
166
|
+
): Promise<void> {
|
|
167
|
+
const content = await fs.readFile(filePath, 'utf-8')
|
|
168
|
+
const yaml = yamlLoad(content) as any
|
|
169
|
+
|
|
170
|
+
const macOSAndWindowsTargets = new Set([
|
|
171
|
+
'x86_64-pc-windows-msvc',
|
|
172
|
+
'aarch64-pc-windows-msvc',
|
|
173
|
+
'x86_64-apple-darwin',
|
|
174
|
+
])
|
|
175
|
+
|
|
176
|
+
const linuxTargets = new Set([
|
|
177
|
+
'x86_64-unknown-linux-gnu',
|
|
178
|
+
'x86_64-unknown-linux-musl',
|
|
179
|
+
'aarch64-unknown-linux-gnu',
|
|
180
|
+
'aarch64-unknown-linux-musl',
|
|
181
|
+
'armv7-unknown-linux-gnueabihf',
|
|
182
|
+
'armv7-unknown-linux-musleabihf',
|
|
183
|
+
'riscv64gc-unknown-linux-gnu',
|
|
184
|
+
'powerpc64le-unknown-linux-gnu',
|
|
185
|
+
's390x-unknown-linux-gnu',
|
|
186
|
+
'aarch64-linux-android',
|
|
187
|
+
'armv7-linux-androideabi',
|
|
188
|
+
])
|
|
189
|
+
|
|
190
|
+
// Check if any Linux targets are enabled
|
|
191
|
+
const hasLinuxTargets = enabledTargets.some((target) =>
|
|
192
|
+
linuxTargets.has(target),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
// Filter the matrix configurations in the build job
|
|
196
|
+
if (yaml?.jobs?.build?.strategy?.matrix?.settings) {
|
|
197
|
+
yaml.jobs.build.strategy.matrix.settings =
|
|
198
|
+
yaml.jobs.build.strategy.matrix.settings.filter((setting: any) => {
|
|
199
|
+
if (setting.target) {
|
|
200
|
+
return enabledTargets.includes(setting.target)
|
|
201
|
+
}
|
|
202
|
+
return true
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const jobsToRemove: string[] = []
|
|
207
|
+
|
|
208
|
+
if (enabledTargets.every((target) => !macOSAndWindowsTargets.has(target))) {
|
|
209
|
+
jobsToRemove.push('test-macOS-windows-binding')
|
|
210
|
+
} else {
|
|
211
|
+
// Filter the matrix configurations in the test-macOS-windows-binding job
|
|
212
|
+
if (
|
|
213
|
+
yaml?.jobs?.['test-macOS-windows-binding']?.strategy?.matrix?.settings
|
|
214
|
+
) {
|
|
215
|
+
yaml.jobs['test-macOS-windows-binding'].strategy.matrix.settings =
|
|
216
|
+
yaml.jobs['test-macOS-windows-binding'].strategy.matrix.settings.filter(
|
|
217
|
+
(setting: any) => {
|
|
218
|
+
if (setting.target) {
|
|
219
|
+
return enabledTargets.includes(setting.target)
|
|
220
|
+
}
|
|
221
|
+
return true
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// If no Linux targets are enabled, remove Linux-specific jobs
|
|
228
|
+
if (!hasLinuxTargets) {
|
|
229
|
+
// Remove test-linux-binding job
|
|
230
|
+
if (yaml?.jobs?.['test-linux-binding']) {
|
|
231
|
+
jobsToRemove.push('test-linux-binding')
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
// Filter the matrix configurations in the test-linux-x64-gnu-binding job
|
|
235
|
+
if (yaml?.jobs?.['test-linux-binding']?.strategy?.matrix?.target) {
|
|
236
|
+
yaml.jobs['test-linux-binding'].strategy.matrix.target = yaml.jobs[
|
|
237
|
+
'test-linux-binding'
|
|
238
|
+
].strategy.matrix.target.filter((target: string) => {
|
|
239
|
+
if (target) {
|
|
240
|
+
return enabledTargets.includes(target)
|
|
241
|
+
}
|
|
242
|
+
return true
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (!enabledTargets.includes('wasm32-wasip1-threads')) {
|
|
248
|
+
jobsToRemove.push('test-wasi')
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (!enabledTargets.includes('x86_64-unknown-freebsd')) {
|
|
252
|
+
jobsToRemove.push('build-freebsd')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Filter other test jobs based on target
|
|
256
|
+
for (const [jobName, jobConfig] of Object.entries(yaml.jobs || {})) {
|
|
257
|
+
if (
|
|
258
|
+
jobName.startsWith('test-') &&
|
|
259
|
+
jobName !== 'test-macOS-windows-binding' &&
|
|
260
|
+
jobName !== 'test-linux-x64-gnu-binding'
|
|
261
|
+
) {
|
|
262
|
+
// Extract target from job name or config
|
|
263
|
+
const job = jobConfig as any
|
|
264
|
+
if (job.strategy?.matrix?.settings?.[0]?.target) {
|
|
265
|
+
const target = job.strategy.matrix.settings[0].target
|
|
266
|
+
if (!enabledTargets.includes(target)) {
|
|
267
|
+
jobsToRemove.push(jobName)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Remove jobs for disabled targets
|
|
274
|
+
for (const jobName of jobsToRemove) {
|
|
275
|
+
delete yaml.jobs[jobName]
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (Array.isArray(yaml.jobs?.publish?.needs)) {
|
|
279
|
+
yaml.jobs.publish.needs = yaml.jobs.publish.needs.filter(
|
|
280
|
+
(need: string) => !jobsToRemove.includes(need),
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Write back the filtered YAML
|
|
285
|
+
const updatedYaml = yamlDump(yaml, {
|
|
286
|
+
lineWidth: -1,
|
|
287
|
+
noRefs: true,
|
|
288
|
+
sortKeys: false,
|
|
289
|
+
})
|
|
290
|
+
await fs.writeFile(filePath, updatedYaml)
|
|
291
|
+
}
|
|
35
292
|
|
|
36
293
|
function processOptions(options: RawNewOptions) {
|
|
37
294
|
debug('Processing options...')
|
|
295
|
+
if (!options.path) {
|
|
296
|
+
throw new Error('Please provide the path as the argument')
|
|
297
|
+
}
|
|
38
298
|
options.path = path.resolve(process.cwd(), options.path)
|
|
39
299
|
debug(`Resolved target path to: ${options.path}`)
|
|
40
300
|
|
|
@@ -54,6 +314,20 @@ function processOptions(options: RawNewOptions) {
|
|
|
54
314
|
throw new Error('At least one target must be enabled')
|
|
55
315
|
}
|
|
56
316
|
}
|
|
317
|
+
if (
|
|
318
|
+
options.targets.some((target) => target === 'wasm32-wasi-preview1-threads')
|
|
319
|
+
) {
|
|
320
|
+
const out = execSync(`rustup target list`, {
|
|
321
|
+
encoding: 'utf8',
|
|
322
|
+
})
|
|
323
|
+
if (out.includes('wasm32-wasip1-threads')) {
|
|
324
|
+
options.targets = options.targets.map((target) =>
|
|
325
|
+
target === 'wasm32-wasi-preview1-threads'
|
|
326
|
+
? 'wasm32-wasip1-threads'
|
|
327
|
+
: target,
|
|
328
|
+
)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
57
331
|
|
|
58
332
|
return applyDefaultNewOptions(options) as NewOptions
|
|
59
333
|
}
|
|
@@ -67,134 +341,124 @@ export async function newProject(userOptions: RawNewOptions) {
|
|
|
67
341
|
debug('Targets to be enabled:')
|
|
68
342
|
debug(options.targets)
|
|
69
343
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await mkdirAsync(options.path, { recursive: true })
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
throw new Error(`Failed to create target directory: ${options.path}`, {
|
|
79
|
-
cause: e,
|
|
80
|
-
})
|
|
344
|
+
// Check if git is available
|
|
345
|
+
if (!(await checkGitCommand())) {
|
|
346
|
+
throw new Error(
|
|
347
|
+
'Git is not installed or not available in PATH. Please install Git to continue.',
|
|
348
|
+
)
|
|
81
349
|
}
|
|
82
350
|
|
|
83
|
-
|
|
84
|
-
debug(`Project created at: ${options.path}`)
|
|
85
|
-
}
|
|
351
|
+
const packageManager = options.packageManager as SupportedPackageManager
|
|
86
352
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
generateCargoToml,
|
|
90
|
-
generateLibRs,
|
|
91
|
-
generateBuildRs,
|
|
92
|
-
generatePackageJson,
|
|
93
|
-
generateGithubWorkflow,
|
|
94
|
-
generateIgnoreFiles,
|
|
95
|
-
].flatMap((generator) => {
|
|
96
|
-
const output = generator(options)
|
|
97
|
-
|
|
98
|
-
if (!output) {
|
|
99
|
-
return []
|
|
100
|
-
}
|
|
353
|
+
// Ensure target directory exists and is empty
|
|
354
|
+
await ensurePath(options.path, options.dryRun)
|
|
101
355
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
} else {
|
|
108
|
-
return [{ ...output, target: path.join(options.path, output.target) }]
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
}
|
|
356
|
+
if (!options.dryRun) {
|
|
357
|
+
try {
|
|
358
|
+
// Download or update template
|
|
359
|
+
const cacheDir = await ensureCacheDir(packageManager)
|
|
360
|
+
await downloadTemplate(packageManager, cacheDir)
|
|
112
361
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
deriveFeatures: options.enableTypeDef ? ['type-def'] : [],
|
|
121
|
-
}),
|
|
122
|
-
}
|
|
123
|
-
}
|
|
362
|
+
// Copy template files to target directory
|
|
363
|
+
const templatePath = path.join(cacheDir, 'repo')
|
|
364
|
+
await copyDirectory(
|
|
365
|
+
templatePath,
|
|
366
|
+
options.path,
|
|
367
|
+
options.targets.includes('wasm32-wasip1-threads'),
|
|
368
|
+
)
|
|
124
369
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
370
|
+
// Rename project using the rename API
|
|
371
|
+
await renameProject({
|
|
372
|
+
cwd: options.path,
|
|
373
|
+
name: options.name,
|
|
374
|
+
binaryName: getBinaryName(options.name),
|
|
375
|
+
})
|
|
131
376
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
377
|
+
// Filter targets in package.json
|
|
378
|
+
const packageJsonPath = path.join(options.path, 'package.json')
|
|
379
|
+
if (existsSync(packageJsonPath)) {
|
|
380
|
+
await filterTargetsInPackageJson(packageJsonPath, options.targets)
|
|
381
|
+
}
|
|
138
382
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
383
|
+
// Filter targets in GitHub Actions CI
|
|
384
|
+
const ciPath = path.join(options.path, '.github', 'workflows', 'CI.yml')
|
|
385
|
+
if (existsSync(ciPath) && options.enableGithubActions) {
|
|
386
|
+
await filterTargetsInGithubActions(ciPath, options.targets)
|
|
387
|
+
} else if (
|
|
388
|
+
!options.enableGithubActions &&
|
|
389
|
+
existsSync(path.join(options.path, '.github'))
|
|
390
|
+
) {
|
|
391
|
+
// Remove .github directory if GitHub Actions is not enabled
|
|
392
|
+
await fs.rm(path.join(options.path, '.github'), {
|
|
393
|
+
recursive: true,
|
|
394
|
+
force: true,
|
|
395
|
+
})
|
|
396
|
+
}
|
|
152
397
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
398
|
+
// Update package.json with additional configurations
|
|
399
|
+
const pkgJsonContent = await fs.readFile(packageJsonPath, 'utf-8')
|
|
400
|
+
const pkgJson = JSON.parse(pkgJsonContent)
|
|
401
|
+
|
|
402
|
+
// Update engine requirement
|
|
403
|
+
if (!pkgJson.engines) {
|
|
404
|
+
pkgJson.engines = {}
|
|
405
|
+
}
|
|
406
|
+
pkgJson.engines.node = napiEngineRequirement(options.minNodeApiVersion)
|
|
157
407
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
408
|
+
// Update license if different from template
|
|
409
|
+
if (options.license && pkgJson.license !== options.license) {
|
|
410
|
+
pkgJson.license = options.license
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Update test framework if needed
|
|
414
|
+
if (options.testFramework !== 'ava') {
|
|
415
|
+
// This would require more complex logic to update test scripts and dependencies
|
|
416
|
+
debug(
|
|
417
|
+
`Test framework ${options.testFramework} requested but not yet implemented`,
|
|
418
|
+
)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
await fs.writeFile(
|
|
422
|
+
packageJsonPath,
|
|
423
|
+
JSON.stringify(pkgJson, null, 2) + '\n',
|
|
424
|
+
)
|
|
425
|
+
} catch (error) {
|
|
426
|
+
throw new Error(`Failed to create project: ${error}`)
|
|
427
|
+
}
|
|
164
428
|
}
|
|
165
|
-
}
|
|
166
429
|
|
|
167
|
-
|
|
168
|
-
return [
|
|
169
|
-
{
|
|
170
|
-
target: './.gitignore',
|
|
171
|
-
content: gitIgnore,
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
target: './.npmignore',
|
|
175
|
-
content: npmIgnore,
|
|
176
|
-
},
|
|
177
|
-
]
|
|
430
|
+
debug(`Project created at: ${options.path}`)
|
|
178
431
|
}
|
|
179
432
|
|
|
180
|
-
async function
|
|
181
|
-
|
|
182
|
-
if (!output) {
|
|
183
|
-
continue
|
|
184
|
-
}
|
|
433
|
+
async function ensurePath(path: string, dryRun = false) {
|
|
434
|
+
const stat = await statAsync(path, {}).catch(() => undefined)
|
|
185
435
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
|
|
436
|
+
// file descriptor exists
|
|
437
|
+
if (stat) {
|
|
438
|
+
if (stat.isFile()) {
|
|
439
|
+
throw new Error(
|
|
440
|
+
`Path ${path} for creating new napi-rs project already exists and it's not a directory.`,
|
|
441
|
+
)
|
|
442
|
+
} else if (stat.isDirectory()) {
|
|
443
|
+
const files = await readdirAsync(path)
|
|
444
|
+
if (files.length) {
|
|
445
|
+
throw new Error(
|
|
446
|
+
`Path ${path} for creating new napi-rs project already exists and it's not empty.`,
|
|
447
|
+
)
|
|
448
|
+
}
|
|
191
449
|
}
|
|
450
|
+
}
|
|
192
451
|
|
|
452
|
+
if (!dryRun) {
|
|
193
453
|
try {
|
|
194
|
-
|
|
195
|
-
|
|
454
|
+
debug(`Try to create target directory: ${path}`)
|
|
455
|
+
if (!dryRun) {
|
|
456
|
+
await mkdirAsync(path, { recursive: true })
|
|
457
|
+
}
|
|
196
458
|
} catch (e) {
|
|
197
|
-
throw new Error(`Failed to
|
|
459
|
+
throw new Error(`Failed to create target directory: ${path}`, {
|
|
460
|
+
cause: e,
|
|
461
|
+
})
|
|
198
462
|
}
|
|
199
463
|
}
|
|
200
464
|
}
|
package/src/api/pre-publish.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { execSync } from 'child_process'
|
|
2
|
-
import { existsSync, statSync } from 'fs'
|
|
3
|
-
import { join,
|
|
1
|
+
import { execSync } from 'node:child_process'
|
|
2
|
+
import { existsSync, statSync } from 'node:fs'
|
|
3
|
+
import { join, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
import { Octokit } from '@octokit/rest'
|
|
6
6
|
|
|
@@ -31,10 +31,13 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
31
31
|
|
|
32
32
|
const options = applyDefaultPrePublishOptions(userOptions)
|
|
33
33
|
|
|
34
|
-
const packageJsonPath =
|
|
34
|
+
const packageJsonPath = resolve(options.cwd, options.packageJsonPath)
|
|
35
35
|
|
|
36
36
|
const { packageJson, targets, packageName, binaryName, npmClient } =
|
|
37
|
-
await readNapiConfig(
|
|
37
|
+
await readNapiConfig(
|
|
38
|
+
packageJsonPath,
|
|
39
|
+
options.configPath ? resolve(options.cwd, options.configPath) : undefined,
|
|
40
|
+
)
|
|
38
41
|
|
|
39
42
|
async function createGhRelease(packageName: string, version: string) {
|
|
40
43
|
if (!options.ghRelease) {
|
|
@@ -129,11 +132,14 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
129
132
|
if (!options.dryRun) {
|
|
130
133
|
await version(userOptions)
|
|
131
134
|
await updatePackageJson(packageJsonPath, {
|
|
132
|
-
optionalDependencies: targets.reduce(
|
|
133
|
-
deps
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
optionalDependencies: targets.reduce(
|
|
136
|
+
(deps, target) => {
|
|
137
|
+
deps[`${packageName}-${target.platformArchABI}`] = packageJson.version
|
|
138
|
+
|
|
139
|
+
return deps
|
|
140
|
+
},
|
|
141
|
+
{} as Record<string, string>,
|
|
142
|
+
),
|
|
137
143
|
})
|
|
138
144
|
}
|
|
139
145
|
|
|
@@ -147,7 +153,9 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
147
153
|
options.npmDir,
|
|
148
154
|
`${target.platformArchABI}`,
|
|
149
155
|
)
|
|
150
|
-
const
|
|
156
|
+
const ext =
|
|
157
|
+
target.platform === 'wasi' || target.platform === 'wasm' ? 'wasm' : 'node'
|
|
158
|
+
const filename = `${binaryName}.${target.platformArchABI}.${ext}`
|
|
151
159
|
const dstPath = join(pkgDir, filename)
|
|
152
160
|
|
|
153
161
|
if (!options.dryRun) {
|
|
@@ -156,10 +164,12 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
156
164
|
continue
|
|
157
165
|
}
|
|
158
166
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
167
|
+
if (!options.skipOptionalPublish) {
|
|
168
|
+
execSync(`${npmClient} publish`, {
|
|
169
|
+
cwd: pkgDir,
|
|
170
|
+
env: process.env,
|
|
171
|
+
})
|
|
172
|
+
}
|
|
163
173
|
|
|
164
174
|
if (options.ghRelease && repo && owner) {
|
|
165
175
|
debug.info(`Creating GitHub release ${pkgInfo.tag}`)
|
|
@@ -184,7 +194,8 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
184
194
|
'content-length': dstFileStats.size,
|
|
185
195
|
'content-type': 'application/octet-stream',
|
|
186
196
|
},
|
|
187
|
-
|
|
197
|
+
// @ts-expect-error octokit types are wrong
|
|
198
|
+
data: await readFileAsync(dstPath),
|
|
188
199
|
})
|
|
189
200
|
debug.info(`GitHub release created`)
|
|
190
201
|
debug.info(`Download URL: %s`, assetInfo.data.browser_download_url)
|