rootless-config 1.4.0 → 1.4.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/setup.js +54 -0
- package/src/cli/index.js +1 -1
- package/src/core/configSchema.js +2 -2
- package/src/core/scriptPatcher.js +12 -1
package/package.json
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*-------- rootless setup — one-command full root cleanup: init + migrate + prepare --------*/
|
|
2
|
+
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { createLogger } from '../../utils/logger.js'
|
|
5
|
+
import initCmd from './init.js'
|
|
6
|
+
import migrateCmd from './migrate.js'
|
|
7
|
+
import prepareCmd from './prepare.js'
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
name: 'setup',
|
|
11
|
+
description: 'Full automated root cleanup: init .root, migrate all configs, prepare (copy + patch scripts)',
|
|
12
|
+
|
|
13
|
+
async handler(args) {
|
|
14
|
+
const logger = createLogger({ verbose: args.verbose ?? false })
|
|
15
|
+
const projectRoot = args.cwd ? path.resolve(args.cwd) : process.cwd()
|
|
16
|
+
|
|
17
|
+
logger.info('─────────────────────────────────────────')
|
|
18
|
+
logger.info(' rootless setup — cleaning your project root')
|
|
19
|
+
logger.info('─────────────────────────────────────────')
|
|
20
|
+
logger.info('')
|
|
21
|
+
|
|
22
|
+
// ── Step 1: init ──────────────────────────────────────────────────────────
|
|
23
|
+
logger.info('[1/3] Initializing .root container…')
|
|
24
|
+
await initCmd.handler({ ...args, yes: true, cwd: projectRoot })
|
|
25
|
+
logger.info('')
|
|
26
|
+
|
|
27
|
+
// ── Step 2: migrate ───────────────────────────────────────────────────────
|
|
28
|
+
logger.info('[2/3] Migrating config files from root…')
|
|
29
|
+
await migrateCmd.handler({ ...args, yes: true, cwd: projectRoot })
|
|
30
|
+
logger.info('')
|
|
31
|
+
|
|
32
|
+
// ── Step 3: prepare ───────────────────────────────────────────────────────
|
|
33
|
+
logger.info('[3/3] Preparing root (copying mandatory files + patching scripts)…')
|
|
34
|
+
await prepareCmd.handler({ ...args, yes: true })
|
|
35
|
+
logger.info('')
|
|
36
|
+
|
|
37
|
+
logger.info('─────────────────────────────────────────')
|
|
38
|
+
logger.success('Setup complete! Your project root is clean.')
|
|
39
|
+
logger.info('')
|
|
40
|
+
logger.info('What happened:')
|
|
41
|
+
logger.info(' • .root/ container created')
|
|
42
|
+
logger.info(' • Config files moved to .root/configs/')
|
|
43
|
+
logger.info(' • .env* files moved to .root/env/')
|
|
44
|
+
logger.info(' • Web assets moved to .root/assets/')
|
|
45
|
+
logger.info(' • package.json scripts patched with --config flags')
|
|
46
|
+
logger.info(' • Mandatory files copied back to root (prepare)')
|
|
47
|
+
logger.info('')
|
|
48
|
+
logger.info('Next steps:')
|
|
49
|
+
logger.info(' rootless status — see what\'s managed')
|
|
50
|
+
logger.info(' rootless doctor — verify everything is wired correctly')
|
|
51
|
+
logger.info(' rootless watch — auto-sync on .root/ changes')
|
|
52
|
+
logger.info('─────────────────────────────────────────')
|
|
53
|
+
},
|
|
54
|
+
}
|
package/src/cli/index.js
CHANGED
|
@@ -20,7 +20,7 @@ async function run(argv) {
|
|
|
20
20
|
for (const cmd of registry.list()) {
|
|
21
21
|
const sub = program.command(cmd.name).description(cmd.description)
|
|
22
22
|
|
|
23
|
-
if (['prepare', 'watch', 'migrate'].includes(cmd.name)) {
|
|
23
|
+
if (['prepare', 'watch', 'migrate', 'setup'].includes(cmd.name)) {
|
|
24
24
|
sub.option('--yes', 'Auto-approve all file override prompts')
|
|
25
25
|
sub.option('--no-yes', 'Auto-decline all file override prompts')
|
|
26
26
|
}
|
package/src/core/configSchema.js
CHANGED
|
@@ -17,8 +17,8 @@ function validateConfig(rawConfig) {
|
|
|
17
17
|
errors.push(new ValidationError('"containerPath" must be a string', 'containerPath'))
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
if (rawConfig.mode !== undefined && !['proxy', 'copy'].includes(rawConfig.mode)) {
|
|
21
|
-
errors.push(new ValidationError('"mode" must be "proxy" or "
|
|
20
|
+
if (rawConfig.mode !== undefined && !['proxy', 'copy', 'clean'].includes(rawConfig.mode)) {
|
|
21
|
+
errors.push(new ValidationError('"mode" must be "proxy", "copy", or "clean"', 'mode'))
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
if (rawConfig.plugins !== undefined && !Array.isArray(rawConfig.plugins)) {
|
|
@@ -287,6 +287,18 @@ const WEB_ASSET_PATTERNS = [
|
|
|
287
287
|
/^health\.json$/,
|
|
288
288
|
/^_redirects$/,
|
|
289
289
|
/^_headers$/,
|
|
290
|
+
// Generic web pages served from root (GitHub Pages, static sites)
|
|
291
|
+
/\.html?$/,
|
|
292
|
+
/\.php$/,
|
|
293
|
+
/\.md$/,
|
|
294
|
+
// Scripts that must run from root
|
|
295
|
+
/\.ps1$/,
|
|
296
|
+
/\.sh$/,
|
|
297
|
+
/\.(bat|cmd)$/,
|
|
298
|
+
// GitHub Pages markers
|
|
299
|
+
/^\.nojekyll$/,
|
|
300
|
+
/^CNAME$/i,
|
|
301
|
+
/^CXNAME$/i,
|
|
290
302
|
]
|
|
291
303
|
|
|
292
304
|
/**
|
|
@@ -342,7 +354,6 @@ function isRootRequired(filename) {
|
|
|
342
354
|
if (NEVER_MIGRATE.has(filename)) return false
|
|
343
355
|
if (ROOT_REQUIRED_FILES.has(filename)) return true
|
|
344
356
|
if (ROOT_REQUIRED_PATTERNS.some(p => p.test(filename))) return true
|
|
345
|
-
if (!isPatchable(filename)) return true // unknown file → safe default: copy to root
|
|
346
357
|
return false
|
|
347
358
|
}
|
|
348
359
|
|