swytchcode 2.5.2 → 2.6.0

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.
Files changed (2) hide show
  1. package/bin/swytchcode.js +81 -46
  2. package/package.json +7 -7
package/bin/swytchcode.js CHANGED
@@ -186,9 +186,10 @@ function apiPost(urlStr, body) {
186
186
  }
187
187
 
188
188
  // ─── Binary resolution (shared by normal pass-through AND onboarding) ────────
189
- function spawnBin(binPath, args) {
189
+ function spawnBin(binPath, args, extraEnv = {}) {
190
+ const env = { ...process.env, ...extraEnv };
190
191
  if (process.stdin.isTTY) {
191
- return spawnSync(binPath, args, { stdio: 'inherit' });
192
+ return spawnSync(binPath, args, { stdio: 'inherit', env });
192
193
  }
193
194
  let stdinData;
194
195
  try { stdinData = fs.readFileSync(0); }
@@ -196,6 +197,7 @@ function spawnBin(binPath, args) {
196
197
  return spawnSync(binPath, args, {
197
198
  stdio: ['pipe', 'inherit', 'inherit'],
198
199
  input: stdinData,
200
+ env,
199
201
  });
200
202
  }
201
203
 
@@ -266,22 +268,47 @@ const isNpx =
266
268
  (process.env.npm_execpath || '').includes('npx');
267
269
 
268
270
  const userArgs = process.argv.slice(2);
269
-
271
+ // Capture original arg BEFORE mutation
272
+ const originalArg = process.argv[2] || '';
273
+ const isCanonicalDemoArg = /^[\w]+\.[\w.]+$/.test(originalArg) && !originalArg.startsWith('-');
270
274
  // Legacy support: npx swytchcode <canonical_id> → npx swytchcode exec <canonical_id>
271
275
  if (userArgs.length > 0 && /^[\w]+\.[\w.]+$/.test(userArgs[0]) && !userArgs[0].startsWith('-')) {
272
276
  userArgs.unshift('exec');
273
277
  }
278
+ async function runOnboardingDirectDemo(canonicalId) {
279
+ writeln();
280
+ writeln(` ${c.yellow}⚡ Running ${c.bold}${canonicalId}${c.reset}${c.yellow} live...${c.reset}`);
281
+ writeln();
282
+ const demoResult = spawnBin(binPath, ['exec', canonicalId], { SWYTCHCODE_ONBOARDING: '1' });
283
+ writeln();
284
+ if (demoResult.status === 0) {
285
+ writeln(` ${c.dim}That was a real API call through Swytchcode.${c.reset}`);
286
+ writeln();
287
+ } else {
288
+ writeln(` ${c.yellow}⚠ ${c.bold}${canonicalId}${c.reset}${c.yellow} isn't a valid demo tool.${c.reset}`);
289
+ writeln(` ${c.dim}Let's run a working demo instead.${c.reset}`);
290
+ writeln();
291
+ await runDemoSelection();
292
+ }
293
+ await runOnboardingSteps2to4();
294
+ }
274
295
 
275
- // ─── Normal pass-through (not npx, or npx with args) ────────────────────────
276
- if (!isNpx || userArgs.length > 0) {
296
+ // ─── Normal pass-through (not npx, or npx with non-demo args) ───────────────
297
+ if (!isNpx || (userArgs.length > 0 && !isCanonicalDemoArg)) {
277
298
  const result = spawnBin(binPath, userArgs);
278
299
  if (result.error) {
279
300
  err(`swytchcode: failed to launch binary: ${result.error.message}`);
280
- process.exit(1);
281
301
  }
282
302
  process.exit(exitCode(result));
283
303
  }
284
-
304
+ // ─── NPX with canonical ID: run demo directly then show onboarding ───────────
305
+ if (isNpx && isCanonicalDemoArg) {
306
+ runOnboardingDirectDemo(originalArg).catch(e => {
307
+ err(`\nswytchcode: onboarding error (${e.message}) — falling back to CLI.\n`);
308
+ const result = spawnBin(binPath, userArgs);
309
+ process.exit(exitCode(result));
310
+ });
311
+ } else {
285
312
  // ─── NPX ONBOARDING FLOW ─────────────────────────────────────────────────────
286
313
  // Only reached when: isNpx === true AND no args passed (bare `npx swytchcode`)
287
314
 
@@ -311,6 +338,49 @@ function apiGet(urlStr) {
311
338
  req.end();
312
339
  });
313
340
  }
341
+
342
+ }
343
+
344
+ async function runDemoSelection() {
345
+ let demoTools = [];
346
+ try {
347
+ const res = await apiGet(`${API_BASE}/demo/tools`);
348
+ if (res.status === 200 && Array.isArray(res.body.tools)) {
349
+ demoTools = res.body.tools;
350
+ }
351
+ } catch (_) {}
352
+
353
+ if (demoTools.length === 0) {
354
+ writeln(`${c.yellow} Demo unavailable right now — skipping to setup.${c.reset}`);
355
+ writeln();
356
+ return;
357
+ }
358
+
359
+ const friendlyName = {
360
+ 'stripe.create_payment': 'Stripe — Create a payment ($20.00)',
361
+ };
362
+
363
+ const demoOptions = demoTools.map(t => ({
364
+ label: friendlyName[t] || t,
365
+ value: t,
366
+ }));
367
+ demoOptions.push({ label: 'Skip demo', value: '__skip__' });
368
+
369
+ const chosen = await menuArrow('Choose a demo to run:', demoOptions);
370
+
371
+ if (chosen !== '__skip__') {
372
+ writeln();
373
+ writeln(` ${c.gray}$ swytchcode demo stripe${c.reset}`);
374
+ spawnSync(binPath, ['demo', 'stripe'], {
375
+ stdio: 'inherit',
376
+ env: { ...process.env, SWYTCHCODE_ONBOARDING: '1' }
377
+ });
378
+ writeln();
379
+ writeln(` ${c.dim}That was a real API call. No credentials, no setup.${c.reset}`);
380
+ writeln(` ${c.dim}With Swytchcode, every API integration works exactly like this.${c.reset}`);
381
+ }
382
+ }
383
+
314
384
  async function runOnboarding() {
315
385
  let cliVersion = '0.0.0';
316
386
  try {
@@ -342,45 +412,11 @@ async function runOnboarding() {
342
412
  writeln(`${c.bold} Step 1 of 4 — See it in action${c.reset}`);
343
413
  writeln(`${c.dim} Run a live API call right now, no setup required.${c.reset}`);
344
414
  writeln();
415
+ await runDemoSelection();
416
+ await runOnboardingSteps2to4();
417
+ }
345
418
 
346
- // Fetch available demo tools
347
- let demoTools = [];
348
- try {
349
- const res = await apiGet(`${API_BASE}/demo/tools`);
350
- if (res.status === 200 && Array.isArray(res.body.tools)) {
351
- demoTools = res.body.tools;
352
- }
353
- } catch (_) {
354
- // silently fall through — skip demo if API is unreachable
355
- }
356
-
357
- if (demoTools.length === 0) {
358
- writeln(`${c.yellow} Demo unavailable right now — skipping to setup.${c.reset}`);
359
- writeln();
360
- } else {
361
- // Map tool IDs to friendly names
362
- const friendlyName = {
363
- 'stripe.create_payment': 'Stripe — Create a payment ($20.00)',
364
- };
365
-
366
- const demoOptions = demoTools.map(t => ({
367
- label: friendlyName[t] || t,
368
- value: t,
369
- }));
370
- demoOptions.push({ label: 'Skip demo', value: '__skip__' });
371
-
372
- const chosen = await menuArrow('Choose a demo to run:', demoOptions);
373
-
374
- if (chosen !== '__skip__') {
375
- writeln();
376
- writeln(` ${c.gray}$ swytchcode demo stripe${c.reset}`);
377
- spawnSync(binPath, ['demo', 'stripe'], { stdio: 'inherit' });
378
- writeln();
379
- writeln(` ${c.dim}That was a real API call. No credentials, no setup.${c.reset}`);
380
- writeln(` ${c.dim}With Swytchcode, every API integration works exactly like this.${c.reset}`);
381
- }
382
- }
383
-
419
+ async function runOnboardingSteps2to4() {
384
420
  // ── Step 2: Install ───────────────────────────────────────────────────────
385
421
  writeln();
386
422
  writeln(' ' + '─'.repeat(45));
@@ -505,7 +541,6 @@ async function runOnboarding() {
505
541
  }
506
542
 
507
543
  runOnboarding().catch(e => {
508
- // If onboarding crashes for any reason, fall back to normal binary pass-through
509
544
  err(`\nswytchcode: onboarding error (${e.message}) — falling back to CLI.\n`);
510
545
  const result = spawnBin(binPath, userArgs);
511
546
  process.exit(exitCode(result));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swytchcode",
3
- "version": "2.5.2",
3
+ "version": "2.6.0",
4
4
  "description": "Execution authority layer for API integrations",
5
5
  "keywords": [
6
6
  "api",
@@ -23,11 +23,11 @@
23
23
  "README.md"
24
24
  ],
25
25
  "optionalDependencies": {
26
- "swytchcode-cli-darwin-arm64": "2.5.2",
27
- "swytchcode-cli-darwin-x64": "2.5.2",
28
- "swytchcode-cli-linux-arm64": "2.5.2",
29
- "swytchcode-cli-linux-x64": "2.5.2",
30
- "swytchcode-cli-win32-arm64": "2.5.2",
31
- "swytchcode-cli-win32-x64": "2.5.2"
26
+ "swytchcode-cli-darwin-arm64": "2.6.0",
27
+ "swytchcode-cli-darwin-x64": "2.6.0",
28
+ "swytchcode-cli-linux-arm64": "2.6.0",
29
+ "swytchcode-cli-linux-x64": "2.6.0",
30
+ "swytchcode-cli-win32-arm64": "2.6.0",
31
+ "swytchcode-cli-win32-x64": "2.6.0"
32
32
  }
33
33
  }