kasy-cli 1.31.5 → 1.31.6

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.
@@ -7,9 +7,7 @@ const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
7
7
  const { printCompactHeader } = require('../utils/brand');
8
8
  const { readBundleId, readPackageName } = require('../utils/mobile-identity');
9
9
  const { spawnFlutterWithSpinner } = require('../utils/flutter-run');
10
- const { augmentedEnv } = require('../utils/env-tools');
11
-
12
- const isWindows = process.platform === 'win32';
10
+ const { spawnSyncFlutter } = require('../utils/env-tools');
13
11
 
14
12
  function runCmd(cmd, args) {
15
13
  const res = spawnSync(cmd, args, { encoding: 'utf8' });
@@ -21,11 +19,9 @@ function runCmd(cmd, args) {
21
19
  }
22
20
 
23
21
  async function listFlutterDevices(projectDir) {
24
- const res = spawnSync('flutter', ['devices', '--machine'], {
22
+ const res = spawnSyncFlutter(['devices', '--machine'], {
25
23
  cwd: projectDir,
26
24
  encoding: 'utf8',
27
- env: augmentedEnv(),
28
- shell: isWindows,
29
25
  });
30
26
  if (res.status !== 0) return [];
31
27
  try {
@@ -1,25 +1,20 @@
1
1
  const path = require('node:path');
2
- const { spawnSync } = require('node:child_process');
3
2
  const fs = require('fs-extra');
4
3
  const kleur = require('kleur');
5
4
  const ui = require('../utils/ui');
6
5
  const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
7
6
  const { printCompactHeader, paintLime } = require('../utils/brand');
8
7
  const { spawnFlutterWithSpinner } = require('../utils/flutter-run');
9
- const { augmentedEnv } = require('../utils/env-tools');
10
-
11
- const isWindows = process.platform === 'win32';
8
+ const { spawnSyncFlutter } = require('../utils/env-tools');
12
9
 
13
10
  function listFlutterDevices(projectDir) {
14
- // Same as `kasy run`'s launcher: expose a freshly-installed Flutter SDK via
15
- // augmentedEnv() (the terminal's PATH may not have it yet), and use a shell on
16
- // Windows so the flutter.bat is found. Without this, a machine that just ran
17
- // `kasy new` reports "Flutter not found" here even though Flutter is installed.
18
- const res = spawnSync('flutter', ['devices', '--machine'], {
11
+ // Shared flutter spawner: exposes a freshly-installed SDK on PATH (the terminal
12
+ // may not have it yet right after `kasy new`) and handles the Windows flutter.bat
13
+ // without tripping Node's shell+args deprecation warning. Without it, a machine
14
+ // that just ran `kasy new` reports "Flutter not found" here.
15
+ const res = spawnSyncFlutter(['devices', '--machine'], {
19
16
  cwd: projectDir,
20
17
  encoding: 'utf8',
21
- env: augmentedEnv(),
22
- shell: isWindows,
23
18
  });
24
19
  if (res.status !== 0) return [];
25
20
  try {
@@ -19,6 +19,7 @@
19
19
  const os = require('node:os');
20
20
  const path = require('node:path');
21
21
  const fs = require('node:fs');
22
+ const { spawn, spawnSync } = require('node:child_process');
22
23
 
23
24
  const isWindows = process.platform === 'win32';
24
25
  const PATH_SEP = isWindows ? ';' : ':';
@@ -179,6 +180,27 @@ function augmentedEnv(extraDirs = []) {
179
180
  return env;
180
181
  }
181
182
 
183
+ /**
184
+ * Spawn `flutter <args>` cross-platform, with the (possibly freshly-installed)
185
+ * SDK exposed on PATH via augmentedEnv().
186
+ *
187
+ * On Windows `flutter` is a .bat, which Node's spawn() refuses to run without a
188
+ * shell. But passing an ARGS ARRAY *together with* shell:true triggers Node's
189
+ * DEP0190 deprecation warning — and that warning, emitted asynchronously while a
190
+ * Clack prompt is on screen, corrupts its redraw (the device picker shows up
191
+ * duplicated). So on Windows we build ONE command STRING and pass shell:true with
192
+ * no args array (no array + shell ⇒ no warning); on Unix we pass the plain args.
193
+ */
194
+ function flutterSpawn(spawnFn, args, options = {}) {
195
+ const base = { env: augmentedEnv(), ...options };
196
+ if (!isWindows) return spawnFn('flutter', args, base);
197
+ const quoted = args.map((a) => (/\s/.test(a) ? `"${a}"` : a));
198
+ return spawnFn(['flutter', ...quoted].join(' '), { ...base, shell: true });
199
+ }
200
+
201
+ const spawnFlutter = (args, options) => flutterSpawn(spawn, args, options);
202
+ const spawnSyncFlutter = (args, options) => flutterSpawn(spawnSync, args, options);
203
+
182
204
  module.exports = {
183
205
  isWindows,
184
206
  homeDir,
@@ -186,4 +208,6 @@ module.exports = {
186
208
  pubCacheBin,
187
209
  keytoolBin,
188
210
  augmentedEnv,
211
+ spawnFlutter,
212
+ spawnSyncFlutter,
189
213
  };
@@ -28,29 +28,9 @@
28
28
 
29
29
  const path = require('node:path');
30
30
  const fs = require('node:fs');
31
- const { spawn } = require('node:child_process');
32
31
  const kleur = require('kleur');
33
32
  const ui = require('./ui');
34
- const { augmentedEnv } = require('./env-tools');
35
-
36
- const isWindows = process.platform === 'win32';
37
-
38
- // `flutter` runs from an SDK that may have been installed by `kasy new` in this
39
- // same session — and Windows only refreshes PATH for NEW terminals, so the
40
- // current one doesn't see it yet. augmentedEnv() exposes %LOCALAPPDATA%\flutter\bin
41
- // (and the pub-cache bin) so `kasy run` finds flutter exactly like `kasy new` did.
42
- // On Windows `flutter` is a .bat, which Node's spawn() refuses to run without a
43
- // shell — hence shell:true there. With shell:true the args become a command line,
44
- // so any arg with a space must be quoted (our flutter args normally have none,
45
- // but a dart-define value could).
46
- function flutterSpawnOptions(extra = {}) {
47
- return { env: augmentedEnv(), shell: isWindows, ...extra };
48
- }
49
-
50
- function safeArgs(args) {
51
- if (!isWindows) return args;
52
- return args.map((a) => (/\s/.test(a) ? `"${a}"` : a));
53
- }
33
+ const { spawnFlutter } = require('./env-tools');
54
34
 
55
35
  // Markers that tell us the initial build is done and the app is running.
56
36
  const FLUTTER_READY_RE = /Flutter run key commands\.|is listening on|VM Service|Dart VM service|To hot reload|Hot restart/i;
@@ -160,10 +140,10 @@ function spawnFlutterWithSpinner(args, projectDir, t, options = {}) {
160
140
  */
161
141
  function spawnRaw(args, projectDir, t, log, onReady) {
162
142
  return new Promise((resolve, reject) => {
163
- const proc = spawn('flutter', safeArgs(args), flutterSpawnOptions({
143
+ const proc = spawnFlutter(args, {
164
144
  cwd: projectDir,
165
145
  stdio: ['inherit', 'pipe', 'pipe'],
166
- }));
146
+ });
167
147
 
168
148
  let readyFired = false;
169
149
  const fireReady = () => {
@@ -212,10 +192,10 @@ function spawnRaw(args, projectDir, t, log, onReady) {
212
192
  */
213
193
  function spawnWithSpinner(args, projectDir, t, log, onReady) {
214
194
  return new Promise((resolve, reject) => {
215
- const proc = spawn('flutter', safeArgs(args), flutterSpawnOptions({
195
+ const proc = spawnFlutter(args, {
216
196
  cwd: projectDir,
217
197
  stdio: ['pipe', 'pipe', 'pipe'],
218
- }));
198
+ });
219
199
 
220
200
  const spinner = ui.spinner();
221
201
  const startTime = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kasy-cli",
3
- "version": "1.31.5",
3
+ "version": "1.31.6",
4
4
  "description": "CLI for scaffolding production-ready Flutter SaaS apps with Firebase, Supabase, or API REST backends.",
5
5
  "bin": {
6
6
  "kasy": "./bin/kasy.js"