xgem-cli 2.0.0-alpha.8 → 2.0.0-alpha.9

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 CHANGED
@@ -1,10 +1,14 @@
1
1
  # xgem
2
2
 
3
- A framework-aware automation CLI. `xgem init` scaffolds clean/build/dev scripts
4
- tailored to your project type (Flutter, Node, Python, React/Vue/Angular, Go,
5
- Rust, Docker, Swift), `xgem run <framework> <script>` runs them, `xgem doctor`
6
- reports on your environment, and `xgem git` wraps a common stage → commit →
7
- rebase-pull push workflow.
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
@@ -59,7 +63,36 @@ Flags (any command): --yes (skip confirmations), --dry-run (show, don't apply),
59
63
 
60
64
  ## Supported frameworks
61
65
 
62
- flutter, node, python, react, vue, angular, go, rust, docker, swift
66
+ flutter, node, python, react, vue, angular, next, go, rust, docker, swift
67
+
68
+ ## Creating a new project
69
+
70
+ `xgem init` asks, per framework, whether to create a brand-new project or use
71
+ what's already in the directory:
72
+
73
+ - **react**: Vite or Create React App ("the normal version"), then TypeScript
74
+ or JavaScript, then current directory or a new folder.
75
+ - **vue** / **next**: runs the official `create-vue`/`create-next-app` wizard
76
+ directly, so you get their own real prompts (router, Tailwind, App Router,
77
+ etc.) rather than a re-implementation of them.
78
+ - **angular**: `ng new` (via a local Angular CLI if you have one, `npx
79
+ @angular/cli` otherwise).
80
+ - **flutter**: `flutter create`, then lists available devices/simulators
81
+ (falling back to available-but-not-booted emulators you can launch) and
82
+ runs on whichever you pick.
83
+ - **node/python/go/rust/docker/swift**: the ecosystem's own minimal init
84
+ command (`npm init`, a `.venv`, `cargo new`, `go mod init`, a starter
85
+ Dockerfile, `swift package init`) — no sub-wizard, since these don't have
86
+ an equivalent "dev server" to launch.
87
+
88
+ For the frameworks with a dev server (react/vue/angular/next), after
89
+ dependencies install xgem offers to start it and open your default browser —
90
+ it tails the server's own log for the first `http://localhost:PORT` it
91
+ prints rather than guessing a framework's default port, so it works even if
92
+ that port's already taken and a different one gets picked.
93
+
94
+ Answering "existing" (the default) skips all of this and behaves exactly
95
+ like before — just scaffolds `.xgem-automate/` into the current directory.
63
96
 
64
97
  ## Architecture
65
98
 
@@ -73,6 +106,7 @@ lib/
73
106
  flutter.sh flutter command group (build/hard-clean/build-runner), delegates iOS builds to ios.sh
74
107
  git.sh git cmt/init/branch/rm-remote/rm-branch
75
108
  scaffold.sh generic clean/build/dev handling for the other, simpler frameworks
109
+ create.sh project creation wizards (react/vue/angular/next/simple frameworks)
76
110
  templates/ the actual clean/build/dev script content xgem scaffolds into your project's .xgem-automate/
77
111
  ```
78
112
 
@@ -134,6 +168,8 @@ Deferred to a follow-up pass, not yet in this release:
134
168
  - Shell completions, `--json` output, per-project config caching (stop re-prompting
135
169
  build name/number/platform every run)
136
170
  - Deeper Android SDK/Java detection
171
+ - Project creation wizards on the Windows engine (`lib-win/`) — react/vue/angular/next
172
+ scaffolding is pure Node.js tooling and would work fine there too, just not built yet
137
173
 
138
174
  ## License
139
175
 
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
 
@@ -85,12 +87,12 @@ case "${1:-}" in
85
87
  log_warn "Workspace configuration layer already exists! Use 'xgem add' to append frameworks."
86
88
  exit 0
87
89
  fi
88
- mkdir -p "$CONFIG_DIR"
89
-
90
90
  echo -e "\033[1;34mSelect your starting framework architecture:\033[0m"
91
91
  PS3="Enter target selection number: "
92
92
  select fw in "${ALL_FRAMEWORKS[@]}"; do
93
93
  if [ -n "$fw" ]; then
94
+ create_project_wizard "$fw"
95
+ mkdir -p "$CONFIG_DIR"
94
96
  scaffold_inject_templates "$fw" "$CONFIG_DIR"
95
97
  log_success "Successfully appended standard scripts for: $CONFIG_DIR/$fw"
96
98
  break
@@ -108,6 +110,8 @@ case "${1:-}" in
108
110
  echo "$CONFIG_DIR/" > .gitignore
109
111
  log_success "Created .gitignore and hidden tracking layer folder references."
110
112
  fi
113
+
114
+ _ask_launch_dev_server
111
115
  exit 0
112
116
  ;;
113
117
 
@@ -198,7 +202,7 @@ case "${1:-}" in
198
202
  exit 0
199
203
  ;;
200
204
 
201
- flutter|node|python|react|vue|angular|go|rust|docker|swift)
205
+ flutter|node|python|react|vue|angular|next|go|rust|docker|swift)
202
206
  TARGET_FW=$1
203
207
  TARGET_FW_UPPER=$(echo "$TARGET_FW" | tr '[:lower:]' '[:upper:]')
204
208
 
package/bin/xgem.js CHANGED
@@ -204,6 +204,7 @@ async function main() {
204
204
  case 'react':
205
205
  case 'vue':
206
206
  case 'angular':
207
+ case 'next':
207
208
  case 'go':
208
209
  case 'rust':
209
210
  case 'docker':
package/lib/create.sh ADDED
@@ -0,0 +1,226 @@
1
+ #!/bin/bash
2
+ # xgem project creation wizards — runs from `xgem init`, before
3
+ # scaffold_inject_templates, for frameworks with a real "ask sub-choice ->
4
+ # scaffold -> install -> launch" story worth building (react/vue/angular/
5
+ # next/flutter). The rest (node/python/go/rust/docker/swift) get a lighter
6
+ # "create with the ecosystem's own standard init command" step.
7
+ #
8
+ # Depends on lib/logger.sh, lib/utils.sh. Uses `cd` directly (no
9
+ # subshells) so a newly created project directory persists as the cwd for
10
+ # the rest of `xgem init` (template injection, .gitignore) without the
11
+ # caller needing to track/re-cd into a returned path.
12
+ #
13
+ # Dev-server launch is deliberately deferred: creators only set
14
+ # XGEM_POST_INIT_LAUNCH_CMD (an array) rather than launching immediately,
15
+ # so `xgem init` finishes template injection and .gitignore setup *before*
16
+ # handing the terminal over to a long-running dev server.
17
+ XGEM_POST_INIT_LAUNCH_CMD=()
18
+
19
+ # _prompt_project_location <human label> -> echoes "." or a new folder name.
20
+ # Pure prompt-and-echo, no other stdout output, so it's safe to capture via
21
+ # command substitution.
22
+ _prompt_project_location() {
23
+ local label=$1
24
+ local choice
25
+ read -r -p "Initialize $label in the current directory, or create a new folder? [current/new] (default: new): " choice
26
+ choice=${choice:-new}
27
+ if [[ "$choice" == c* || "$choice" == C* ]]; then
28
+ echo "."
29
+ return 0
30
+ fi
31
+ local name
32
+ read -r -p "Project name: " name
33
+ [ -n "$name" ] || die "Project name cannot be empty."
34
+ echo "$name"
35
+ }
36
+
37
+ _open_url() {
38
+ local url=$1
39
+ case "$(detect_os)" in
40
+ darwin) open "$url" 2>/dev/null ;;
41
+ linux) xdg-open "$url" 2>/dev/null ;;
42
+ *) log_debug "Don't know how to open a browser on this OS — visit $url manually." ;;
43
+ esac
44
+ }
45
+
46
+ # _launch_dev_server_and_open_browser <cmd...>
47
+ # Starts the dev server in the background, tails its log for the first
48
+ # http://localhost URL it prints — this works across Vite/CRA/Next/Angular
49
+ # without hardcoding any one framework's default port (which can differ or
50
+ # be taken already) — opens it, then waits so Ctrl-C stops the server
51
+ # normally instead of leaving it orphaned in the background.
52
+ _launch_dev_server_and_open_browser() {
53
+ local log_file
54
+ log_file=$(mktemp)
55
+ log_info "Starting dev server: $*"
56
+ "$@" > "$log_file" 2>&1 &
57
+ local server_pid=$!
58
+
59
+ local url="" waited=0
60
+ while [ -z "$url" ] && [ "$waited" -lt 30 ] && kill -0 "$server_pid" 2>/dev/null; do
61
+ url=$(grep -oE 'https?://(localhost|127\.0\.0\.1)[:0-9]*[^[:space:]]*' "$log_file" 2>/dev/null | head -1)
62
+ if [ -z "$url" ]; then
63
+ sleep 1
64
+ waited=$((waited + 1))
65
+ fi
66
+ done
67
+
68
+ if [ -n "$url" ]; then
69
+ log_success "Dev server up at $url"
70
+ _open_url "$url"
71
+ elif kill -0 "$server_pid" 2>/dev/null; then
72
+ log_warn "Dev server is running (pid $server_pid) but its URL wasn't detected automatically after ${waited}s — check the output below."
73
+ else
74
+ log_error "Dev server exited early."
75
+ fi
76
+
77
+ cat "$log_file" &
78
+ wait "$server_pid" 2>/dev/null
79
+ }
80
+
81
+ _ask_launch_dev_server() {
82
+ [ ${#XGEM_POST_INIT_LAUNCH_CMD[@]} -gt 0 ] || return 0
83
+ local answer
84
+ read -r -p "Launch the dev server now and open it in your browser? (Y/n): " answer
85
+ answer=${answer:-y}
86
+ [[ "$answer" == "y" || "$answer" == "Y" ]] && _launch_dev_server_and_open_browser "${XGEM_POST_INIT_LAUNCH_CMD[@]}"
87
+ }
88
+
89
+ _create_react() {
90
+ local variant lang project_dir
91
+ read -r -p "Use Vite or Create React App (the 'normal' version)? [vite/cra] (default: vite): " variant
92
+ variant=${variant:-vite}
93
+ read -r -p "TypeScript or JavaScript? [ts/js] (default: ts): " lang
94
+ lang=${lang:-ts}
95
+ project_dir=$(_prompt_project_location "React")
96
+
97
+ if [[ "$variant" == cra* || "$variant" == CRA* ]]; then
98
+ require_cmd npx "Install Node.js (npm ships with it): https://nodejs.org"
99
+ local -a args=(create-react-app)
100
+ [ "$project_dir" != "." ] && args+=("$project_dir") || args+=(.)
101
+ [ "$lang" = "ts" ] && args+=(--template typescript)
102
+ npx "${args[@]}" || die "create-react-app failed."
103
+ else
104
+ require_cmd npm "Install Node.js (npm ships with it): https://nodejs.org"
105
+ local template="react"
106
+ [ "$lang" = "ts" ] && template="react-ts"
107
+ npm create vite@latest "$project_dir" -- --template "$template" || die "npm create vite failed."
108
+ fi
109
+
110
+ [ "$project_dir" != "." ] && { cd "$project_dir" || die "Could not enter $project_dir"; }
111
+ log_info "Installing dependencies..."
112
+ npm install
113
+ XGEM_POST_INIT_LAUNCH_CMD=(npm run dev)
114
+ }
115
+
116
+ _create_vue() {
117
+ require_cmd npm "Install Node.js (npm ships with it): https://nodejs.org"
118
+ local project_dir
119
+ project_dir=$(_prompt_project_location "Vue")
120
+ npm create vue@latest "$project_dir" || die "npm create vue failed."
121
+ [ "$project_dir" != "." ] && { cd "$project_dir" || die "Could not enter $project_dir"; }
122
+ log_info "Installing dependencies..."
123
+ npm install
124
+ XGEM_POST_INIT_LAUNCH_CMD=(npm run dev)
125
+ }
126
+
127
+ _create_angular() {
128
+ local project_dir
129
+ project_dir=$(_prompt_project_location "Angular")
130
+ local -a ng_cmd=(ng)
131
+ has_cmd ng || ng_cmd=(npx @angular/cli@latest)
132
+
133
+ if [ "$project_dir" = "." ]; then
134
+ "${ng_cmd[@]}" new "$(basename "$PWD")" --directory=. || die "ng new failed."
135
+ else
136
+ "${ng_cmd[@]}" new "$project_dir" || die "ng new failed."
137
+ cd "$project_dir" || die "Could not enter $project_dir"
138
+ fi
139
+ XGEM_POST_INIT_LAUNCH_CMD=(npm run start)
140
+ }
141
+
142
+ _create_next() {
143
+ require_cmd npx "Install Node.js (npm ships with it): https://nodejs.org"
144
+ local project_dir
145
+ project_dir=$(_prompt_project_location "Next.js")
146
+ npx create-next-app@latest "$project_dir" || die "create-next-app failed."
147
+ [ "$project_dir" != "." ] && { cd "$project_dir" || die "Could not enter $project_dir"; }
148
+ XGEM_POST_INIT_LAUNCH_CMD=(npm run dev)
149
+ }
150
+
151
+ # Lighter path for frameworks without a dev-server/browser story — just the
152
+ # ecosystem's own standard init command, no sub-wizard.
153
+ _create_simple() {
154
+ local fw=$1
155
+ local project_dir
156
+ project_dir=$(_prompt_project_location "$fw")
157
+ [ "$project_dir" != "." ] && { mkdir -p "$project_dir" && cd "$project_dir" || die "Could not enter $project_dir"; }
158
+
159
+ case "$fw" in
160
+ node)
161
+ require_cmd npm "Install Node.js (npm ships with it): https://nodejs.org"
162
+ npm init -y
163
+ ;;
164
+ python)
165
+ require_cmd python3 "Install Python 3: https://www.python.org/downloads/"
166
+ python3 -m venv .venv
167
+ log_success "Created .venv — activate with 'source .venv/bin/activate'."
168
+ ;;
169
+ go)
170
+ require_cmd go "Install Go: https://go.dev/doc/install"
171
+ local module_name
172
+ read -r -p "Module name (e.g. github.com/you/project): " module_name
173
+ [ -n "$module_name" ] || module_name=$(basename "$PWD")
174
+ go mod init "$module_name"
175
+ ;;
176
+ rust)
177
+ require_cmd cargo "Install Rust: https://www.rust-lang.org/tools/install"
178
+ if [ "$project_dir" != "." ]; then
179
+ cd .. || return 1
180
+ cargo new "$project_dir" || die "cargo new failed."
181
+ cd "$project_dir" || die "Could not enter $project_dir"
182
+ else
183
+ cargo init || die "cargo init failed."
184
+ fi
185
+ ;;
186
+ swift)
187
+ require_cmd swift "Install Swift: https://www.swift.org/install/"
188
+ swift package init --type executable
189
+ ;;
190
+ docker)
191
+ if [ ! -f Dockerfile ]; then
192
+ cat > Dockerfile << 'EOF'
193
+ FROM alpine:latest
194
+ WORKDIR /app
195
+ COPY . .
196
+ CMD ["sh"]
197
+ EOF
198
+ log_success "Created a starter Dockerfile — edit it for your actual base image/entrypoint."
199
+ else
200
+ log_warn "Dockerfile already exists, leaving it as-is."
201
+ fi
202
+ ;;
203
+ esac
204
+ }
205
+
206
+ # create_project_wizard <framework>
207
+ # Asks whether to create a new project or use what's already here; if
208
+ # creating, dispatches to the right per-framework creator. Leaves the
209
+ # process cwd inside the (possibly new) project directory either way.
210
+ create_project_wizard() {
211
+ local fw=$1
212
+ local create_choice
213
+ read -r -p "Create a brand-new $fw project, or use what's already in this directory? [new/existing] (default: existing): " create_choice
214
+ create_choice=${create_choice:-existing}
215
+ [[ "$create_choice" == n* || "$create_choice" == N* ]] || return 0
216
+
217
+ case "$fw" in
218
+ react) _create_react ;;
219
+ vue) _create_vue ;;
220
+ angular) _create_angular ;;
221
+ next) _create_next ;;
222
+ flutter) create_flutter_project ;;
223
+ node|python|go|rust|docker|swift) _create_simple "$fw" ;;
224
+ *) log_debug "No creation wizard for '$fw'; using current directory as-is." ;;
225
+ esac
226
+ }
package/lib/flutter.sh CHANGED
@@ -237,3 +237,106 @@ flutter_run_native_command() {
237
237
  *) die "No native flutter command for '$script'." ;;
238
238
  esac
239
239
  }
240
+
241
+ # create_flutter_project — used by lib/create.sh's create_project_wizard.
242
+ # `flutter create` needs a target dir; "." scaffolds into the current one.
243
+ create_flutter_project() {
244
+ require_cmd flutter "Install Flutter: https://docs.flutter.dev/get-started/install"
245
+ local project_dir
246
+ project_dir=$(_prompt_project_location "Flutter")
247
+ if [ "$project_dir" = "." ]; then
248
+ flutter create . || die "flutter create failed."
249
+ else
250
+ flutter create "$project_dir" || die "flutter create failed."
251
+ cd "$project_dir" || die "Could not enter $project_dir"
252
+ fi
253
+ _flutter_offer_run_on_device
254
+ }
255
+
256
+ # _flutter_select_device -> echoes the chosen device id, or nothing if
257
+ # none available/selected. Uses `flutter devices --machine` (JSON) parsed
258
+ # with python3 — already a soft dependency elsewhere in lib/ios.sh for the
259
+ # same reason (no jq assumed present).
260
+ _flutter_select_device() {
261
+ require_cmd python3 "Needed to parse 'flutter devices --machine' output."
262
+ local devices_json_file
263
+ devices_json_file=$(mktemp)
264
+ flutter devices --machine > "$devices_json_file" 2>/dev/null
265
+
266
+ local -a ids=() labels=()
267
+ while IFS='|' read -r id label; do
268
+ [ -n "$id" ] || continue
269
+ ids+=("$id")
270
+ labels+=("$label")
271
+ done < <(python3 - "$devices_json_file" <<'PYEOF'
272
+ import json, sys
273
+
274
+ try:
275
+ with open(sys.argv[1]) as f:
276
+ devices = json.load(f)
277
+ except Exception:
278
+ devices = []
279
+
280
+ for d in devices:
281
+ platform = d.get("platform") or d.get("targetPlatform") or ""
282
+ name = d.get("name", "unknown")
283
+ device_id = d.get("id", "")
284
+ print(f"{device_id}|{name} ({platform})")
285
+ PYEOF
286
+ )
287
+ rm -f "$devices_json_file"
288
+
289
+ if [ ${#ids[@]} -eq 0 ]; then
290
+ log_warn "No running devices/simulators found."
291
+ _flutter_offer_launch_emulator
292
+ return 1
293
+ fi
294
+
295
+ echo "Available devices:" >&2
296
+ local i
297
+ for i in "${!ids[@]}"; do
298
+ echo "$((i + 1))) ${labels[$i]}" >&2
299
+ done
300
+
301
+ local choice
302
+ read -r -p "Select a device [1-${#ids[@]}]: " choice
303
+ if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -lt 1 ] || [ "$choice" -gt "${#ids[@]}" ]; then
304
+ log_warn "Invalid selection."
305
+ return 1
306
+ fi
307
+ echo "${ids[$((choice - 1))]}"
308
+ }
309
+
310
+ # No running devices — check for available-but-not-booted emulators and
311
+ # offer to launch one, matching the "check available simulators... then
312
+ # launch it" behavior the user asked for.
313
+ _flutter_offer_launch_emulator() {
314
+ local emulators_output
315
+ emulators_output=$(flutter emulators 2>/dev/null)
316
+ [ -n "$emulators_output" ] || return 1
317
+
318
+ echo "$emulators_output"
319
+ local launch_choice
320
+ read -r -p "Launch one of these emulators? Enter its id, or leave blank to skip: " launch_choice
321
+ [ -n "$launch_choice" ] || return 1
322
+
323
+ log_info "Launching emulator '$launch_choice'..."
324
+ flutter emulators --launch "$launch_choice"
325
+ log_info "Waiting for it to boot..."
326
+ sleep 5
327
+ }
328
+
329
+ _flutter_offer_run_on_device() {
330
+ local run_choice
331
+ read -r -p "Run the app now on a device/simulator? (Y/n): " run_choice
332
+ run_choice=${run_choice:-y}
333
+ [[ "$run_choice" == "y" || "$run_choice" == "Y" ]] || return 0
334
+
335
+ local device_id
336
+ device_id=$(_flutter_select_device)
337
+ if [ -n "$device_id" ]; then
338
+ flutter run -d "$device_id"
339
+ else
340
+ log_warn "No device selected — run 'flutter run' manually once one is available."
341
+ fi
342
+ }
package/lib/scaffold.sh CHANGED
@@ -11,14 +11,14 @@
11
11
  #
12
12
  # Depends on lib/logger.sh and XGEM_HOME (set by bin/xgem).
13
13
 
14
- ALL_FRAMEWORKS=(flutter node python react vue angular go rust docker swift)
14
+ ALL_FRAMEWORKS=(flutter node python react vue angular next go rust docker swift)
15
15
 
16
16
  framework_scripts() {
17
17
  case "$1" in
18
18
  flutter) echo "hard-clean build build-runner" ;;
19
19
  node) echo "hard-clean build start" ;;
20
20
  python) echo "hard-clean install" ;;
21
- react|vue|angular) echo "hard-clean build dev" ;;
21
+ react|vue|angular|next) echo "hard-clean build dev" ;;
22
22
  go) echo "hard-clean build" ;;
23
23
  rust) echo "hard-clean build" ;;
24
24
  docker) echo "hard-clean build-up" ;;
@@ -30,8 +30,8 @@ framework_scripts() {
30
30
  _scaffold_template_dir() {
31
31
  local framework=$1
32
32
  case "$framework" in
33
- react|vue|angular) echo "$XGEM_HOME/templates/webframework" ;;
34
- *) echo "$XGEM_HOME/templates/$framework" ;;
33
+ react|vue|angular|next) echo "$XGEM_HOME/templates/webframework" ;;
34
+ *) echo "$XGEM_HOME/templates/$framework" ;;
35
35
  esac
36
36
  }
37
37
 
package/lib/version.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  # xgem version info.
3
3
 
4
- XGEM_VERSION="2.0.0-alpha.8"
4
+ XGEM_VERSION="2.0.0-alpha.9"
5
5
 
6
6
  print_version() {
7
7
  echo "xgem $XGEM_VERSION"
@@ -7,7 +7,7 @@ const path = require('node:path');
7
7
  const { spawnSync } = require('node:child_process');
8
8
  const { logInfo, logSuccess, logWarn, logError, die } = require('./logger');
9
9
 
10
- const ALL_FRAMEWORKS = ['flutter', 'node', 'python', 'react', 'vue', 'angular', 'go', 'rust', 'docker'];
10
+ const ALL_FRAMEWORKS = ['flutter', 'node', 'python', 'react', 'vue', 'angular', 'next', 'go', 'rust', 'docker'];
11
11
 
12
12
  const FRAMEWORK_SCRIPTS = {
13
13
  flutter: ['hard-clean', 'build', 'build-runner'],
@@ -16,6 +16,7 @@ const FRAMEWORK_SCRIPTS = {
16
16
  react: ['hard-clean', 'build', 'dev'],
17
17
  vue: ['hard-clean', 'build', 'dev'],
18
18
  angular: ['hard-clean', 'build', 'dev'],
19
+ next: ['hard-clean', 'build', 'dev'],
19
20
  go: ['hard-clean', 'build'],
20
21
  rust: ['hard-clean', 'build'],
21
22
  docker: ['hard-clean', 'build-up'],
@@ -27,7 +28,7 @@ function frameworkScripts(fw) {
27
28
 
28
29
  function templateDir(fw) {
29
30
  const templatesRoot = path.join(__dirname, '..', 'templates-win');
30
- if (fw === 'react' || fw === 'vue' || fw === 'angular') {
31
+ if (fw === 'react' || fw === 'vue' || fw === 'angular' || fw === 'next') {
31
32
  return path.join(templatesRoot, 'webframework');
32
33
  }
33
34
  return path.join(templatesRoot, fw);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xgem-cli",
3
- "version": "2.0.0-alpha.8",
3
+ "version": "2.0.0-alpha.9",
4
4
  "description": "Framework-aware automation CLI: scaffolds and runs clean/build/dev scripts per project type, an environment doctor, a SwiftPM-aware iOS build engine, and a git workflow helper. Runs natively on macOS, Linux, and Windows.",
5
5
  "bin": {
6
6
  "xgem": "bin/xgem.js"