1
- import { mkdir , readdir , readFile , rm , stat , writeFile } from 'node:fs/promises'
1
+ import { access , copyFile , mkdir , readdir , readFile , rename , rm , stat , writeFile } from 'node:fs/promises'
2
2
import { execSync } from 'node:child_process'
3
3
import { basename , join , relative } from 'node:path'
4
4
import { Readable } from 'node:stream'
5
- import { extract } from 'tar'
5
+ import * as tar from 'tar'
6
+ import * as yaml from 'js-yaml'
7
+ import envPaths from 'env-paths'
6
8
import getRegistry from 'get-registry'
7
9
import parse from 'yargs-parser'
8
10
import prompts from 'prompts'
9
11
import which from 'which-pm-runs'
10
12
import kleur from 'kleur'
11
13
14
+ const paths = envPaths ( 'create-cordis' , { suffix : '' } )
15
+
12
16
let project : string
13
17
let rootDir : string
14
18
@@ -45,6 +49,8 @@ async function confirm(message: string) {
45
49
}
46
50
47
51
class Scaffold {
52
+ registry ?: string
53
+
48
54
constructor ( public options : Record < string , any > = { } ) { }
49
55
50
56
async getName ( ) {
@@ -81,13 +87,49 @@ class Scaffold {
81
87
await mkdir ( rootDir )
82
88
}
83
89
90
+ async downloadYarn ( ) {
91
+ interface YarnRC {
92
+ yarnPath ?: string
93
+ }
94
+
95
+ const rc = yaml . load ( await readFile ( join ( rootDir , '.yarnrc.yml' ) , 'utf8' ) ) as any as YarnRC
96
+ const version = rc . yarnPath ?. match ( / ^ \. y a r n \/ r e l e a s e s \/ y a r n - ( [ ^ / ] + ) .c j s $ / ) ?. [ 1 ]
97
+ if ( ! version ) return
98
+
99
+ const cacheDir = join ( paths . cache , '.yarn/releases' )
100
+ const cacheFile = join ( cacheDir , `yarn-${ version } .cjs` )
101
+ try {
102
+ await access ( join ( cacheDir , `yarn-${ version } .cjs` ) )
103
+ } catch {
104
+ const tempDir = join ( paths . temp , '@yarnpkg/cli-dist' )
105
+ await mkdir ( tempDir , { recursive : true } )
106
+ await mkdir ( cacheDir , { recursive : true } )
107
+ const resp3 = await fetch ( `${ this . registry } /@yarnpkg/cli-dist/-/cli-dist-${ version } .tgz` )
108
+ await new Promise < void > ( ( resolve , reject ) => {
109
+ const stream = Readable . fromWeb ( resp3 . body as any ) . pipe ( tar . extract ( {
110
+ cwd : tempDir ,
111
+ newer : true ,
112
+ strip : 2 ,
113
+ } , [ 'package/bin/yarn.js' ] ) )
114
+ stream . on ( 'finish' , resolve )
115
+ stream . on ( 'error' , reject )
116
+ } )
117
+ await rename ( join ( tempDir , 'yarn.js' ) , cacheFile )
118
+ }
119
+
120
+ const targetDir = join ( rootDir , '.yarn/releases' )
121
+ const targetFile = join ( targetDir , `yarn-${ version } .cjs` )
122
+ await mkdir ( targetDir , { recursive : true } )
123
+ await copyFile ( targetFile , cacheFile )
124
+ }
125
+
84
126
async scaffold ( ) {
85
127
console . log ( kleur . dim ( ' Scaffolding project in ' ) + project + kleur . dim ( ' ...' ) )
86
128
87
- const registry = ( await getRegistry ( ) ) . replace ( / \/ $ / , '' )
129
+ this . registry = ( await getRegistry ( ) ) . replace ( / \/ $ / , '' )
88
130
const template = argv . template || this . options . template
89
131
90
- const resp1 = await fetch ( `${ registry } /${ template } ` )
132
+ const resp1 = await fetch ( `${ this . registry } /${ template } ` )
91
133
if ( ! resp1 . ok ) {
92
134
const { status, statusText } = resp1
93
135
console . log ( `${ kleur . red ( 'error' ) } request failed with status code ${ status } ${ statusText } ` )
@@ -98,21 +140,26 @@ class Scaffold {
98
140
99
141
const resp2 = await fetch ( remote . versions [ version ] . dist . tarball )
100
142
await new Promise < void > ( ( resolve , reject ) => {
101
- const stream = Readable . fromWeb ( resp2 . body as any ) . pipe ( extract ( { cwd : rootDir , newer : true , strip : 1 } ) )
143
+ const stream = Readable . fromWeb ( resp2 . body as any ) . pipe ( tar . extract ( {
144
+ cwd : rootDir ,
145
+ newer : true ,
146
+ strip : 1 ,
147
+ } ) )
102
148
stream . on ( 'finish' , resolve )
103
149
stream . on ( 'error' , reject )
104
150
} )
105
151
106
- await this . writePackageJson ( )
152
+ await Promise . all ( [
153
+ this . downloadYarn ( ) ,
154
+ this . writePackageJson ( ) ,
155
+ ] )
107
156
console . log ( kleur . green ( ' Done.\n' ) )
108
157
}
109
158
110
159
async writePackageJson ( ) {
111
160
const filename = join ( rootDir , 'package.json' )
112
- const meta = JSON . parse ( await readFile ( filename , 'utf-8 ' ) )
161
+ const meta = JSON . parse ( await readFile ( filename , 'utf8 ' ) )
113
162
meta . name = project
114
- meta . private = true
115
- meta . version = '0.0.0'
116
163
if ( argv . prod ) {
117
164
// https://github.com/koishijs/koishi/issues/994
118
165
// Do not use `NODE_ENV` or `--production` flag.
0 commit comments