xgem-cli 2.0.0-alpha.1 → 2.0.0-alpha.12
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 +53 -31
- package/bin/xgem +21 -14
- package/bin/xgem.js +235 -0
- package/lib/create.sh +334 -0
- package/lib/doctor.sh +13 -2
- package/lib/flutter.sh +163 -18
- package/lib/git.sh +157 -23
- package/lib/ios.sh +126 -47
- package/lib/scaffold.sh +24 -5
- package/lib/version.sh +1 -1
- package/lib-win/doctor.js +44 -0
- package/lib-win/flutter.js +101 -0
- package/lib-win/git.js +279 -0
- package/lib-win/logger.js +35 -0
- package/lib-win/scaffold.js +102 -0
- package/lib-win/utils.js +67 -0
- package/package.json +8 -7
- package/templates/node/build.sh.tmpl +9 -1
- package/templates/node/hard-clean.sh.tmpl +34 -2
- package/templates/node/lint.sh.tmpl +10 -0
- package/templates/node/start.sh.tmpl +9 -1
- package/templates/node/test.sh.tmpl +10 -0
- package/templates/webframework/build.sh.tmpl +10 -1
- package/templates/webframework/dev.sh.tmpl +9 -1
- package/templates/webframework/hard-clean.sh.tmpl +35 -2
- package/templates/webframework/lint.sh.tmpl +10 -0
- package/templates/webframework/test.sh.tmpl +10 -0
- package/templates-win/docker/build-up.mjs.tmpl +3 -0
- package/templates-win/docker/hard-clean.mjs.tmpl +4 -0
- package/templates-win/flutter/build-runner.mjs.tmpl +4 -0
- package/templates-win/flutter/build.mjs.tmpl +4 -0
- package/templates-win/flutter/hard-clean.mjs.tmpl +6 -0
- package/templates-win/go/build.mjs.tmpl +3 -0
- package/templates-win/go/hard-clean.mjs.tmpl +4 -0
- package/templates-win/node/build.mjs.tmpl +10 -0
- package/templates-win/node/hard-clean.mjs.tmpl +28 -0
- package/templates-win/node/lint.mjs.tmpl +10 -0
- package/templates-win/node/start.mjs.tmpl +10 -0
- package/templates-win/node/test.mjs.tmpl +10 -0
- package/templates-win/python/hard-clean.mjs.tmpl +8 -0
- package/templates-win/python/install.mjs.tmpl +12 -0
- package/templates-win/rust/build.mjs.tmpl +3 -0
- package/templates-win/rust/hard-clean.mjs.tmpl +3 -0
- package/templates-win/webframework/build.mjs.tmpl +10 -0
- package/templates-win/webframework/dev.mjs.tmpl +10 -0
- package/templates-win/webframework/hard-clean.mjs.tmpl +32 -0
- package/templates-win/webframework/lint.mjs.tmpl +10 -0
- package/templates-win/webframework/test.mjs.tmpl +10 -0
- package/scripts/check-platform.js +0 -17
package/README.md
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
# xgem
|
|
2
2
|
|
|
3
|
-
A framework-aware automation CLI. `xgem init`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
A framework-aware automation CLI. `xgem init` can create a brand-new project
|
|
4
|
+
(real `npm create vite`/`create-next-app`/`create-vue`/`ng new`/`flutter create`
|
|
5
|
+
scaffolding, framework-specific questions, dependency install, and launching
|
|
6
|
+
the dev server in your browser or the app on a picked device/simulator) or
|
|
7
|
+
just scaffold clean/build/dev scripts into a project you already have
|
|
8
|
+
(Flutter, Node, Python, React/Vue/Angular/Next, Go, Rust, Docker, Swift).
|
|
9
|
+
`xgem run <framework> <script>` runs those scripts, `xgem doctor` reports on
|
|
10
|
+
your environment, and `xgem git` wraps a common stage → commit → rebase-pull
|
|
11
|
+
→ push workflow.
|
|
8
12
|
|
|
9
13
|
Flutter's iOS builds go through a dedicated engine that detects whether your
|
|
10
14
|
project uses CocoaPods or Swift Package Manager (SPM), figures out the actual
|
|
11
15
|
deployment target your resolved SPM plugins require (instead of guessing),
|
|
12
|
-
and reconciles it automatically
|
|
16
|
+
and reconciles it automatically.
|
|
17
|
+
|
|
18
|
+
**Full documentation: [docs/](https://github.com/Code4Hacker/x-gem-cli/blob/xgem/docs/README.md)** — getting started, every command in
|
|
19
|
+
depth, exactly what each framework's project-creation wizard does, the iOS build
|
|
20
|
+
engine explained, Windows support, and troubleshooting. This README is a summary.
|
|
21
|
+
(Absolute link on purpose — `docs/` isn't shipped inside the npm package itself,
|
|
22
|
+
so a relative link would 404 on npmjs.com's rendered README.)
|
|
13
23
|
|
|
14
24
|
## Install
|
|
15
25
|
|
|
@@ -27,7 +37,8 @@ xgem isn't in Homebrew's central `homebrew-core` (that requires a formal submiss
|
|
|
27
37
|
npm install -g xgem-cli
|
|
28
38
|
```
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
Works natively on Windows too (no WSL needed) — npm's install runs a small Node.js
|
|
41
|
+
engine there instead of the bash one; see [Windows support](#windows-support).
|
|
31
42
|
|
|
32
43
|
### curl
|
|
33
44
|
|
|
@@ -48,6 +59,7 @@ xgem doctor ios [path] Report on iOS build readiness: CocoaPods vs SPM, d
|
|
|
48
59
|
targets per config, and whether they're reconciled
|
|
49
60
|
xgem git cmt "message" Auto-stage, commit, rebase-pull, and push
|
|
50
61
|
xgem git init Setup local repo, attach remote tracker shortcuts
|
|
62
|
+
xgem git branch Pick, create, or switch branches; remembers your choice
|
|
51
63
|
xgem git rm-remote Drop a configured remote
|
|
52
64
|
xgem git rm-branch Safely drop local and/or remote branch
|
|
53
65
|
xgem --version Print xgem's version
|
|
@@ -57,7 +69,18 @@ Flags (any command): --yes (skip confirmations), --dry-run (show, don't apply),
|
|
|
57
69
|
|
|
58
70
|
## Supported frameworks
|
|
59
71
|
|
|
60
|
-
flutter, node, python, react, vue, angular, go, rust, docker, swift
|
|
72
|
+
flutter, node, python, react, vue, angular, next, go, rust, docker, swift
|
|
73
|
+
|
|
74
|
+
## Creating a new project
|
|
75
|
+
|
|
76
|
+
`xgem init` asks, per framework, whether to create a brand-new project or use
|
|
77
|
+
what's already in the directory — real `create-vite`/`create-vue`/`ng new`/
|
|
78
|
+
`create-next-app`/`flutter create` scaffolding, with framework-specific
|
|
79
|
+
questions and a working dev-server/device launch at the end. Package manager
|
|
80
|
+
(npm/yarn/pnpm/bun) is auto-detected everywhere, never assumed. Answering
|
|
81
|
+
"existing" (the default) skips all of this and just scaffolds
|
|
82
|
+
`.xgem-automate/` into the current directory. Full detail, including exactly
|
|
83
|
+
what runs for each framework: **[docs/frameworks.md](https://github.com/Code4Hacker/x-gem-cli/blob/xgem/docs/frameworks.md)**.
|
|
61
84
|
|
|
62
85
|
## Architecture
|
|
63
86
|
|
|
@@ -69,8 +92,9 @@ lib/
|
|
|
69
92
|
doctor.sh environment + feature detection ("xgem doctor")
|
|
70
93
|
ios.sh the SwiftPM-aware iOS build engine
|
|
71
94
|
flutter.sh flutter command group (build/hard-clean/build-runner), delegates iOS builds to ios.sh
|
|
72
|
-
git.sh git cmt/init/rm-remote/rm-branch
|
|
95
|
+
git.sh git cmt/init/branch/rm-remote/rm-branch
|
|
73
96
|
scaffold.sh generic clean/build/dev handling for the other, simpler frameworks
|
|
97
|
+
create.sh project creation wizards (react/vue/angular/next/simple frameworks)
|
|
74
98
|
templates/ the actual clean/build/dev script content xgem scaffolds into your project's .xgem-automate/
|
|
75
99
|
```
|
|
76
100
|
|
|
@@ -82,29 +106,25 @@ of logic that can drift out of sync with two copies.
|
|
|
82
106
|
## Why the iOS build engine exists
|
|
83
107
|
|
|
84
108
|
Flutter auto-generates a wrapper Swift package, `FlutterGeneratedPluginSwiftPackage`,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
upstream Flutter bug
|
|
109
|
+
whose declared minimum iOS platform can desync from your app's own
|
|
110
|
+
`IPHONEOS_DEPLOYMENT_TARGET` — independently, even when your app's own target is
|
|
111
|
+
already high enough. This is a confirmed, currently-open upstream Flutter bug
|
|
112
|
+
([flutter/flutter#186804](https://github.com/flutter/flutter/issues/186804),
|
|
88
113
|
[#189422](https://github.com/flutter/flutter/issues/189422),
|
|
89
|
-
[#162072](https://github.com/flutter/flutter/issues/162072)).
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
and verifies the regenerated package matches.
|
|
104
|
-
5. If it still doesn't (the upstream bug above), patches the generated package directly
|
|
105
|
-
as a documented, loudly-logged last resort — never silently.
|
|
106
|
-
|
|
107
|
-
Run `xgem doctor ios` any time for a standalone readiness report without doing a build.
|
|
114
|
+
[#162072](https://github.com/flutter/flutter/issues/162072)). `xgem run flutter build`
|
|
115
|
+
(iOS target) detects the actual requirement from your resolved SPM plugins, patches
|
|
116
|
+
every deployment-target occurrence, forces a clean regeneration, verifies it, and
|
|
117
|
+
falls back to a documented direct patch if the upstream bug is still biting — full
|
|
118
|
+
detail: **[docs/ios-build-engine.md](https://github.com/Code4Hacker/x-gem-cli/blob/xgem/docs/ios-build-engine.md)**. Run `xgem doctor ios`
|
|
119
|
+
any time for a standalone readiness report without doing a build.
|
|
120
|
+
|
|
121
|
+
## Windows support
|
|
122
|
+
|
|
123
|
+
Homebrew and the curl installer are macOS/Linux only, same as any bash tool. npm is
|
|
124
|
+
different: it ships a small native Windows engine (`lib-win/`) so `npm install -g
|
|
125
|
+
xgem-cli` actually works in `cmd.exe`/PowerShell, no WSL required — everything except
|
|
126
|
+
Flutter iOS/macOS builds (Xcode has no Windows equivalent) and the project-creation
|
|
127
|
+
wizards (not ported yet). Full detail: **[docs/windows.md](https://github.com/Code4Hacker/x-gem-cli/blob/xgem/docs/windows.md)**.
|
|
108
128
|
|
|
109
129
|
## Roadmap
|
|
110
130
|
|
|
@@ -114,6 +134,8 @@ Deferred to a follow-up pass, not yet in this release:
|
|
|
114
134
|
- Shell completions, `--json` output, per-project config caching (stop re-prompting
|
|
115
135
|
build name/number/platform every run)
|
|
116
136
|
- Deeper Android SDK/Java detection
|
|
137
|
+
- Project creation wizards on the Windows engine (`lib-win/`) — react/vue/angular/next
|
|
138
|
+
scaffolding is pure Node.js tooling and would work fine there too, just not built yet
|
|
117
139
|
|
|
118
140
|
## License
|
|
119
141
|
|
package/bin/xgem
CHANGED
|
@@ -33,6 +33,8 @@ source "$XGEM_HOME/lib/ios.sh"
|
|
|
33
33
|
source "$XGEM_HOME/lib/flutter.sh"
|
|
34
34
|
# shellcheck source=lib/scaffold.sh
|
|
35
35
|
source "$XGEM_HOME/lib/scaffold.sh"
|
|
36
|
+
# shellcheck source=lib/create.sh
|
|
37
|
+
source "$XGEM_HOME/lib/create.sh"
|
|
36
38
|
|
|
37
39
|
CONFIG_DIR=".xgem-automate"
|
|
38
40
|
|
|
@@ -70,6 +72,7 @@ print_usage() {
|
|
|
70
72
|
echo " xgem doctor [ios] - Report on your environment / iOS SwiftPM build readiness"
|
|
71
73
|
echo " xgem git cmt \"message\" - Auto-stage, commit, rebase-pull, and push"
|
|
72
74
|
echo " xgem git init - Setup local repo, attach remote tracker shortcuts"
|
|
75
|
+
echo " xgem git branch - Pick, create, or switch branches; remembers your choice"
|
|
73
76
|
echo " xgem git rm-remote - Drop specified target remote tracing rules"
|
|
74
77
|
echo " xgem git rm-branch - Safely drop local and remote workspace branch states"
|
|
75
78
|
echo " xgem --version - Print xgem's version"
|
|
@@ -84,28 +87,32 @@ case "${1:-}" in
|
|
|
84
87
|
log_warn "Workspace configuration layer already exists! Use 'xgem add' to append frameworks."
|
|
85
88
|
exit 0
|
|
86
89
|
fi
|
|
87
|
-
mkdir -p "$CONFIG_DIR"
|
|
88
|
-
|
|
89
90
|
echo -e "\033[1;34mSelect your starting framework architecture:\033[0m"
|
|
90
91
|
PS3="Enter target selection number: "
|
|
91
92
|
select fw in "${ALL_FRAMEWORKS[@]}"; do
|
|
92
93
|
if [ -n "$fw" ]; then
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
# create_project_wizard handles ALL of xgem's own
|
|
95
|
+
# bookkeeping (.xgem-automate + .gitignore) internally now,
|
|
96
|
+
# at the earliest safe point for each framework — never
|
|
97
|
+
# after a slow/interruptible step, so a Ctrl-C during (say)
|
|
98
|
+
# `ng new`'s install can no longer lose it. See lib/create.sh.
|
|
99
|
+
create_project_wizard "$fw"
|
|
95
100
|
break
|
|
96
101
|
else
|
|
97
102
|
echo "Invalid selection."
|
|
98
103
|
fi
|
|
99
104
|
done
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
_ask_launch_dev_server
|
|
107
|
+
|
|
108
|
+
# A child process (this script) can never change the parent
|
|
109
|
+
# shell's cwd — xgem's own process correctly cd'd into the new
|
|
110
|
+
# project folder for everything above, but your actual terminal
|
|
111
|
+
# is still wherever it started. Say so explicitly instead of
|
|
112
|
+
# leaving you to discover it the confusing way.
|
|
113
|
+
if [ -n "$XGEM_CREATED_NEW_FOLDER" ]; then
|
|
114
|
+
echo ""
|
|
115
|
+
log_info "Your project is in ./$XGEM_CREATED_NEW_FOLDER — your terminal is still in the original directory. Run: cd $XGEM_CREATED_NEW_FOLDER"
|
|
109
116
|
fi
|
|
110
117
|
exit 0
|
|
111
118
|
;;
|
|
@@ -182,7 +189,7 @@ case "${1:-}" in
|
|
|
182
189
|
;;
|
|
183
190
|
|
|
184
191
|
git)
|
|
185
|
-
[ -n "${2:-}" ] || die "Usage: xgem git <cmt|init|rm-remote|rm-branch>"
|
|
192
|
+
[ -n "${2:-}" ] || die "Usage: xgem git <cmt|init|branch|rm-remote|rm-branch>"
|
|
186
193
|
cmd_git "$2" "${3:-}"
|
|
187
194
|
exit 0
|
|
188
195
|
;;
|
|
@@ -197,7 +204,7 @@ case "${1:-}" in
|
|
|
197
204
|
exit 0
|
|
198
205
|
;;
|
|
199
206
|
|
|
200
|
-
flutter|node|python|react|vue|angular|go|rust|docker|swift)
|
|
207
|
+
flutter|node|python|react|vue|angular|next|go|rust|docker|swift)
|
|
201
208
|
TARGET_FW=$1
|
|
202
209
|
TARGET_FW_UPPER=$(echo "$TARGET_FW" | tr '[:lower:]' '[:upper:]')
|
|
203
210
|
|
package/bin/xgem.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// xgem npm entrypoint. On macOS/Linux this is a thin passthrough to the
|
|
3
|
+
// real, already-tested bash bin/xgem sitting next to it — zero logic
|
|
4
|
+
// duplication, zero behavioral change for POSIX users. On Windows it runs
|
|
5
|
+
// the native lib-win/*.js engine, since bash doesn't exist there.
|
|
6
|
+
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const { spawnSync } = require('node:child_process');
|
|
9
|
+
|
|
10
|
+
if (process.platform !== 'win32') {
|
|
11
|
+
const bashScript = path.join(__dirname, 'xgem');
|
|
12
|
+
const result = spawnSync(bashScript, process.argv.slice(2), { stdio: 'inherit' });
|
|
13
|
+
process.exit(result.status ?? 0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ---- Windows-native engine ----
|
|
17
|
+
const fs = require('node:fs');
|
|
18
|
+
const { logInfo, logSuccess, logWarn, logError, die, paint } = require('../lib-win/logger');
|
|
19
|
+
const { prompt } = require('../lib-win/utils');
|
|
20
|
+
const { cmdDoctor } = require('../lib-win/doctor');
|
|
21
|
+
const { cmdGit } = require('../lib-win/git');
|
|
22
|
+
const { cmdFlutter } = require('../lib-win/flutter');
|
|
23
|
+
const scaffold = require('../lib-win/scaffold');
|
|
24
|
+
|
|
25
|
+
const CONFIG_DIR = '.xgem-automate';
|
|
26
|
+
|
|
27
|
+
function printBanner() {
|
|
28
|
+
console.log(paint('yellow', ''));
|
|
29
|
+
console.log('██╗ ██╗ ██████╗ ███████╗███╗ ███╗██╗███╗ ██╗██╗');
|
|
30
|
+
console.log('╚██╗██╔╝ ██╔════╝ ██╔════╝████╗ ████║██║████╗ ██║██║');
|
|
31
|
+
console.log(' ╚███╔╝ █████╗██║ ███╗█████╗ ██╔████╔██║██║██╔██╗ ██║██║');
|
|
32
|
+
console.log(' ██╔██╗ ╚════╝██║ ██║██╔══╝ ██║╚██╔╝██║██║██║╚██╗██║██║');
|
|
33
|
+
console.log('██╔╝ ██╗ ╚██████╔╝███████╗██║ ╚═╝ ██║██║██║ ╚████║██║');
|
|
34
|
+
console.log('╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝');
|
|
35
|
+
console.log(paint('cyan', ' ....Windows engine....\n'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function printUsage() {
|
|
39
|
+
console.log('Usage:');
|
|
40
|
+
console.log(' xgem init - Initialize tracking system and add first framework');
|
|
41
|
+
console.log(' xgem add - Interactive state-aware addition of remaining frameworks');
|
|
42
|
+
console.log(' xgem run <framework> <script> - Run a workspace automation command script');
|
|
43
|
+
console.log(' xgem terminate - Purge all generated automated layouts completely');
|
|
44
|
+
console.log(' xgem <framework> [help] - View tailored instructions for a specific script layout');
|
|
45
|
+
console.log(' xgem doctor [ios] - Report on your environment / iOS build availability');
|
|
46
|
+
console.log(' xgem git cmt "message" - Auto-stage, commit, rebase-pull, and push');
|
|
47
|
+
console.log(' xgem git init - Setup local repo, attach remote tracker shortcuts');
|
|
48
|
+
console.log(' xgem git branch - Pick, create, or switch branches; remembers your choice');
|
|
49
|
+
console.log(' xgem git rm-remote - Drop specified target remote tracing rules');
|
|
50
|
+
console.log(' xgem git rm-branch - Safely drop local and remote workspace branch states');
|
|
51
|
+
console.log(' xgem --version - Print xgem\'s version');
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log('Flags (any command): --yes (skip confirmations), --dry-run (show, don\'t apply), --verbose');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function selectFramework(options) {
|
|
57
|
+
options.forEach((fw, i) => console.log(`${i + 1}) ${fw}`));
|
|
58
|
+
const choice = await prompt('Enter target selection number');
|
|
59
|
+
const idx = parseInt(choice, 10) - 1;
|
|
60
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= options.length) return null;
|
|
61
|
+
return options[idx];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Some teams want the generated scripts checked in so collaborators get the
|
|
65
|
+
// same automation; others want them private/local-only. Ask instead of
|
|
66
|
+
// always gitignoring.
|
|
67
|
+
async function updateGitignore() {
|
|
68
|
+
const gitignorePath = '.gitignore';
|
|
69
|
+
const ignoreChoice = ((await prompt(`Should ${CONFIG_DIR}/ be ignored by git (private to you), or tracked so collaborators get the same scripts? [ignore/track]`, 'ignore'))).toLowerCase();
|
|
70
|
+
|
|
71
|
+
if (ignoreChoice.startsWith('t')) {
|
|
72
|
+
if (fs.existsSync(gitignorePath)) {
|
|
73
|
+
const lines = fs.readFileSync(gitignorePath, 'utf8').split(/\r?\n/).filter((l) => l !== `${CONFIG_DIR}/`);
|
|
74
|
+
fs.writeFileSync(gitignorePath, lines.join('\n'));
|
|
75
|
+
logInfo(`Removed existing ${CONFIG_DIR}/ entry from .gitignore since you chose to track it.`);
|
|
76
|
+
}
|
|
77
|
+
logSuccess(`${CONFIG_DIR}/ will be tracked in git.`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (fs.existsSync(gitignorePath)) {
|
|
82
|
+
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
83
|
+
if (!content.includes(`${CONFIG_DIR}/`)) {
|
|
84
|
+
fs.appendFileSync(gitignorePath, `\n${CONFIG_DIR}/\n`);
|
|
85
|
+
logSuccess('Added automation tracking to .gitignore');
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
fs.writeFileSync(gitignorePath, `${CONFIG_DIR}/\n`);
|
|
89
|
+
logSuccess('Created .gitignore and hidden tracking layer folder references.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function cmdInit() {
|
|
94
|
+
printBanner();
|
|
95
|
+
if (fs.existsSync(CONFIG_DIR)) {
|
|
96
|
+
logWarn("Workspace configuration layer already exists! Use 'xgem add' to append frameworks.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
100
|
+
|
|
101
|
+
console.log('Select your starting framework architecture:');
|
|
102
|
+
const fw = await selectFramework(scaffold.ALL_FRAMEWORKS);
|
|
103
|
+
if (!fw) die('Invalid selection.');
|
|
104
|
+
scaffold.injectTemplates(fw, CONFIG_DIR);
|
|
105
|
+
logSuccess(`Successfully appended standard scripts for: ${CONFIG_DIR}/${fw}`);
|
|
106
|
+
|
|
107
|
+
await updateGitignore();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function cmdAdd() {
|
|
111
|
+
if (!fs.existsSync(CONFIG_DIR)) die("System tracking layer not found. Run 'xgem init' first.");
|
|
112
|
+
|
|
113
|
+
const remaining = scaffold.getRemainingFrameworks(CONFIG_DIR);
|
|
114
|
+
if (remaining.length === 0) {
|
|
115
|
+
logWarn('All available framework blocks are already generated inside the workspace!');
|
|
116
|
+
const restore = (await prompt('Do you want to restore/regenerate all framework templates to defaults? (y/n)')).toLowerCase();
|
|
117
|
+
if (restore === 'y') {
|
|
118
|
+
for (const fw of scaffold.ALL_FRAMEWORKS) scaffold.injectTemplates(fw, CONFIG_DIR);
|
|
119
|
+
logSuccess('All framework automation layouts cleanly re-generated!');
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log('Select a framework script block to add:');
|
|
125
|
+
const fw = await selectFramework(remaining);
|
|
126
|
+
if (!fw) { console.log('Operation canceled.'); return; }
|
|
127
|
+
scaffold.injectTemplates(fw, CONFIG_DIR);
|
|
128
|
+
logSuccess(`Successfully loaded and updated files for: ${CONFIG_DIR}/${fw}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function cmdRun(fw, script) {
|
|
132
|
+
if (!fw || !script) die('Usage: xgem run <framework> <script>');
|
|
133
|
+
if (fw === 'flutter' && ['hard-clean', 'build', 'build-runner'].includes(script)) {
|
|
134
|
+
await cmdFlutter(script);
|
|
135
|
+
} else {
|
|
136
|
+
scaffold.runScript(fw, script, CONFIG_DIR);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function cmdTerminate() {
|
|
141
|
+
if (!fs.existsSync(CONFIG_DIR)) die(`Tracking layer ${CONFIG_DIR} not found. Nothing to terminate.`);
|
|
142
|
+
|
|
143
|
+
logWarn(`Initiating core termination sequence for ${CONFIG_DIR}...`);
|
|
144
|
+
const folders = fs.readdirSync(CONFIG_DIR, { withFileTypes: true })
|
|
145
|
+
.filter((d) => d.isDirectory())
|
|
146
|
+
.map((d) => d.name);
|
|
147
|
+
|
|
148
|
+
const { confirm } = require('../lib-win/utils');
|
|
149
|
+
const ok = await confirm(`This deletes ${CONFIG_DIR} and everything in it. Continue?`);
|
|
150
|
+
if (!ok) { logInfo('Cancelled.'); return; }
|
|
151
|
+
|
|
152
|
+
for (const fw of folders) {
|
|
153
|
+
console.log(` [ x ] Removing ${fw}...`);
|
|
154
|
+
fs.rmSync(path.join(CONFIG_DIR, fw), { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
fs.rmSync(CONFIG_DIR, { recursive: true, force: true });
|
|
157
|
+
|
|
158
|
+
if (fs.existsSync('.gitignore')) {
|
|
159
|
+
const lines = fs.readFileSync('.gitignore', 'utf8').split(/\r?\n/).filter((l) => l !== `${CONFIG_DIR}/`);
|
|
160
|
+
fs.writeFileSync('.gitignore', lines.join('\n'));
|
|
161
|
+
logSuccess('Cleaned up .gitignore tracking records.');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
logSuccess(`Termination complete. Total blocks destroyed: ${folders.length} (${folders.join(', ') || 'none'})`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function printFrameworkHelp(fw) {
|
|
168
|
+
console.log(paint('cyan', `=== ${fw.toUpperCase()} Automation Blueprint (Windows) ===`));
|
|
169
|
+
if (!fs.existsSync(path.join(CONFIG_DIR, fw))) {
|
|
170
|
+
logWarn('Status: Not currently injected in this workspace.');
|
|
171
|
+
console.log("Run 'xgem add' to instantly append its structural scripts.\n");
|
|
172
|
+
} else {
|
|
173
|
+
logSuccess(`Status: Active & Mounted inside ${CONFIG_DIR}/${fw}/`);
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
console.log(`To execute scripts, use: xgem run ${fw} <script>\n`);
|
|
177
|
+
console.log('Configured Commands:');
|
|
178
|
+
for (const script of scaffold.frameworkScripts(fw) || []) {
|
|
179
|
+
console.log(` ${script}`);
|
|
180
|
+
}
|
|
181
|
+
if (fw === 'flutter') {
|
|
182
|
+
console.log('');
|
|
183
|
+
logInfo("Flutter builds on Windows support APK, App Bundle, and Windows desktop targets. Run 'xgem doctor ios' for why iOS/macOS aren't available here.");
|
|
184
|
+
}
|
|
185
|
+
console.log('');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function main() {
|
|
189
|
+
const rawArgs = process.argv.slice(2);
|
|
190
|
+
const args = [];
|
|
191
|
+
for (const arg of rawArgs) {
|
|
192
|
+
if (arg === '--yes') process.env.XGEM_YES = '1';
|
|
193
|
+
else if (arg === '--dry-run') process.env.XGEM_DRY_RUN = '1';
|
|
194
|
+
else if (arg === '--verbose') process.env.XGEM_VERBOSE = '1';
|
|
195
|
+
else args.push(arg);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const [cmd, a2, a3] = args;
|
|
199
|
+
|
|
200
|
+
switch (cmd) {
|
|
201
|
+
case 'init': return cmdInit();
|
|
202
|
+
case 'add': return cmdAdd();
|
|
203
|
+
case 'run': return cmdRun(a2, a3);
|
|
204
|
+
case 'terminate': return cmdTerminate();
|
|
205
|
+
case 'git':
|
|
206
|
+
if (!a2) die('Usage: xgem git <cmt|init|branch|rm-remote|rm-branch>');
|
|
207
|
+
return cmdGit(a2, a3);
|
|
208
|
+
case 'doctor': return cmdDoctor(a2);
|
|
209
|
+
case '--version':
|
|
210
|
+
case '-V':
|
|
211
|
+
case 'version': {
|
|
212
|
+
const pkg = require('../package.json');
|
|
213
|
+
console.log(`xgem ${pkg.version} (Windows engine)`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
case 'flutter':
|
|
217
|
+
case 'node':
|
|
218
|
+
case 'python':
|
|
219
|
+
case 'react':
|
|
220
|
+
case 'vue':
|
|
221
|
+
case 'angular':
|
|
222
|
+
case 'next':
|
|
223
|
+
case 'go':
|
|
224
|
+
case 'rust':
|
|
225
|
+
case 'docker':
|
|
226
|
+
return printFrameworkHelp(cmd);
|
|
227
|
+
default:
|
|
228
|
+
return printUsage();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
main().catch((err) => {
|
|
233
|
+
logError(err.message || String(err));
|
|
234
|
+
process.exit(1);
|
|
235
|
+
});
|