@grest-ts/cli 0.0.39 → 0.0.42
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/README.md +14 -0
- package/index.mjs +100 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,20 @@ npx @grest-ts/cli update next # bump to a dist-tag
|
|
|
16
16
|
npx @grest-ts/cli update --dry-run # preview only
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
## Linking a local checkout (development)
|
|
20
|
+
|
|
21
|
+
When working on grest-ts itself, symlink every `@grest-ts/*` package in your project to a local grest-ts checkout so the project runs against live source:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @grest-ts/cli link # links against ../grest-ts
|
|
25
|
+
npx @grest-ts/cli link ../grest-ts # explicit checkout path
|
|
26
|
+
npx @grest-ts/cli unlink # restore the published versions
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`link` replaces every installed `@grest-ts/*` package — declared deps and the transitive peers npm hoisted in — with a symlink to its source. It links all of them at once so you never load two copies of a package. `unlink` removes the links and reinstalls the versions pinned in `package-lock.json`.
|
|
30
|
+
|
|
31
|
+
This is for **running** tests and dev servers against live source — vitest and tsx execute the linked `.ts` directly. It is **not** a typecheck tool: `tsc` sees grest-ts source under your project's stricter compiler options, and resolves third-party types from grest-ts's own `node_modules`, so it can report errors that disappear once you `unlink`. A later `npm install` reverts the links — re-run `link` after installing.
|
|
32
|
+
|
|
19
33
|
## Install (optional)
|
|
20
34
|
|
|
21
35
|
`npx` works without installing anything. To pin a CLI version per-project:
|
package/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { readFileSync, writeFileSync, existsSync, unlinkSync, readdirSync, rmSync } from "fs"
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync, readdirSync, rmSync, symlinkSync } from "fs"
|
|
4
4
|
import { join, resolve, dirname } from "path"
|
|
5
5
|
import { spawnSync } from "child_process"
|
|
6
6
|
|
|
@@ -9,6 +9,8 @@ const DEP_BLOCKS = ["dependencies", "devDependencies", "peerDependencies"]
|
|
|
9
9
|
|
|
10
10
|
const COMMANDS = {
|
|
11
11
|
update: runUpdate,
|
|
12
|
+
link: runLink,
|
|
13
|
+
unlink: runUnlink,
|
|
12
14
|
help: runHelp,
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -44,6 +46,12 @@ Commands:
|
|
|
44
46
|
@grest-ts/* peers to your dependencies.
|
|
45
47
|
Flags:
|
|
46
48
|
--dry-run Show what would change without writing.
|
|
49
|
+
link [path] Symlink every @grest-ts/* dep to a local grest-ts
|
|
50
|
+
checkout (default ../grest-ts) so the project builds and
|
|
51
|
+
tests against live source. Links all matched packages at
|
|
52
|
+
once; a later 'npm install' reverts the links.
|
|
53
|
+
unlink Remove the links and reinstall the @grest-ts/* versions
|
|
54
|
+
pinned in package-lock.json.
|
|
47
55
|
help Show this message.
|
|
48
56
|
`)
|
|
49
57
|
}
|
|
@@ -238,6 +246,97 @@ async function runUpdate(args) {
|
|
|
238
246
|
console.log(`\n✓ Updated all @grest-ts/* to ${canonicalRange}`)
|
|
239
247
|
}
|
|
240
248
|
|
|
249
|
+
async function runLink(args) {
|
|
250
|
+
const positional = args.filter(a => !a.startsWith("--"))
|
|
251
|
+
const cwd = process.cwd()
|
|
252
|
+
if (!existsSync(join(cwd, "package.json"))) {
|
|
253
|
+
throw new Error(`No package.json found in ${cwd}`)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const grestSrc = resolve(cwd, positional[0] || "../grest-ts")
|
|
257
|
+
const grestPkgPath = join(grestSrc, "package.json")
|
|
258
|
+
if (!existsSync(grestPkgPath)) {
|
|
259
|
+
throw new Error(`No grest-ts checkout at ${grestSrc}. Pass its path: grest-ts link <path>`)
|
|
260
|
+
}
|
|
261
|
+
const grestRootPkg = readJson(grestPkgPath)
|
|
262
|
+
if (grestRootPkg.name !== "@grest-ts/framework") {
|
|
263
|
+
throw new Error(`${grestSrc} is not a grest-ts checkout (its package.json is "${grestRootPkg.name || "unnamed"}", expected "@grest-ts/framework").`)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const dirByName = new Map()
|
|
267
|
+
for (const p of findWorkspacePackages(grestSrc, grestRootPkg)) {
|
|
268
|
+
const pkg = readJson(p)
|
|
269
|
+
if (pkg.name && pkg.name.startsWith(GREST_PREFIX)) {
|
|
270
|
+
dirByName.set(pkg.name, dirname(p))
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Link the full set npm installed under @grest-ts/ — declared deps plus the
|
|
275
|
+
// transitive peers npm hoisted in — not just the project's declared deps.
|
|
276
|
+
// A mixed source/registry set loads two copies of a package and breaks
|
|
277
|
+
// instanceof checks and the framework's runtime dedup.
|
|
278
|
+
const installedDir = join(cwd, "node_modules", "@grest-ts")
|
|
279
|
+
if (!existsSync(installedDir)) {
|
|
280
|
+
throw new Error(`No node_modules/@grest-ts in ${cwd}. Run 'npm install' first.`)
|
|
281
|
+
}
|
|
282
|
+
const toLink = []
|
|
283
|
+
const notFound = []
|
|
284
|
+
for (const entry of readdirSync(installedDir)) {
|
|
285
|
+
if (entry.startsWith(".")) continue
|
|
286
|
+
const name = GREST_PREFIX + entry
|
|
287
|
+
const dir = dirByName.get(name)
|
|
288
|
+
if (dir) toLink.push({ name, dir })
|
|
289
|
+
else notFound.push(name)
|
|
290
|
+
}
|
|
291
|
+
if (notFound.length > 0) {
|
|
292
|
+
console.log(`⚠ Installed but not in ${grestSrc} — staying on the registry build:`)
|
|
293
|
+
for (const name of notFound) console.log(` ! ${name}`)
|
|
294
|
+
}
|
|
295
|
+
if (toLink.length === 0) {
|
|
296
|
+
throw new Error(`No installed @grest-ts/* packages exist in ${grestSrc}.`)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
for (const { name, dir } of toLink) {
|
|
300
|
+
const linkPath = join(cwd, "node_modules", name)
|
|
301
|
+
rmSync(linkPath, { recursive: true, force: true })
|
|
302
|
+
symlinkSync(dir, linkPath)
|
|
303
|
+
console.log(` → ${name} ⇒ ${dir}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
console.log(`\n✓ Linked ${toLink.length} @grest-ts/* package(s) to ${grestSrc}.`)
|
|
307
|
+
console.log(" For running tests/dev against live source — 'tsc' against linked source is noisy (see README).")
|
|
308
|
+
console.log(" Any 'npm install' here reverts these links — re-run 'link' afterwards.")
|
|
309
|
+
console.log(" Run 'grest-ts unlink' to restore the installed versions.")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function runUnlink() {
|
|
313
|
+
const cwd = process.cwd()
|
|
314
|
+
if (!existsSync(join(cwd, "package.json"))) {
|
|
315
|
+
throw new Error(`No package.json found in ${cwd}`)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const grestModulesPath = join(cwd, "node_modules", "@grest-ts")
|
|
319
|
+
if (existsSync(grestModulesPath)) {
|
|
320
|
+
console.log("Removing node_modules/@grest-ts/ ...")
|
|
321
|
+
rmSync(grestModulesPath, { recursive: true, force: true })
|
|
322
|
+
}
|
|
323
|
+
// Drop npm's install-state lockfile so the reinstall re-resolves @grest-ts
|
|
324
|
+
// from package-lock.json instead of trusting the now-deleted link state.
|
|
325
|
+
const hiddenLockPath = join(cwd, "node_modules", ".package-lock.json")
|
|
326
|
+
if (existsSync(hiddenLockPath)) {
|
|
327
|
+
console.log("Deleting node_modules/.package-lock.json...")
|
|
328
|
+
unlinkSync(hiddenLockPath)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
console.log("Running npm install...")
|
|
332
|
+
const result = spawnSync("npm install", { stdio: "inherit", shell: true, cwd })
|
|
333
|
+
if (result.status !== 0) {
|
|
334
|
+
throw new Error(`npm install exited with code ${result.status}`)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
console.log("\n✓ Unlinked — @grest-ts/* restored from package-lock.json.")
|
|
338
|
+
}
|
|
339
|
+
|
|
241
340
|
// ---- helpers ----
|
|
242
341
|
|
|
243
342
|
function readJson(path) {
|
package/package.json
CHANGED