rootless-config 1.8.0 → 1.8.2
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 +1 -1
- package/src/cli/commands/migrate.js +29 -2
- package/src/core/scriptPatcher.js +69 -0
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*-------- rootless migrate — moves existing root configs into .root container --------*/
|
|
2
2
|
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { readdir, unlink } from 'node:fs/promises'
|
|
4
|
+
import { readdir, readFile, unlink } from 'node:fs/promises'
|
|
5
5
|
import { createLogger } from '../../utils/logger.js'
|
|
6
6
|
import { fileExists, ensureDir, atomicWrite, copyFile, readJsonFile } from '../../utils/fsUtils.js'
|
|
7
7
|
import { confirm } from '../../utils/prompt.js'
|
|
8
|
-
import { patchPackageScripts, isPatchable, NEVER_MIGRATE } from '../../core/scriptPatcher.js'
|
|
8
|
+
import { patchPackageScripts, isPatchable, NEVER_MIGRATE, patchServerScript } from '../../core/scriptPatcher.js'
|
|
9
9
|
|
|
10
10
|
// Files that are OS/editor/VCS noise — never migrate, never touch
|
|
11
11
|
const SYSTEM_FILES = new Set([
|
|
@@ -92,6 +92,33 @@ export default {
|
|
|
92
92
|
const dest = path.join(destDir, name)
|
|
93
93
|
|
|
94
94
|
if (isCleanMode) {
|
|
95
|
+
// For PS1 server scripts: patch $root before writing to .root/assets/
|
|
96
|
+
if (name.endsWith('.ps1')) {
|
|
97
|
+
const raw = await readFile(src, 'utf8')
|
|
98
|
+
const patched = patchServerScript(raw)
|
|
99
|
+
if (patched) {
|
|
100
|
+
await atomicWrite(dest, patched)
|
|
101
|
+
await unlink(src)
|
|
102
|
+
logger.success(`Moved+patched .root/${destSubdir}/${name} (server root → project root)`)
|
|
103
|
+
continue
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// For .cmd/.bat launcher scripts: fix relative path to .ps1 → use %~dp0
|
|
107
|
+
// so the ps1 is found relative to the cmd file's own location
|
|
108
|
+
if (name.endsWith('.cmd') || name.endsWith('.bat')) {
|
|
109
|
+
const raw = await readFile(src, 'utf8')
|
|
110
|
+
// Replace: -File .server.ps1 → -File "%~dp0.server.ps1"
|
|
111
|
+
const patched = raw.replace(
|
|
112
|
+
/(-File\s+)(?!")([^\s"]+\.ps1)/gi,
|
|
113
|
+
(_, flag, ps1) => `${flag}"%~dp0${ps1}"`
|
|
114
|
+
)
|
|
115
|
+
if (patched !== raw) {
|
|
116
|
+
await atomicWrite(dest, patched)
|
|
117
|
+
await unlink(src)
|
|
118
|
+
logger.success(`Moved+patched .root/${destSubdir}/${name} (ps1 path → %~dp0-relative)`)
|
|
119
|
+
continue
|
|
120
|
+
}
|
|
121
|
+
}
|
|
95
122
|
// Binary-safe stream copy — works for .png, .js, .css, etc.
|
|
96
123
|
await copyFile(src, dest)
|
|
97
124
|
await unlink(src)
|
|
@@ -459,6 +459,74 @@ async function patchPackageScripts(projectRoot, configsDir, logger) {
|
|
|
459
459
|
return changed
|
|
460
460
|
}
|
|
461
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Patches a PowerShell HTTP server script (.server.ps1 style) so it works
|
|
464
|
+
* correctly after being moved to .root/assets/.
|
|
465
|
+
*
|
|
466
|
+
* The script originally uses $PSScriptRoot as web root. After migration,
|
|
467
|
+
* $PSScriptRoot = .root/assets/ — so subdirectories left in the project root
|
|
468
|
+
* (viewer/, agreement/, etc.) are invisible to it.
|
|
469
|
+
*
|
|
470
|
+
* This patch:
|
|
471
|
+
* 1. Sets $root to the project root (2 dirs up from $PSScriptRoot)
|
|
472
|
+
* 2. Keeps $assetsRoot pointing to .root/assets/ for fallback
|
|
473
|
+
* 3. After path resolution, falls back to $assetsRoot when file not found in $root
|
|
474
|
+
* 4. Fixes the 404 page lookup to also check $assetsRoot
|
|
475
|
+
*
|
|
476
|
+
* Returns patched content, or null if the file doesn't look like a server script.
|
|
477
|
+
*/
|
|
478
|
+
function patchServerScript(content) {
|
|
479
|
+
// Only patch scripts that use $PSScriptRoot as web root
|
|
480
|
+
if (!content.includes('$PSScriptRoot') || !content.includes('$root')) return null
|
|
481
|
+
|
|
482
|
+
let out = content
|
|
483
|
+
|
|
484
|
+
// 1. Redefine $root → project root (2 levels up), keep $assetsRoot for fallback
|
|
485
|
+
out = out.replace(
|
|
486
|
+
/\$root(\s*)=(\s*)\$PSScriptRoot\.TrimEnd\('\\\\?'\)\s*\+\s*'\\\\'?/,
|
|
487
|
+
`$assetsRoot$1=$2$PSScriptRoot.TrimEnd('\\') + '\\'
|
|
488
|
+
$root$1=$2(Get-Item "$PSScriptRoot\\..\\..").FullName.TrimEnd('\\') + '\\'`
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
// If the above didn't match (different whitespace/quoting), try simpler form
|
|
492
|
+
if (out === content) {
|
|
493
|
+
const marker = `$root = $PSScriptRoot.TrimEnd('\\') + '\\'`
|
|
494
|
+
if (content.includes(marker)) {
|
|
495
|
+
out = out.replace(
|
|
496
|
+
marker,
|
|
497
|
+
`$assetsRoot = $PSScriptRoot.TrimEnd('\\') + '\\'
|
|
498
|
+
$root = (Get-Item "$PSScriptRoot\\..\\..").FullName.TrimEnd('\\') + '\\'`
|
|
499
|
+
)
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// 2. Add rootless fallback after $filePath = $resolved
|
|
504
|
+
const filePathLine = ' $filePath = $resolved'
|
|
505
|
+
if (out.includes(filePathLine)) {
|
|
506
|
+
out = out.replace(
|
|
507
|
+
filePathLine,
|
|
508
|
+
filePathLine + `
|
|
509
|
+
# rootless: fallback to .root/assets/ when file not found in project root
|
|
510
|
+
if ($relPath -ne '' -and -not (Test-Path $filePath)) {
|
|
511
|
+
$assetsCandidate = [System.IO.Path]::GetFullPath((Join-Path $assetsRoot $relPath))
|
|
512
|
+
if (Test-Path $assetsCandidate) { $filePath = $assetsCandidate }
|
|
513
|
+
}`
|
|
514
|
+
)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// 3. Fix 404 page lookup to also check $assetsRoot
|
|
518
|
+
const notFoundLine = ' $candidate = Join-Path $root $filename'
|
|
519
|
+
if (out.includes(notFoundLine)) {
|
|
520
|
+
out = out.replace(
|
|
521
|
+
notFoundLine,
|
|
522
|
+
notFoundLine + `
|
|
523
|
+
if (-not (Test-Path $candidate -PathType Leaf)) { $candidate = Join-Path $assetsRoot $filename }`
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return out === content ? null : out
|
|
528
|
+
}
|
|
529
|
+
|
|
462
530
|
/**
|
|
463
531
|
* Add "prepare": "rootless prepare --yes" to project's package.json.
|
|
464
532
|
*/
|
|
@@ -492,5 +560,6 @@ export {
|
|
|
492
560
|
NEVER_MIGRATE,
|
|
493
561
|
ROOT_REQUIRED_PATTERNS,
|
|
494
562
|
WEB_ASSET_PATTERNS,
|
|
563
|
+
patchServerScript,
|
|
495
564
|
}
|
|
496
565
|
|