create-jst 0.4.4 → 0.4.8
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/package.json
CHANGED
|
@@ -4,6 +4,7 @@ export function createProjectInitializer({ onProgress = () => undefined, project
|
|
|
4
4
|
await projectGateway.assertDestinationIsEmpty(specification.destination)
|
|
5
5
|
const temporaryDestination = await projectGateway.prepareDestination(specification.destination)
|
|
6
6
|
const temporarySpecification = Object.freeze({ ...specification, destination: temporaryDestination })
|
|
7
|
+
let rollbackDestination = temporaryDestination
|
|
7
8
|
|
|
8
9
|
try {
|
|
9
10
|
onProgress({ type: 'template.download.started', specification })
|
|
@@ -28,16 +29,17 @@ export function createProjectInitializer({ onProgress = () => undefined, project
|
|
|
28
29
|
onProgress({ type: 'git.initialization.started', specification })
|
|
29
30
|
await projectGateway.initializeGit(temporaryDestination)
|
|
30
31
|
}
|
|
32
|
+
await projectGateway.commitDestination(temporaryDestination, specification.destination)
|
|
33
|
+
rollbackDestination = specification.destination
|
|
31
34
|
if (specification.install) {
|
|
32
35
|
onProgress({ type: 'dependencies.installation.started', specification })
|
|
33
|
-
await projectGateway.installDependencies(
|
|
36
|
+
await projectGateway.installDependencies(specification.destination, specification.packageManager)
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
await projectGateway.commitDestination(temporaryDestination, specification.destination)
|
|
37
39
|
onProgress({ type: 'project.initialized', specification })
|
|
38
40
|
}
|
|
39
41
|
catch (error) {
|
|
40
|
-
await projectGateway.cleanupDestination(
|
|
42
|
+
await projectGateway.cleanupDestination(rollbackDestination)
|
|
41
43
|
throw error
|
|
42
44
|
}
|
|
43
45
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process'
|
|
2
2
|
import { readFile, rm, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
|
+
import process from 'node:process'
|
|
4
5
|
import { promisify } from 'node:util'
|
|
5
6
|
|
|
6
7
|
const executeFile = promisify(execFile)
|
|
@@ -32,7 +33,10 @@ export function createNodeMigrationGateway() {
|
|
|
32
33
|
async verify(directory) {
|
|
33
34
|
const manifest = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8'))
|
|
34
35
|
const packageManager = manifest.packageManager?.startsWith('pnpm@') ? 'pnpm' : 'npm'
|
|
35
|
-
return executeFile(packageManager, ['run', 'check'], {
|
|
36
|
+
return executeFile(packageManager, ['run', 'check'], {
|
|
37
|
+
cwd: directory,
|
|
38
|
+
shell: process.platform === 'win32',
|
|
39
|
+
})
|
|
36
40
|
},
|
|
37
41
|
async writeTransaction(directory, files, verify) {
|
|
38
42
|
const originals = new Map()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn, execFile } from 'node:child_process'
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
import { lstat, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises'
|
|
4
|
-
import { basename, dirname, join } from 'node:path'
|
|
4
|
+
import { basename, dirname, extname, join } from 'node:path'
|
|
5
5
|
import process from 'node:process'
|
|
6
6
|
import { promisify } from 'node:util'
|
|
7
7
|
|
|
@@ -10,6 +10,8 @@ const installCommands = {
|
|
|
10
10
|
npm: ['install', '--no-audit', '--no-fund'],
|
|
11
11
|
pnpm: ['install'],
|
|
12
12
|
}
|
|
13
|
+
const pnpmAction = 'pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0'
|
|
14
|
+
const textExtensions = new Set(['.md', '.mjs', '.yaml', '.yml'])
|
|
13
15
|
|
|
14
16
|
export function createNodeProjectGateway({ nodeExecutable, signal }) {
|
|
15
17
|
return {
|
|
@@ -58,7 +60,7 @@ export function createNodeProjectGateway({ nodeExecutable, signal }) {
|
|
|
58
60
|
'--color-scheme', specification.colorScheme,
|
|
59
61
|
'--primary-color', specification.primaryColor,
|
|
60
62
|
'--style', specification.style,
|
|
61
|
-
], specification.destination, signal)
|
|
63
|
+
], specification.destination, { signal })
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
async function configureExample(specification) {
|
|
@@ -69,11 +71,14 @@ export function createNodeProjectGateway({ nodeExecutable, signal }) {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
function initializeGit(destination) {
|
|
72
|
-
return run('git', ['init', '--initial-branch=main'], destination, signal)
|
|
74
|
+
return run('git', ['init', '--initial-branch=main'], destination, { signal })
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
function installDependencies(destination, packageManager) {
|
|
76
|
-
return run(packageManager, installCommands[packageManager], destination,
|
|
78
|
+
return run(packageManager, installCommands[packageManager], destination, {
|
|
79
|
+
shell: process.platform === 'win32',
|
|
80
|
+
signal,
|
|
81
|
+
})
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
async function validateTemplate(specification) {
|
|
@@ -112,6 +117,9 @@ async function configurePackageManager(destination, packageManager, signal) {
|
|
|
112
117
|
catch {
|
|
113
118
|
throw new Error(`Could not run ${packageManager}. Install it or choose another package manager.`)
|
|
114
119
|
}
|
|
120
|
+
if (packageManager === 'pnpm') {
|
|
121
|
+
manifest.scripts = replaceManifestCommands(manifest.scripts)
|
|
122
|
+
}
|
|
115
123
|
const packageManagerEntry = ['packageManager', `${packageManager}@${version.trim()}`]
|
|
116
124
|
const entries = Object.entries(manifest).flatMap(entry => entry[0] === 'engines' ? [packageManagerEntry, entry] : [entry])
|
|
117
125
|
if (!manifest.engines) {
|
|
@@ -129,34 +137,67 @@ minimumReleaseAgeExclude:
|
|
|
129
137
|
trustPolicy: no-downgrade
|
|
130
138
|
trustPolicyIgnoreAfter: 10080
|
|
131
139
|
shellEmulator: true
|
|
140
|
+
|
|
141
|
+
packages:
|
|
142
|
+
- .
|
|
132
143
|
`,
|
|
133
144
|
)
|
|
134
|
-
await
|
|
145
|
+
await replaceProjectCommands(destination)
|
|
135
146
|
}
|
|
136
147
|
}
|
|
137
148
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
|
|
149
|
+
function replaceManifestCommands(scripts = {}) {
|
|
150
|
+
return Object.fromEntries(Object.entries(scripts).map(([name, command]) => [name, replacePnpmCommands(command)]))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function replaceProjectCommands(directory) {
|
|
154
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
155
|
+
const path = join(directory, entry.name)
|
|
156
|
+
if (entry.isDirectory()) {
|
|
157
|
+
await replaceProjectCommands(path)
|
|
158
|
+
}
|
|
159
|
+
else if (textExtensions.has(extname(entry.name)) || entry.name === 'Dockerfile') {
|
|
160
|
+
const source = await readFile(path, 'utf8')
|
|
161
|
+
const converted = entry.name === 'Dockerfile' ? replacePnpmDockerfile(source) : replacePnpmText(source)
|
|
162
|
+
if (converted !== source) {
|
|
163
|
+
await writeFile(path, converted)
|
|
164
|
+
}
|
|
147
165
|
}
|
|
148
166
|
}
|
|
149
167
|
}
|
|
150
168
|
|
|
169
|
+
function replacePnpmText(source) {
|
|
170
|
+
let result = replacePnpmCommands(source)
|
|
171
|
+
result = result.replaceAll('cache: npm', 'cache: pnpm')
|
|
172
|
+
result = result.replace(/^([ \t]*)- uses: actions\/setup-node@/mu, `$1- uses: ${pnpmAction}\n$&`)
|
|
173
|
+
return result.replace(/^\s*- run: npm install -g npm@[^\n]+\n/mu, '')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function replacePnpmCommands(source) {
|
|
177
|
+
return source
|
|
178
|
+
.replaceAll('npm ci', 'pnpm install --frozen-lockfile')
|
|
179
|
+
.replaceAll('npm run ', 'pnpm run ')
|
|
180
|
+
.replaceAll('npx ', 'pnpm exec ')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function replacePnpmDockerfile(source) {
|
|
184
|
+
return replacePnpmCommands(source)
|
|
185
|
+
.replaceAll(/^(FROM [^\n]+)$/gmu, '$1\nRUN corepack enable')
|
|
186
|
+
.replaceAll('COPY package.json package-lock.json ./', 'COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./')
|
|
187
|
+
.replaceAll('pnpm install --frozen-lockfile --omit=dev', 'pnpm install --prod --frozen-lockfile')
|
|
188
|
+
.replaceAll('npm cache clean --force', 'pnpm store prune')
|
|
189
|
+
.replaceAll('CMD ["npm", "start"]', 'CMD ["pnpm", "start"]')
|
|
190
|
+
}
|
|
191
|
+
|
|
151
192
|
async function prepareDestination(destination) {
|
|
152
193
|
const temporaryDestination = join(dirname(destination), `.${basename(destination)}-${process.pid}-${Date.now()}.tmp`)
|
|
153
194
|
await rm(temporaryDestination, { force: true, recursive: true })
|
|
154
195
|
return temporaryDestination
|
|
155
196
|
}
|
|
156
197
|
|
|
157
|
-
function run(command, args, cwd, signal) {
|
|
198
|
+
function run(command, args, cwd, { shell = false, signal } = {}) {
|
|
158
199
|
return new Promise((resolve, reject) => {
|
|
159
|
-
const child = spawn(command, args, { cwd, signal, stdio: 'inherit' })
|
|
200
|
+
const child = spawn(command, args, { cwd, shell, signal, stdio: 'inherit' })
|
|
160
201
|
child.once('error', error => reject(new Error(`Could not run ${command}: ${error.message}`)))
|
|
161
202
|
child.once('close', code => {
|
|
162
203
|
if (code === 0) {
|