Skip to content

Commit 2e343b8

Browse files
authored
feat: CLI for initiation (#22)
* initial cli * chore: own-package
1 parent 956c2a2 commit 2e343b8

File tree

5 files changed

+203
-1
lines changed

5 files changed

+203
-1
lines changed

adex/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"description": "An easier way to build apps with Vite and Preact",
55
"keywords": [
66
"adex",
7-
"meta-framework",
87
"preact",
98
"minimal",
109
"server",
@@ -61,6 +60,7 @@
6160
"dotenv": "^16.4.5",
6261
"hoofd": "^1.7.1",
6362
"mri": "^1.2.0",
63+
"node-stream-zip": "^1.15.0",
6464
"preact-render-to-string": "^6.5.5",
6565
"regexparam": "^3.0.0",
6666
"sirv": "^2.0.4",

create-adex/cli.mjs

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env node
2+
3+
import StreamZip from 'node-stream-zip'
4+
import { createWriteStream, existsSync } from 'node:fs'
5+
import { copyFile, mkdir, readdir, rm } from 'node:fs/promises'
6+
import { dirname, join, resolve } from 'node:path'
7+
import { Readable } from 'node:stream'
8+
import { parseArgs } from 'node:util'
9+
import { finished } from 'stream/promises'
10+
import k from 'kleur'
11+
12+
const TMP_FOLDER_PREFX = '.create-adex'
13+
const info = k.cyan
14+
const success = k.green
15+
const failure = k.red
16+
17+
const TEMPLATES = {
18+
default: {
19+
name: 'adex-default-template',
20+
link: 'https://github.com/barelyhuman/adex-default-template/archive/refs/heads/main.zip',
21+
branch: 'main',
22+
},
23+
}
24+
25+
const flags = parseArgs({
26+
allowPositionals: true,
27+
options: {
28+
help: {
29+
short: 'h',
30+
type: 'boolean',
31+
default: false,
32+
},
33+
init: {
34+
type: 'boolean',
35+
default: false,
36+
},
37+
},
38+
})
39+
40+
await main()
41+
42+
async function main() {
43+
const { init, help } = flags.values
44+
const targetDir = flags.positionals[0] ?? '.'
45+
46+
if (help) {
47+
console.log(`
48+
${k.gray('[USAGE]')}
49+
50+
$ adex [flags] [args]
51+
52+
${k.gray('[FLAGS]')}
53+
54+
--help,-h Show this help
55+
--init PATH Initialise a new adex project at PATH (${k.gray('default: ./')})
56+
57+
`)
58+
return
59+
}
60+
61+
if (init) {
62+
if (existsSync(targetDir)) {
63+
const entries = await readdir(targetDir)
64+
if (entries.filter(d => d != '.tmp').length) {
65+
console.log(
66+
`${failure(`[FAIL]`)} ${k.bold(targetDir)} is not empty, aborting initialisation`
67+
)
68+
return
69+
}
70+
}
71+
console.log(info(`Initializing in ${targetDir}`))
72+
const selectedTemplate = TEMPLATES.default
73+
const targetFilePath = await downloadFile(
74+
selectedTemplate.link,
75+
'adex-template.zip'
76+
)
77+
78+
const unzipStream = new StreamZip.async({
79+
file: targetFilePath,
80+
})
81+
82+
const entries = await unzipStream.entries()
83+
84+
const files = (
85+
await Promise.all(
86+
Object.values(entries).map(async entry => {
87+
const outFile = join(TMP_FOLDER_PREFX, 'out', entry.name)
88+
await mkdir(dirname(outFile), { recursive: true })
89+
await unzipStream.extract(entry, outFile)
90+
if (entry.isFile) {
91+
return outFile
92+
}
93+
})
94+
)
95+
).filter(Boolean)
96+
97+
await Promise.allSettled(
98+
files
99+
.map(d => {
100+
const absolutePath = resolve(d)
101+
return {
102+
source: absolutePath,
103+
dest: absolutePath.replace(
104+
join(
105+
process.cwd(),
106+
TMP_FOLDER_PREFX,
107+
'out',
108+
selectedTemplate.name + '-' + selectedTemplate.branch
109+
),
110+
resolve(targetDir)
111+
),
112+
}
113+
})
114+
.map(async d => {
115+
try {
116+
await mkdir(dirname(d.dest), { recursive: true })
117+
await copyFile(d.source, d.dest)
118+
console.log(`${k.gray('[Created]')} ${k.white(d.dest)}`)
119+
} catch (err) {
120+
console.log(failure(`[FAIL] Creation: ${d.dest}, ${err.message}`))
121+
}
122+
})
123+
)
124+
125+
rm(TMP_FOLDER_PREFX, { recursive: true })
126+
127+
console.log(
128+
`\nNext Steps\n
129+
$ cd ${targetDir}
130+
$ npm i`
131+
)
132+
console.log(success('\nDone!\n'))
133+
134+
return
135+
}
136+
}
137+
138+
async function downloadFile(url, fileName) {
139+
const res = await fetch(url)
140+
if (!existsSync(TMP_FOLDER_PREFX)) await mkdir(TMP_FOLDER_PREFX)
141+
const destination = resolve(TMP_FOLDER_PREFX, fileName)
142+
if (existsSync(destination)) {
143+
await rm(destination, { recursive: true })
144+
}
145+
const fileStream = createWriteStream(destination, { flags: 'wx' })
146+
// @ts-expect-error , supports the input but readable needs to be fixed for the same
147+
await finished(Readable.fromWeb(res.body).pipe(fileStream))
148+
return destination
149+
}

create-adex/package.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "create-adex",
3+
"version": "0.0.0",
4+
"bin": {
5+
"adex": "./cli.mjs"
6+
},
7+
"description": "CLI to create adex projects",
8+
"keywords": [
9+
"adex",
10+
"preact",
11+
"minimal",
12+
"server",
13+
"node"
14+
],
15+
"bugs": "github.com/barelyhuman/adex/issues",
16+
"repository": {
17+
"type": "git",
18+
"url": "github.com/barelyhuman/adex"
19+
},
20+
"type": "module",
21+
"files": [
22+
"cli.mjs"
23+
],
24+
"dependencies": {
25+
"kleur": "^4.1.5",
26+
"node-stream-zip": "^1.15.0"
27+
}
28+
}

pnpm-lock.yaml

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
packages:
22
- adex
3+
- create-adex
34
- playground

0 commit comments

Comments
 (0)