@papercraneai/cli 1.9.0-beta.0 → 1.9.0-beta.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.
Files changed (2) hide show
  1. package/lib/dev-server.js +50 -59
  2. package/package.json +1 -1
package/lib/dev-server.js CHANGED
@@ -378,6 +378,9 @@ export async function startDevServer(workspaceDir, port) {
378
378
 
379
379
  const projectDir = workspaceDir;
380
380
 
381
+ // Set the port so authFetch('local.*') knows where to reach the dev server
382
+ process.env.PAPERCRANE_LOCAL_PORT = String(port);
383
+
381
384
  const nextApp = next({
382
385
  dev: true,
383
386
  dir: projectDir,
@@ -394,16 +397,44 @@ export async function startDevServer(workspaceDir, port) {
394
397
  // ---- Local handler routes ----
395
398
  server.use(express.json());
396
399
 
397
- // POST /function/local.* execute a local handler
398
- server.post('/function/local.:rest(*)', async (req, res) => {
400
+ // Local handler routes — match /function/local or /function/local.*
401
+ // Uses a middleware pattern since Express 5 path-to-regexp doesn't support .:param(*)
402
+ server.use('/function', async (req, res, next) => {
403
+ // Only handle paths starting with /local
404
+ if (!req.path.startsWith('/local')) return next();
405
+
406
+ const fullPath = req.path.slice(1); // remove leading /
407
+ const segments = fullPath.split('.'); // ['local', 'handler', 'method', ...]
408
+
409
+ // GET /function/local — list all local handlers
410
+ if (segments.length === 1 && req.method === 'GET') {
411
+ try {
412
+ const { loadHandlers, clearHandlerCache } = await import('./handler-loader.js');
413
+ clearHandlerCache(projectDir);
414
+ const handlers = loadHandlers(projectDir);
415
+ const items = [];
416
+ for (const [name, node] of handlers) {
417
+ items.push({
418
+ path: `local.${name}`,
419
+ description: node.description,
420
+ isGroup: !!node.next,
421
+ });
422
+ }
423
+ return res.json({ items });
424
+ } catch (err) {
425
+ return res.status(500).json({ error: err.message });
426
+ }
427
+ }
428
+
429
+ if (segments.length < 2) return next();
430
+
431
+ const handlerName = segments[1];
432
+ const methodPath = segments.slice(2);
433
+
399
434
  try {
400
435
  const { resolve } = await import('./resolver.js');
401
436
  const { loadHandler, clearHandlerCache } = await import('./handler-loader.js');
402
437
 
403
- const segments = req.params.rest.split('.');
404
- const handlerName = segments[0];
405
- const methodPath = segments.slice(1);
406
-
407
438
  // Clear cache on each request during dev for hot-reload
408
439
  clearHandlerCache(projectDir);
409
440
 
@@ -413,45 +444,25 @@ export async function startDevServer(workspaceDir, port) {
413
444
  }
414
445
 
415
446
  const ctx = { credentials: {}, pathParams: {}, cleanup: [] };
416
- const params = req.body?.params || req.body || {};
417
-
418
- const result = await resolve(node, methodPath, ctx, params, 'POST');
419
-
420
- // Run cleanup functions
421
- for (const fn of ctx.cleanup || []) {
422
- try { await fn(); } catch {}
423
- }
424
-
425
- if (!result.ok) {
426
- const response = { error: result.error };
427
- if (result.schema) response.schema = result.schema;
428
- return res.status(result.status || 500).json(response);
429
- }
430
-
431
- return res.json({ result: result.result });
432
- } catch (err) {
433
- return res.status(500).json({ error: err.message });
434
- }
435
- });
436
447
 
437
- // GET /function/local.* describe a local handler
438
- server.get('/function/local.:rest(*)', async (req, res) => {
439
- try {
440
- const { resolve } = await import('./resolver.js');
441
- const { loadHandler, clearHandlerCache } = await import('./handler-loader.js');
448
+ if (req.method === 'POST') {
449
+ const params = req.body?.params || req.body || {};
450
+ const result = await resolve(node, methodPath, ctx, params, 'POST');
442
451
 
443
- const segments = req.params.rest.split('.');
444
- const handlerName = segments[0];
445
- const methodPath = segments.slice(1);
452
+ for (const fn of ctx.cleanup || []) {
453
+ try { await fn(); } catch {}
454
+ }
446
455
 
447
- clearHandlerCache(projectDir);
456
+ if (!result.ok) {
457
+ const response = { error: result.error };
458
+ if (result.schema) response.schema = result.schema;
459
+ return res.status(result.status || 500).json(response);
460
+ }
448
461
 
449
- const node = loadHandler(projectDir, handlerName);
450
- if (!node) {
451
- return res.status(404).json({ error: `Local handler not found: ${handlerName}` });
462
+ return res.json({ result: result.result });
452
463
  }
453
464
 
454
- const ctx = { credentials: {}, pathParams: {}, cleanup: [] };
465
+ // GET describe
455
466
  const result = await resolve(node, methodPath, ctx, {}, 'GET');
456
467
 
457
468
  for (const fn of ctx.cleanup || []) {
@@ -468,26 +479,6 @@ export async function startDevServer(workspaceDir, port) {
468
479
  }
469
480
  });
470
481
 
471
- // GET /function/local — list all local handlers
472
- server.get('/function/local', async (req, res) => {
473
- try {
474
- const { loadHandlers, clearHandlerCache } = await import('./handler-loader.js');
475
- clearHandlerCache(projectDir);
476
- const handlers = loadHandlers(projectDir);
477
- const items = [];
478
- for (const [name, node] of handlers) {
479
- items.push({
480
- path: `local.${name}`,
481
- description: node.description,
482
- isGroup: !!node.next,
483
- });
484
- }
485
- return res.json({ items });
486
- } catch (err) {
487
- return res.status(500).json({ error: err.message });
488
- }
489
- });
490
-
491
482
  // Everything else -> Next.js
492
483
  server.all('/{*path}', (req, res) => handle(req, res));
493
484
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papercraneai/cli",
3
- "version": "1.9.0-beta.0",
3
+ "version": "1.9.0-beta.2",
4
4
  "description": "CLI tool for managing OAuth credentials for LLM integrations",
5
5
  "main": "index.js",
6
6
  "type": "module",