-
Notifications
You must be signed in to change notification settings - Fork 669
/
Copy pathfix.js
134 lines (118 loc) · 3.56 KB
/
fix.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// This should run by node without any dependencies
// because you may need to run it without deps.
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const here = (...p) => path.join(__dirname, ...p)
const workshopRoot = here('..')
const examples = (await readDir(here('../examples'))).map((dir) =>
here(`../examples/${dir}`),
)
const exercises = (await readDir(here('../exercises')))
.map((name) => here(`../exercises/${name}`))
.filter((filepath) => fs.statSync(filepath).isDirectory())
const exerciseApps = (
await Promise.all(
exercises.flatMap(async (exercise) => {
return (await readDir(exercise))
.filter((dir) => {
return /(problem|solution)/.test(dir)
})
.map((dir) => path.join(exercise, dir))
}),
)
).flat()
const exampleApps = (await readDir(here('../examples'))).map((dir) =>
here(`../examples/${dir}`),
)
const apps = [...exampleApps, ...exerciseApps]
const appsWithPkgJson = [...examples, ...apps].filter((app) => {
const pkgjsonPath = path.join(app, 'package.json')
return exists(pkgjsonPath)
})
// update the package.json file name property
// to match the parent directory name + directory name
// e.g. exercises/01-goo/problem.01-great
// name: "exercises__sep__01-goo.problem__sep__01-great"
function relativeToWorkshopRoot(dir) {
return dir.replace(`${workshopRoot}${path.sep}`, '')
}
await updatePkgNames()
await copyTestFiles()
await updateTsconfig()
async function updatePkgNames() {
for (const file of appsWithPkgJson) {
const pkgjsonPath = path.join(file, 'package.json')
const pkg = JSON.parse(await fs.promises.readFile(pkgjsonPath, 'utf8'))
pkg.name = relativeToWorkshopRoot(file).replace(/\\|\//g, '__sep__')
const written = await writeIfNeeded(
pkgjsonPath,
`${JSON.stringify(pkg, null, 2)}\n`,
)
if (written) {
console.log(`updated ${path.relative(process.cwd(), pkgjsonPath)}`)
}
}
}
async function copyTestFiles() {
for (const app of exerciseApps) {
if (app.includes('problem')) {
const solutionApp = app.replace('problem', 'solution')
const testDir = path.join(solutionApp, 'tests')
const destTestDir = path.join(app, 'tests')
if (exists(testDir)) {
// Remove existing test directory in problem app if it exists
if (exists(destTestDir)) {
await fs.promises.rm(destTestDir, { recursive: true, force: true })
}
// Copy the entire test directory from solution to problem
await fs.promises.cp(testDir, destTestDir, { recursive: true })
}
}
}
}
async function updateTsconfig() {
const tsconfig = {
files: [],
exclude: ['node_modules'],
references: appsWithPkgJson.map((a) => ({
path: relativeToWorkshopRoot(a).replace(/\\/g, '/'),
})),
}
const written = await writeIfNeeded(
path.join(workshopRoot, 'tsconfig.json'),
`${JSON.stringify(tsconfig, null, 2)}\n`,
{ parser: 'json' },
)
if (written) {
// delete node_modules/.cache
const cacheDir = path.join(workshopRoot, 'node_modules', '.cache')
if (exists(cacheDir)) {
await fs.promises.rm(cacheDir, { recursive: true })
}
console.log('all fixed up')
}
}
async function writeIfNeeded(filepath, content) {
const oldContent = await fs.promises.readFile(filepath, 'utf8')
if (oldContent !== content) {
await fs.promises.writeFile(filepath, content)
}
return oldContent !== content
}
function exists(p) {
if (!p) return false
try {
fs.statSync(p)
return true
} catch (error) {
return false
}
}
async function readDir(dir) {
if (exists(dir)) {
return fs.promises.readdir(dir)
}
return []
}