taskdex 0.1.1 → 0.1.3

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
@@ -36,6 +36,8 @@ taskdex init
36
36
 
37
37
  This will clone the repo and immediately run interactive terminal setup.
38
38
  Setup now defaults to `dev-client` runtime, can build the native app (`expo run:ios` / `expo run:android`), and then starts Expo in `--dev-client` mode.
39
+ For iOS builds, setup asks whether to run on a real iPhone or Simulator, and supports choosing a specific iPhone device name.
40
+ When a `pnpm-lock.yaml` is present in `mobile`, the CLI installs mobile dependencies with pnpm automatically.
39
41
 
40
42
  For an already-cloned repo:
41
43
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskdex",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Terminal-first installer and launcher for Taskdex mobile + bridge",
5
5
  "type": "module",
6
6
  "bin": {
@@ -43,6 +43,16 @@ function runCommand(command, args, options = {}) {
43
43
  });
44
44
  }
45
45
 
46
+ async function installMobileDependencies(mobileDir) {
47
+ const hasPnpmLock = existsSync(path.join(mobileDir, 'pnpm-lock.yaml'));
48
+ if (hasPnpmLock) {
49
+ // Expo mobile app in this repo is pnpm-based; npm can fail on some npm/arborist versions.
50
+ await runCommand(npxCmd, ['-y', 'pnpm@9', 'install'], { cwd: mobileDir });
51
+ return;
52
+ }
53
+ await runCommand(npmCmd, ['install'], { cwd: mobileDir });
54
+ }
55
+
46
56
  function isTaskdexRepo(dir) {
47
57
  return (
48
58
  existsSync(path.join(dir, 'bridge-server')) &&
@@ -150,6 +160,13 @@ function parseBuildPlatform(input) {
150
160
  return normalized;
151
161
  }
152
162
 
163
+ function parseIosTarget(input) {
164
+ const normalized = input.trim().toLowerCase() || 'iphone';
165
+ if (['iphone', 'device', 'physical'].includes(normalized)) return 'iphone';
166
+ if (['simulator', 'sim', 'ios-simulator'].includes(normalized)) return 'simulator';
167
+ throw new Error('iOS target must be "iphone" or "simulator".');
168
+ }
169
+
153
170
  function parseInstallChoice(input) {
154
171
  const normalized = input.trim().toLowerCase();
155
172
  if (!normalized || normalized === 'y' || normalized === 'yes') return true;
@@ -173,12 +190,21 @@ async function readSetupConfig() {
173
190
  const runtime = parseRuntime(runtimeInput);
174
191
  let buildDevClient = false;
175
192
  let buildPlatform = process.platform === 'darwin' ? 'ios' : 'android';
193
+ let iosTarget = 'iphone';
194
+ let iosDeviceName = '';
176
195
  if (runtime === 'dev-client') {
177
196
  const buildInput = await rl.question('Build native development client now? [Y/n]: ');
178
197
  buildDevClient = parseInstallChoice(buildInput);
179
198
  if (buildDevClient) {
180
199
  const platformInput = await rl.question(`Build platform (ios/android) [${buildPlatform}]: `);
181
200
  buildPlatform = parseBuildPlatform(platformInput);
201
+ if (buildPlatform === 'ios') {
202
+ const targetInput = await rl.question('iOS target (iphone/simulator) [iphone]: ');
203
+ iosTarget = parseIosTarget(targetInput);
204
+ if (iosTarget === 'iphone') {
205
+ iosDeviceName = (await rl.question('iPhone device name (optional, Enter to choose automatically): ')).trim();
206
+ }
207
+ }
182
208
  }
183
209
  }
184
210
 
@@ -189,6 +215,8 @@ async function readSetupConfig() {
189
215
  runtime,
190
216
  buildDevClient,
191
217
  buildPlatform,
218
+ iosTarget,
219
+ iosDeviceName,
192
220
  installDeps: parseInstallChoice(installInput),
193
221
  };
194
222
  } finally {
@@ -203,7 +231,17 @@ async function runInteractiveSetup(rootDir) {
203
231
  throw new Error(`Invalid Taskdex repository at ${rootDir}`);
204
232
  }
205
233
 
206
- const { port, apiKey, expoMode, runtime, buildDevClient, buildPlatform, installDeps } = await readSetupConfig();
234
+ const {
235
+ port,
236
+ apiKey,
237
+ expoMode,
238
+ runtime,
239
+ buildDevClient,
240
+ buildPlatform,
241
+ iosTarget,
242
+ iosDeviceName,
243
+ installDeps,
244
+ } = await readSetupConfig();
207
245
  const bridgeUrl = `ws://${getLocalIPv4()}:${port}`;
208
246
 
209
247
  console.log(`\nBridge URL: ${bridgeUrl}`);
@@ -216,7 +254,7 @@ async function runInteractiveSetup(rootDir) {
216
254
  // Keep older clones working where this dependency might be missing.
217
255
  await runCommand(npmCmd, ['install', 'qrcode-terminal@^0.12.0'], { cwd: bridgeDir });
218
256
  console.log('\nInstalling mobile dependencies...\n');
219
- await runCommand(npmCmd, ['install'], { cwd: mobileDir });
257
+ await installMobileDependencies(mobileDir);
220
258
  }
221
259
 
222
260
  console.log('\nStarting bridge server...\n');
@@ -245,7 +283,16 @@ async function runInteractiveSetup(rootDir) {
245
283
 
246
284
  if (runtime === 'dev-client' && buildDevClient) {
247
285
  console.log(`\nBuilding native dev client (${buildPlatform})...\n`);
248
- await runCommand(npxCmd, ['expo', `run:${buildPlatform}`, '--no-bundler'], {
286
+ const buildArgs = ['expo', `run:${buildPlatform}`, '--no-bundler'];
287
+ if (buildPlatform === 'ios' && iosTarget === 'iphone') {
288
+ if (iosDeviceName) {
289
+ buildArgs.push('--device', iosDeviceName);
290
+ } else {
291
+ buildArgs.push('--device');
292
+ }
293
+ }
294
+
295
+ await runCommand(npxCmd, buildArgs, {
249
296
  cwd: mobileDir,
250
297
  env: expoEnv,
251
298
  });