taskdex 0.1.0 → 0.1.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/README.md +2 -0
- package/package.json +1 -1
- package/scripts/taskdex.mjs +67 -10
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@ taskdex init
|
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
This will clone the repo and immediately run interactive terminal setup.
|
|
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
|
+
When a `pnpm-lock.yaml` is present in `mobile`, the CLI installs mobile dependencies with pnpm automatically.
|
|
38
40
|
|
|
39
41
|
For an already-cloned repo:
|
|
40
42
|
|
package/package.json
CHANGED
package/scripts/taskdex.mjs
CHANGED
|
@@ -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')) &&
|
|
@@ -134,6 +144,22 @@ function parseExpoMode(input) {
|
|
|
134
144
|
return normalized;
|
|
135
145
|
}
|
|
136
146
|
|
|
147
|
+
function parseRuntime(input) {
|
|
148
|
+
const normalized = input.trim().toLowerCase() || 'dev-client';
|
|
149
|
+
if (['dev-client', 'dev', 'devbuild', 'dev-build'].includes(normalized)) return 'dev-client';
|
|
150
|
+
if (['expo-go', 'go', 'expo'].includes(normalized)) return 'expo-go';
|
|
151
|
+
throw new Error('Runtime must be "dev-client" or "expo-go".');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function parseBuildPlatform(input) {
|
|
155
|
+
const fallback = process.platform === 'darwin' ? 'ios' : 'android';
|
|
156
|
+
const normalized = input.trim().toLowerCase() || fallback;
|
|
157
|
+
if (!['ios', 'android'].includes(normalized)) {
|
|
158
|
+
throw new Error('Build platform must be "ios" or "android".');
|
|
159
|
+
}
|
|
160
|
+
return normalized;
|
|
161
|
+
}
|
|
162
|
+
|
|
137
163
|
function parseInstallChoice(input) {
|
|
138
164
|
const normalized = input.trim().toLowerCase();
|
|
139
165
|
if (!normalized || normalized === 'y' || normalized === 'yes') return true;
|
|
@@ -152,12 +178,27 @@ async function readSetupConfig() {
|
|
|
152
178
|
const portInput = await rl.question('Bridge port [3001]: ');
|
|
153
179
|
const apiKeyInput = await rl.question('Bridge API key [auto-generate]: ');
|
|
154
180
|
const expoModeInput = await rl.question('Expo mode (lan/tunnel) [lan]: ');
|
|
181
|
+
const runtimeInput = await rl.question('App runtime (dev-client/expo-go) [dev-client]: ');
|
|
155
182
|
const installInput = await rl.question('Install npm dependencies first? [Y/n]: ');
|
|
183
|
+
const runtime = parseRuntime(runtimeInput);
|
|
184
|
+
let buildDevClient = false;
|
|
185
|
+
let buildPlatform = process.platform === 'darwin' ? 'ios' : 'android';
|
|
186
|
+
if (runtime === 'dev-client') {
|
|
187
|
+
const buildInput = await rl.question('Build native development client now? [Y/n]: ');
|
|
188
|
+
buildDevClient = parseInstallChoice(buildInput);
|
|
189
|
+
if (buildDevClient) {
|
|
190
|
+
const platformInput = await rl.question(`Build platform (ios/android) [${buildPlatform}]: `);
|
|
191
|
+
buildPlatform = parseBuildPlatform(platformInput);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
156
194
|
|
|
157
195
|
return {
|
|
158
196
|
port: parsePort((portInput || '3001').trim()),
|
|
159
197
|
apiKey: apiKeyInput.trim() || crypto.randomBytes(24).toString('hex'),
|
|
160
198
|
expoMode: parseExpoMode(expoModeInput),
|
|
199
|
+
runtime,
|
|
200
|
+
buildDevClient,
|
|
201
|
+
buildPlatform,
|
|
161
202
|
installDeps: parseInstallChoice(installInput),
|
|
162
203
|
};
|
|
163
204
|
} finally {
|
|
@@ -172,7 +213,7 @@ async function runInteractiveSetup(rootDir) {
|
|
|
172
213
|
throw new Error(`Invalid Taskdex repository at ${rootDir}`);
|
|
173
214
|
}
|
|
174
215
|
|
|
175
|
-
const { port, apiKey, expoMode, installDeps } = await readSetupConfig();
|
|
216
|
+
const { port, apiKey, expoMode, runtime, buildDevClient, buildPlatform, installDeps } = await readSetupConfig();
|
|
176
217
|
const bridgeUrl = `ws://${getLocalIPv4()}:${port}`;
|
|
177
218
|
|
|
178
219
|
console.log(`\nBridge URL: ${bridgeUrl}`);
|
|
@@ -182,8 +223,10 @@ async function runInteractiveSetup(rootDir) {
|
|
|
182
223
|
if (installDeps) {
|
|
183
224
|
console.log('Installing bridge dependencies...\n');
|
|
184
225
|
await runCommand(npmCmd, ['install'], { cwd: bridgeDir });
|
|
226
|
+
// Keep older clones working where this dependency might be missing.
|
|
227
|
+
await runCommand(npmCmd, ['install', 'qrcode-terminal@^0.12.0'], { cwd: bridgeDir });
|
|
185
228
|
console.log('\nInstalling mobile dependencies...\n');
|
|
186
|
-
await
|
|
229
|
+
await installMobileDependencies(mobileDir);
|
|
187
230
|
}
|
|
188
231
|
|
|
189
232
|
console.log('\nStarting bridge server...\n');
|
|
@@ -204,18 +247,32 @@ async function runInteractiveSetup(rootDir) {
|
|
|
204
247
|
|
|
205
248
|
await wait(1200);
|
|
206
249
|
|
|
250
|
+
const expoEnv = {
|
|
251
|
+
...process.env,
|
|
252
|
+
EXPO_PUBLIC_BRIDGE_URL: bridgeUrl,
|
|
253
|
+
EXPO_PUBLIC_BRIDGE_API_KEY: apiKey,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if (runtime === 'dev-client' && buildDevClient) {
|
|
257
|
+
console.log(`\nBuilding native dev client (${buildPlatform})...\n`);
|
|
258
|
+
await runCommand(npxCmd, ['expo', `run:${buildPlatform}`, '--no-bundler'], {
|
|
259
|
+
cwd: mobileDir,
|
|
260
|
+
env: expoEnv,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
207
264
|
console.log('\nStarting Expo. Scan the QR code to open the app.');
|
|
208
265
|
console.log('Bridge URL and API key are prefilled from this terminal setup.\n');
|
|
266
|
+
if (runtime === 'dev-client' && !buildDevClient) {
|
|
267
|
+
console.log('If dev client is not installed yet, rerun setup and enable native build.\n');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const expoArgs = runtime === 'dev-client'
|
|
271
|
+
? ['expo', 'start', '--dev-client', `--${expoMode}`]
|
|
272
|
+
: ['expo', 'start', `--${expoMode}`];
|
|
209
273
|
|
|
210
274
|
try {
|
|
211
|
-
await runCommand(npxCmd,
|
|
212
|
-
cwd: mobileDir,
|
|
213
|
-
env: {
|
|
214
|
-
...process.env,
|
|
215
|
-
EXPO_PUBLIC_BRIDGE_URL: bridgeUrl,
|
|
216
|
-
EXPO_PUBLIC_BRIDGE_API_KEY: apiKey,
|
|
217
|
-
},
|
|
218
|
-
});
|
|
275
|
+
await runCommand(npxCmd, expoArgs, { cwd: mobileDir, env: expoEnv });
|
|
219
276
|
} finally {
|
|
220
277
|
if (!bridgeProcess.killed) {
|
|
221
278
|
bridgeProcess.kill('SIGTERM');
|