@browserbasehq/sdk-functions 0.0.1

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 ADDED
File without changes
package/dist/cli.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import d from 'chalk';
3
+ import * as j from 'fs';
4
+ import { existsSync, readdirSync, readFileSync } from 'fs';
5
+ import * as O from 'path';
6
+ import { join } from 'path';
7
+ import 'dotenv/config';
8
+ import Se from 'archiver';
9
+ import { Command } from 'commander';
10
+ import { createServer } from 'http';
11
+ import { randomUUID } from 'crypto';
12
+ import ge from '@browserbasehq/sdk';
13
+ import b, { z } from 'zod';
14
+ import { spawn } from 'child_process';
15
+
16
+ var H=Object.defineProperty;var ue=(o,e,n)=>e in o?H(o,e,{enumerable:true,configurable:true,writable:true,value:n}):o[e]=n;var B=(o,e)=>()=>(o&&(e=o(o=0)),e);var de=(o,e)=>{for(var n in e)H(o,n,{get:e[n],enumerable:true});};var l=(o,e,n)=>ue(o,typeof e!="symbol"?e+"":e,n);function Z(o){let e=process.env.BB_API_KEY;e||(console.error(d.red("Error: BB_API_KEY not found in environment variables.")),console.log(d.gray("Please set BB_API_KEY in your .env file or environment.")),process.exit(1));let n=process.env.BB_PROJECT_ID;n||(console.error(d.red("Error: BB_PROJECT_ID not found in environment variables.")),console.log(d.gray("Please set BB_PROJECT_ID in your .env file or environment.")),process.exit(1));let r=o.apiUrl||process.env.BB_API_URL||"https://api.browserbase.com",t=o.entrypoint||"main.ts",s=O.resolve(t);j.existsSync(s)||(console.error(d.red(`Error: Entrypoint file not found: ${s}`)),process.exit(1));let i=O.extname(t).toLowerCase();return [".ts",".js",".mjs",".mts"].includes(i)||(console.error(d.red(`Error: Invalid entrypoint extension: ${i}. Must be .ts, .js, .mjs, or .mts`)),process.exit(1)),{apiKey:e,projectId:n,apiUrl:r,entrypoint:t,workingDirectory:process.cwd()}}function Q(o){o.apiKey.startsWith("bb_")||console.warn(d.yellow("Warning: API key doesn't start with 'bb_'. Make sure you're using a valid Browserbase API key."));}var X=B(()=>{});function Re(o){let e=O.join(o,".gitignore"),n=["node_modules/**",".git/**",".env",".env.*","*.log",".DS_Store","dist/**","build/**","*.zip","*.tar","*.tar.gz",".vscode/**",".idea/**"];if(!j.existsSync(e))return n;try{let t=j.readFileSync(e,"utf-8").split(`
17
+ `).map(s=>s.trim()).filter(s=>s&&!s.startsWith("#")).map(s=>s.endsWith("/")?`${s}**`:s);return [...n,...t]}catch(r){return console.warn(d.yellow(r,"Warning: Could not read .gitignore file, using defaults")),n}}async function ee(o,e){return new Promise((n,r)=>{console.log(d.cyan("Creating archive..."));let t=Se("tar",{gzip:true,gzipOptions:{level:9}}),s=[],i=0;t.on("data",a=>{s.push(a);}),t.on("entry",a=>{if(!a.stats?.isDirectory()&&(i++,e?.dryRun)){let u=O.relative(o,a.name);console.log(d.gray(` + ${u}`));}}),t.on("end",()=>{let a=Buffer.concat(s),u=(a.length/(1024*1024)).toFixed(2);console.log(d.green(`\u2713 Archive created: ${i} files, ${u} MB`)),n({buffer:a,size:a.length,fileCount:i});}),t.on("error",a=>{console.error(d.red(`Archive error: ${a.message}`)),r(a);}),t.on("warning",a=>{a.code==="ENOENT"?console.warn(d.yellow(`Warning: ${a.message}`)):r(a);});let c=Re(o);e?.dryRun&&(console.log(d.gray(`
18
+ Ignoring patterns:`)),c.forEach(a=>{console.log(d.gray(` - ${a}`));}),console.log(d.gray(`
19
+ Including files:`))),t.glob("**/*",{cwd:o,ignore:c,dot:true,follow:false}),t.finalize();})}function ne(o,e=50){let n=o/1048576;n>e&&(console.error(d.red(`Error: Archive size (${n.toFixed(2)} MB) exceeds maximum allowed size (${e} MB)`)),console.log(d.gray("Consider adding more patterns to .gitignore to reduce archive size")),process.exit(1));}var oe=B(()=>{});async function re(o,e,n){if(n?.dryRun)return console.log(d.cyan(`
20
+ [Dry run] Would upload to:`)),console.log(d.gray(` URL: ${o.apiUrl}/v1/functions/builds`)),console.log(d.gray(` Project ID: ${o.projectId}`)),console.log(d.gray(` Entrypoint: ${o.entrypoint}`)),console.log(d.gray(` Archive size: ${(e.length/(1024*1024)).toFixed(2)} MB`)),{success:true,message:"Dry run completed successfully"};console.log(d.cyan(`
21
+ Uploading build...`));try{let r=new FormData,t={entrypoint:o.entrypoint,projectId:o.projectId};r.append("metadata",JSON.stringify(t));let s=new Blob([e],{type:"application/gzip"});r.append("archive",s,"archive.tar.gz");let i=`${o.apiUrl}/v1/functions/builds`;console.log(d.gray(`Uploading to: ${i}`));let c=await fetch(i,{method:"POST",headers:{"x-bb-api-key":o.apiKey},body:r});if(!c.ok){let u=`HTTP ${c.status}: ${c.statusText}`;try{let p=await c.json();if(typeof p=="object"&&p!==null&&("message"in p||"error"in p)){let f=p;u=f.message||f.error||u;}}catch{try{let p=await c.text();p&&(u=p);}catch{}}return console.error(d.red(`Upload failed: ${u}`)),{success:!1,message:u}}let a={};try{let u=await c.json();typeof u=="object"&&u!==null&&(a=u);}catch{}return a.id?(console.log(d.green("\u2713 Build uploaded successfully")),console.log(d.gray(`Build ID: ${a.id}`)),{success:!0,buildId:a.id,message:"Build uploaded successfully"}):(console.error(d.red("Upload failed: No build ID received in response")),{success:!1,message:"No build ID received in response"})}catch(r){let t=r instanceof Error?r.message:"Unknown error occurred";return console.error(d.red(`Upload error: ${t}`)),r&&typeof r=="object"&&"code"in r&&r.code==="ECONNREFUSED"&&console.log(d.yellow(`
22
+ Cannot connect to ${o.apiUrl}. Make sure the API server is running.`)),{success:false,message:t}}}async function xe(o,e){try{let n=`${o.apiUrl}/v1/functions/builds/${e}`,r=await fetch(n,{method:"GET",headers:{"x-bb-api-key":o.apiKey}});return r.ok?await r.json():(console.error(d.red(`Failed to get build status: HTTP ${r.status}`)),null)}catch(n){return console.error(d.red(`Error fetching build status: ${n instanceof Error?n.message:"Unknown error"}`)),null}}async function te(o,e,n){let r=2e3,t=60;console.log(d.cyan(`
23
+ Waiting for build to complete...`));for(let s=0;s<t;s++){let i=await xe(o,e);if(!i)return console.error(d.red("Failed to get build status")),null;if(process.stdout.write(`\r${d.gray(`Status: ${i.status}... (${s+1}/${t})`)}`),i.status!=="RUNNING")return process.stdout.write("\r"+" ".repeat(50)+"\r"),i.status==="COMPLETED"?console.log(d.green("\u2713 Build completed successfully")):i.status==="FAILED"&&console.error(d.red("\u2717 Build failed")),i;await new Promise(c=>setTimeout(c,r));}return process.stdout.write("\r"+" ".repeat(50)+"\r"),console.error(d.yellow("Build is still running after maximum wait time")),null}var se=B(()=>{});var ie={};de(ie,{publishFunction:()=>Ce});async function Ce(o){console.log(d.bold.cyan(`
24
+ Browserbase Functions - Publish
25
+ `));try{let e={};o.entrypoint!==void 0&&(e.entrypoint=o.entrypoint),o.apiUrl!==void 0&&(e.apiUrl=o.apiUrl);let n=Z(e);Q(n),console.log(d.gray(`Working directory: ${n.workingDirectory}`)),console.log(d.gray(`Entrypoint: ${n.entrypoint}`)),console.log(d.gray(`API URL: ${n.apiUrl}`)),console.log(d.gray(`Project ID: ${n.projectId}`)),o.dryRun&&console.log(d.yellow(`
26
+ [Dry run mode - no files will be uploaded]
27
+ `));let r={};o.dryRun!==void 0&&(r.dryRun=o.dryRun);let t=await ee(n.workingDirectory,r);ne(t.size);let s={};o.dryRun!==void 0&&(s.dryRun=o.dryRun);let i=await re(n,t.buffer,s);if(i.success||(console.error(d.red(`
28
+ \u2717 Publish failed`)),process.exit(1)),o.dryRun)console.log(d.bold.green(`
29
+ \u2713 Dry run completed successfully!`)),console.log(d.cyan(`
30
+ Your function would have been published. Run without --dry-run to publish.`));else if(console.log(d.bold.green(`
31
+ \u2713 Function uploaded successfully!`)),i.buildId){console.log(d.gray(`
32
+ Build ID: ${i.buildId}`));let c=await te(n,i.buildId);c?.status==="COMPLETED"?console.log(d.bold.green(`
33
+ \u{1F389} Your function has been deployed and is ready for invocation!`)):c?.status==="FAILED"?(console.error(d.red(`
34
+ \u2717 Build failed during processing`)),process.exit(1)):console.log(d.yellow(`
35
+ Build status could not be determined. Check the dashboard for updates.`));}else console.log(d.cyan(`
36
+ Your function will be available for invocation once the build is processed.`));}catch(e){console.error(d.red(`
37
+ \u2717 Publish failed: ${e.message??"unknown error"}`)),process.exit(1);}}var ae=B(()=>{X();oe();se();});var k=class{constructor(e=false){l(this,"nextConnection",null);l(this,"invokeConnection",null);l(this,"currentRequestId",null);l(this,"currentFunctionName",null);l(this,"currentSessionId",null);l(this,"sessionCleanupCallback",null);l(this,"verbose");l(this,"runtimeConnectedOnce",false);this.verbose=e;}setSessionCleanupCallback(e){this.sessionCleanupCallback=e;}holdNextConnection(e){this.nextConnection&&(this.nextConnection.response.writeHead(503,{"Content-Type":"application/json"}),this.nextConnection.response.end(JSON.stringify({error:"Another runtime connected"}))),this.nextConnection={response:e,timestamp:Date.now()},this.runtimeConnectedOnce=true,this.verbose&&console.log(d.cyan("\u{1F50C} Function runtime connected, ready for invocations"));}triggerInvocation(e,n,r,t){if(!this.nextConnection)return this.verbose&&console.log(d.yellow("\u26A0\uFE0F No runtime connected to handle invocation")),false;if(this.invokeConnection)return this.verbose&&console.log(d.yellow("\u26A0\uFE0F Another invocation is already in progress")),false;let s=randomUUID();this.currentRequestId=s,this.currentFunctionName=e,this.currentSessionId=r.session.id,this.invokeConnection={response:t,timestamp:Date.now()};let i={functionName:e,params:n,context:r};return this.nextConnection.response.writeHead(200,{"Content-Type":"application/json","Lambda-Runtime-Aws-Request-Id":s,"Lambda-Runtime-Deadline-Ms":String(Date.now()+3e5),"Lambda-Runtime-Invoked-Function-Arn":`arn:aws:lambda:us-east-1:000000000000:function:${e}`}),this.nextConnection.response.end(JSON.stringify(i)),this.nextConnection=null,console.log(d.blue(`\u{1F680} Invoking function '${e}' (request-id: ${s})`)),true}completeWithSuccess(e,n){return e!==this.currentRequestId?(this.verbose&&console.log(d.yellow(`\u26A0\uFE0F Request ID mismatch: expected ${this.currentRequestId}, got ${e}`)),false):this.invokeConnection?(this.invokeConnection.response.writeHead(200,{"Content-Type":"application/json"}),this.invokeConnection.response.end(JSON.stringify(n??{})),console.log(d.green(`\u2713 Function '${this.currentFunctionName}' completed successfully`)),this.sessionCleanupCallback&&this.currentSessionId&&this.sessionCleanupCallback(this.currentSessionId).catch(r=>{console.error(d.red("Failed to cleanup session:"),r);}),this.invokeConnection=null,this.currentRequestId=null,this.currentFunctionName=null,this.currentSessionId=null,true):(this.verbose&&console.log(d.yellow("\u26A0\uFE0F No active invocation to complete")),false)}completeWithError(e,n){return e!==this.currentRequestId?(this.verbose&&console.log(d.yellow(`\u26A0\uFE0F Request ID mismatch: expected ${this.currentRequestId}, got ${e}`)),false):this.invokeConnection?(this.invokeConnection.response.writeHead(500,{"Content-Type":"application/json"}),this.invokeConnection.response.end(JSON.stringify({error:{message:n.errorMessage,type:n.errorType,stackTrace:n.stackTrace}})),console.log(d.red(`\u2717 Function '${this.currentFunctionName}' failed: ${n.errorMessage}`)),this.sessionCleanupCallback&&this.currentSessionId&&this.sessionCleanupCallback(this.currentSessionId).catch(r=>{console.error(d.red("Failed to cleanup session:"),r);}),this.invokeConnection=null,this.currentRequestId=null,this.currentFunctionName=null,this.currentSessionId=null,true):(this.verbose&&console.log(d.yellow("\u26A0\uFE0F No active invocation to complete")),false)}isReady(){return this.nextConnection!==null&&this.invokeConnection===null}hasActiveInvocation(){return this.invokeConnection!==null}getCurrentRequestId(){return this.currentRequestId}isRuntimeConnected(){return this.runtimeConnectedOnce&&this.nextConnection!==null}};var M=class{constructor(){l(this,"browserbaseClient",null);l(this,"projectId");l(this,"apiKey");l(this,"initialized",false);let e=process.env.BB_PROJECT_ID,n=process.env.BB_API_KEY;if(!e||!n)throw console.error(d.red(`\u2717 Browserbase credentials not found.
38
+ `)+d.red(` Please set BB_PROJECT_ID and BB_API_KEY in your .env file.
39
+ `)+d.gray(" Copy .env.example to .env and fill in your credentials.")),new Error("Missing Browserbase credentials");this.projectId=e,this.apiKey=n;}async initialize(){this.initialized||(this.browserbaseClient=new ge({apiKey:this.apiKey}),this.initialized=true,console.log(d.green("\u2713 Browserbase client initialized")));}async createSession(e){if(!this.browserbaseClient)throw new Error("Browser manager not initialized");console.log(d.cyan("Creating browser session..."));let n=await this.browserbaseClient.sessions.create({projectId:this.projectId,...e}),r={id:n.id,connectUrl:n.connectUrl};return console.log(d.green(`\u2713 Browser session created: ${r.id}`)),r}async closeSession(e){if(!this.browserbaseClient)throw new Error("Browser manager not initialized");try{console.log(d.cyan(`Closing browser session: ${e}...`)),await this.browserbaseClient.sessions.update(e,{projectId:this.projectId,status:"REQUEST_RELEASE"}),console.log(d.green(`\u2713 Browser session closed: ${e}`));}catch(n){console.warn(d.yellow(`\u26A0\uFE0F Could not close session ${e}:`),n instanceof Error?n.message:String(n));}}getProjectId(){return this.projectId}isInitialized(){return this.initialized}};var N=class{constructor(e){l(this,"manifests",new Map);l(this,"manifestsPath");this.manifestsPath=e||join(process.cwd(),".browserbase","functions","manifests");}loadManifests(){if(!existsSync(this.manifestsPath)){console.log(d.yellow(`\u26A0\uFE0F No ${this.manifestsPath} directory found`)),console.log(d.gray(" Run your entrypoint file first to generate manifests"));return}try{let n=readdirSync(this.manifestsPath).filter(r=>r.endsWith(".json"));for(let r of n){let t=join(this.manifestsPath,r),s=readFileSync(t,"utf-8"),i=JSON.parse(s);this.manifests.set(i.name,i),console.log(d.gray(` Loaded manifest for function: ${i.name}`));}this.manifests.size>0?console.log(d.green(`\u2713 Loaded ${this.manifests.size} function manifest(s)`)):console.log(d.yellow("\u26A0\uFE0F No function manifests found in .browserbase directory"));}catch(e){console.error(d.red("Failed to load function manifests:"),e);}}getManifest(e){return this.manifests.get(e)}getSize(){return this.manifests.size}hasManifest(e){return this.manifests.has(e)}getManifestNames(){return Array.from(this.manifests.keys())}};var $={async parseJsonBody(o){return new Promise((e,n)=>{let r="";o.on("data",t=>{r+=t.toString();}),o.on("end",()=>{try{let t=r?JSON.parse(r):{};e(t);}catch(t){n(new Error("Invalid JSON body",{cause:t}));}}),o.on("error",n);})},async parseAndValidate(o,e){let n=await this.parseJsonBody(o);return e.parse(n)}};var h={sendJson(o,e,n){o.writeHead(e,{"Content-Type":"application/json"}),o.end(JSON.stringify(n));},sendSuccess(o,e,n=200){let r={status:"success",...e!==void 0&&{data:e}};this.sendJson(o,n,r);},sendError(o,e,n=500,r,t){let s={error:e};r&&(s.message=r),t&&(s.details=t),this.sendJson(o,n,s);},sendBadRequest(o,e,n){this.sendError(o,"Bad Request",400,e,n);},sendNotFound(o,e){this.sendError(o,"Not Found",404,e);},sendInternalError(o,e="An internal error occurred",n){this.sendError(o,"Internal Server Error",500,e,n);},sendServiceUnavailable(o,e){this.sendError(o,"Service Unavailable",503,e);},sendAccepted(o,e){let n=e||{status:"accepted"};this.sendJson(o,202,n);}};var ve=b.object({id:b.string(),connectUrl:b.string()}),F=b.object({session:ve});var ye=b.object({functionName:b.string().min(1),params:b.looseObject({}),context:F});b.object({requestId:b.string().min(1),event:ye});var W=b.object({errorMessage:b.string().min(1),errorType:b.string().min(1),stackTrace:b.array(b.string().min(1))});var A=class{constructor(e){l(this,"bridge");l(this,"browserManager");l(this,"manifestStore");this.bridge=e.bridge,this.browserManager=e.browserManager,this.manifestStore=e.manifestStore,this.bridge.setSessionCleanupCallback(async n=>{await this.cleanupSession(n);});}async handleInvocationNext(e,n){this.bridge.holdNextConnection(n);}async handleFunctionInvoke(e,n,r){try{let t=z.object({functionName:z.string().optional(),params:z.unknown().default({}),context:F.optional()}),s=await $.parseAndValidate(e,t),i=r||s.functionName;if(!i){h.sendBadRequest(n,"Function name is required");return}let c=this.manifestStore.getManifest(i);if(!c){console.error(d.red(`\u2717 Function "${i}" not found in registry`)),console.error(d.gray(" Make sure the function is defined in your entrypoint file")),h.sendNotFound(n,`Function "${i}" not found in registry. Make sure it is defined with defineFn() in your entrypoint file.`);return}let a;try{console.log(d.cyan(`Creating browser session for ${i}...`));let f=c?.config?.sessionConfig||{};a=await this.browserManager.createSession(f);}catch(f){console.error(d.red("Failed to create browser session:"),f),h.sendInternalError(n,"Failed to create browser session",f instanceof Error?f.message:String(f));return}let u=s.context||{invocation:{id:crypto.randomUUID(),region:"local"},session:a};if(u.session=a,!this.bridge.triggerInvocation(i,s.params,u,n)){await this.cleanupSession(a.id),h.sendServiceUnavailable(n,this.bridge.hasActiveInvocation()?"Another invocation is in progress":"No runtime connected");return}}catch(t){t instanceof z.ZodError?h.sendBadRequest(n,"Invalid request body",t):(console.error(d.red("Error handling invoke:"),t),h.sendInternalError(n));}}async handleInvocationResponse(e,n,r){try{let t=await $.parseJsonBody(e);if(!this.bridge.completeWithSuccess(r,t)){h.sendBadRequest(n,"No matching invocation or request ID mismatch");return}h.sendAccepted(n);}catch(t){console.error(d.red("Error handling response:"),t),h.sendInternalError(n);}}async handleInvocationError(e,n,r){try{let t=await $.parseAndValidate(e,W);if(!this.bridge.completeWithError(r,t)){h.sendBadRequest(n,"No matching invocation or request ID mismatch");return}h.sendAccepted(n);}catch(t){t instanceof z.ZodError?h.sendBadRequest(n,"Invalid error format",t):(console.error(d.red("Error handling error report:"),t),h.sendInternalError(n));}}async cleanupSession(e){try{await this.browserManager.closeSession(e);}catch(n){console.error(d.red(`Failed to cleanup session ${e}:`),n);}}};async function we(o,e,n){let{handlers:r}=n,t=new URL(o.url||"",`http://${o.headers.host}`),s=o.method||"GET",i=t.pathname;if(console.log(d.gray(`[${s}] ${i}`)),e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"),s==="OPTIONS"){e.writeHead(200),e.end();return}try{if(s==="GET"&&i==="/"){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!0}));return}if(s==="GET"&&i==="/2018-06-01/runtime/invocation/next"){await r.handleInvocationNext(o,e);return}let c=i.match(/^\/v1\/functions\/([^/]+)\/invoke$/);if(s==="POST"&&c&&c[1]){let p=c[1];await r.handleFunctionInvoke(o,e,p);return}let a=i.match(/^\/2018-06-01\/runtime\/invocation\/([^/]+)\/response$/);if(s==="POST"&&a&&a[1]){let p=a[1];await r.handleInvocationResponse(o,e,p);return}let u=i.match(/^\/2018-06-01\/runtime\/invocation\/([^/]+)\/error$/);if(s==="POST"&&u&&u[1]){let p=u[1];await r.handleInvocationError(o,e,p);return}e.writeHead(404,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"Not found"}));}catch(c){console.error(d.red("Server error:"),c),e.writeHead(500,{"Content-Type":"application/json"}),e.end(JSON.stringify({error:"Internal server error"}));}}async function G(o){let{port:e,host:n,handlers:s}=o,i=createServer(async(c,a)=>{await we(c,a,{handlers:s});});return new Promise((c,a)=>{i.listen(e,n,()=>{c(i);}),i.on("error",u=>{u.code==="EADDRINUSE"?a(new Error(`Port ${e} is already in use`)):u.code==="EACCES"?a(new Error(`Permission denied to bind to port ${e}`)):a(u);});})}var D=class{constructor(e){l(this,"process",null);l(this,"entrypoint");l(this,"runtimeApiUrl");l(this,"verbose");l(this,"isShuttingDown",false);this.entrypoint=e.entrypoint,this.runtimeApiUrl=e.runtimeApiUrl,this.verbose=e.verbose;}async start(){if(this.process)throw new Error("Process is already running");if(this.verbose&&(console.log(d.gray("Starting runtime process...")),console.log(d.gray(` Command: tsx watch --clear-screen=false ${this.entrypoint}`)),console.log(d.gray(` Working directory: ${process.cwd()}`)),console.log(d.gray(` Runtime API: ${this.runtimeApiUrl}`))),this.process=spawn("tsx",["watch","--clear-screen=false",this.entrypoint],{cwd:process.cwd(),env:{...process.env,AWS_LAMBDA_RUNTIME_API:this.runtimeApiUrl,BB_FUNCTIONS_PHASE:"runtime",NODE_ENV:"local"},stdio:["ignore","pipe","pipe"]}),this.process.stdout?.on("data",e=>{e.toString().trim().split(`
40
+ `).forEach(r=>{r.trim()&&console.log(d.blue("[Runtime]"),r);});}),this.process.stderr?.on("data",e=>{e.toString().trim().split(`
41
+ `).forEach(r=>{r.trim()&&(r.includes("Watching for file changes")?console.log(d.green("\u2713 Runtime watching for file changes")):r.includes("Restarting")?console.log(d.yellow("\u21BB Runtime restarting due to file change...")):console.error(d.red("[Runtime Error]"),r));});}),this.process.on("exit",(e,n)=>{this.isShuttingDown||(e!==0?(console.error(d.red(`\u2717 Runtime process exited unexpectedly with code ${e}`)),n&&console.error(d.red(` Signal: ${n}`))):console.log(d.gray("Runtime process exited")),this.process=null);}),this.process.on("error",e=>{e.code==="ENOENT"?console.error(d.red("\u2717 Failed to start runtime: tsx not found"),d.yellow(`
42
+ Make sure tsx is installed: npm install -g tsx or pnpm add tsx`)):console.error(d.red("\u2717 Failed to start runtime process:"),e),this.process=null;}),await new Promise(e=>setTimeout(e,100)),!this.process||this.process.exitCode!==null)throw new Error("Failed to start runtime process");console.log(d.green("\u2713 Runtime process started"));}async stop(){if(this.process)return this.isShuttingDown=true,this.verbose&&console.log(d.gray("Stopping runtime process...")),new Promise(e=>{if(!this.process){e();return}let n=setTimeout(()=>{this.process&&(console.log(d.yellow("\u26A0\uFE0F Force killing runtime process")),this.process.kill("SIGKILL"));},5e3);this.process.on("exit",()=>{clearTimeout(n),this.process=null,console.log(d.green("\u2713 Runtime process stopped")),e();}),this.process.kill("SIGTERM");})}isRunning(){return this.process!==null&&this.process.exitCode===null}};async function V(o){let{entrypoint:e,port:n,host:r,verbose:t}=o;process.env.NODE_ENV==="production"&&console.warn(d.yellow("\u26A0\uFE0F Warning: Running dev server in production mode. This is not recommended."));let s=`${r}:${n}`;t&&console.log(d.gray(`Runtime API URL: ${s}`));let i=new k(t),c=new M;await c.initialize();let a=new N;a.loadManifests();let u=new A({bridge:i,browserManager:c,manifestStore:a}),p=new D({entrypoint:e,runtimeApiUrl:s,verbose:t}),f=null;try{f=await G({port:n,host:r,bridge:i,browserManager:c,handlers:u}),console.log(d.green(`\u2713 Development server listening on http://${r}:${n}`)),console.log(d.cyan("Starting runtime process...")),await p.start();let E=1e4,ce=200,le=Date.now(),_=!1;for(;Date.now()-le<E;){if(i.isRuntimeConnected()){_=!0,console.log(d.green("\u2713 Runtime connected and ready")),a.loadManifests();break}await new Promise(z=>setTimeout(z,ce));}_||(console.log(d.yellow("\u26A0\uFE0F Runtime is taking longer than expected to connect...")),a.loadManifests());let J=async()=>(console.log(d.cyan(`
43
+ \u{1F4E6} Shutting down...`)),await p.stop(),new Promise(z=>{f?.close(()=>{console.log(d.green("\u2713 Server closed")),z();});}));process.on("SIGINT",async()=>{await J(),process.exit(0);}),process.on("SIGTERM",async()=>{await J(),process.exit(0);});}catch(E){throw console.error(d.red("Failed to start:"),E),p.isRunning()&&await p.stop(),f&&f.close(),E}}var q=new Command;q.name("bb").description("Browserbase Functions CLI").version("0.0.1");q.command("dev").description("Start a local development server for testing Browserbase Functions").argument("<entrypoint>","Path to the TypeScript/JavaScript file that imports all your functions").option("-p, --port <number>","Port to listen on","14113").option("-h, --host <string>","Host to bind to","127.0.0.1").action(async(o,e)=>{try{let n=await import('fs'),r=await import('path'),t=r.resolve(o);n.existsSync(t)||(console.error(d.red(`Error: Entrypoint file not found: ${t}`)),process.exit(1));let s=r.extname(t);[".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(s)||(console.error(d.red("Error: Invalid file extension. Expected .ts, .tsx, .js, .jsx, .mjs, or .cjs")),process.exit(1));let i=parseInt(e.port,10);(isNaN(i)||i<1||i>65535)&&(console.error(d.red("Error: Invalid port number. Must be between 1 and 65535.")),process.exit(1)),console.log(d.cyan("Starting Browserbase Functions development server...")),console.log(d.gray(`Entrypoint: ${t}`)),await V({entrypoint:t,port:i,host:e.host,verbose:e.verbose});}catch(n){console.error(d.red("Failed to start development server:"),n),process.exit(1);}});q.command("publish").description("Publish your Browserbase Function to the cloud").argument("<entrypoint>","Path to the TypeScript/JavaScript file that imports all your functions").option("-u, --api-url <url>","API endpoint URL").option("--dry-run","Show what would be published without uploading").action(async(o,e)=>{try{let{publishFunction:n}=await Promise.resolve().then(()=>(ae(),ie));await n({entrypoint:o,apiUrl:e.apiUrl,dryRun:e.dryRun});}catch(n){console.error(d.red("Publish failed:"),n),process.exit(1);}});q.parse();
44
+ //# sourceMappingURL=cli.js.map
45
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/publish/config.ts","../src/cli/publish/archiver.ts","../src/cli/publish/api-client.ts","../src/cli/publish/index.ts","../src/cli/dev/bridge.ts","../src/cli/dev/browser-manager.ts","../src/cli/dev/handlers/manifest-store.ts","../src/cli/dev/handlers/request-parser.ts","../src/cli/dev/handlers/response-builder.ts","../src/schemas/invocation.ts","../src/schemas/events.ts","../src/cli/dev/handlers/index.ts","../src/cli/dev/server.ts","../src/cli/dev/process.ts","../src/cli/dev/index.ts","../src/cli/main.ts"],"names":["loadConfig","options","apiKey","chalk","projectId","apiUrl","entrypoint","entrypointPath","Y","ext","validateConfig","config","init_config","__esmMin","loadGitignorePatterns","workingDirectory","gitignorePath","U","defaultPatterns","patterns","line","pattern","error","createArchive","resolve","reject","archive","archiver","chunks","fileCount","chunk","entry","relativePath","buffer","sizeInMB","err","ignorePatterns","validateArchiveSize","size","maxSizeMB","init_archiver","uploadBuild","archiveBuffer","formData","metadata","blob","url","response","errorMessage","errorBody","typedErrorBody","textBody","responseData","jsonResponse","getBuildStatus","buildId","pollBuildStatus","intervalMs","maxAttempts","attempt","status","init_api_client","publish_exports","__export","publishFunction","configOptions","archiveOptions","uploadOptions","result","buildStatus","init_publish","InvocationBridge","verbose","__publicField","callback","functionName","params","context","invokeResponse","requestId","randomUUID","payload","RemoteBrowserManager","foundProjectId","foundApiKey","Browserbase","sessionConfig","createdSession","session","sessionId","ManifestStore","manifestsPath","join","existsSync","jsonFiles","readdirSync","f","file","filePath","content","readFileSync","manifest","requestParser","req","body","parsed","schema","responseBuilder","res","statusCode","data","message","details","FunctionInvocationContextSessionDetails","z","FunctionInvocationContext","RuntimeEventPayload","RuntimeError","DevServerHandlers","deps","_req","invokeSchema","validatedData","finalFunctionName","validatedError","handleRequest","handlers","method","path","invokeMatch","responseMatch","errorMatch","startServer","port","host","server","createServer","ProcessManager","spawn","code","signal","killTimeout","startDevServer","runtimeApiUrl","bridge","browserManager","manifestStore","processManager","maxWaitTime","pollInterval","startTime","runtimeConnected","shutdown","program","Command","fs"],"mappings":"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","file":"cli.js","sourcesContent":["import chalk from \"chalk\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport \"dotenv/config\";\n\nexport interface PublishConfig {\n apiKey: string;\n projectId: string;\n apiUrl: string;\n entrypoint: string;\n workingDirectory: string;\n}\n\nexport function loadConfig(options: {\n entrypoint?: string;\n apiUrl?: string;\n}): PublishConfig {\n // Get API key from environment\n const apiKey = process.env[\"BB_API_KEY\"];\n if (!apiKey) {\n console.error(\n chalk.red(\"Error: BB_API_KEY not found in environment variables.\"),\n );\n console.log(\n chalk.gray(\"Please set BB_API_KEY in your .env file or environment.\"),\n );\n process.exit(1);\n }\n\n // Get project ID from environment\n const projectId = process.env[\"BB_PROJECT_ID\"];\n if (!projectId) {\n console.error(\n chalk.red(\"Error: BB_PROJECT_ID not found in environment variables.\"),\n );\n console.log(\n chalk.gray(\"Please set BB_PROJECT_ID in your .env file or environment.\"),\n );\n process.exit(1);\n }\n\n // Use provided API URL or default\n const apiUrl =\n options.apiUrl ||\n process.env[\"BB_API_URL\"] ||\n \"https://api.browserbase.com\";\n\n // Use provided entrypoint or default to main.ts\n const entrypoint = options.entrypoint || \"main.ts\";\n\n // Validate entrypoint exists\n const entrypointPath = path.resolve(entrypoint);\n if (!fs.existsSync(entrypointPath)) {\n console.error(\n chalk.red(`Error: Entrypoint file not found: ${entrypointPath}`),\n );\n process.exit(1);\n }\n\n // Validate entrypoint has valid extension\n const ext = path.extname(entrypoint).toLowerCase();\n if (![\".ts\", \".js\", \".mjs\", \".mts\"].includes(ext)) {\n console.error(\n chalk.red(\n `Error: Invalid entrypoint extension: ${ext}. Must be .ts, .js, .mjs, or .mts`,\n ),\n );\n process.exit(1);\n }\n\n return {\n apiKey,\n projectId,\n apiUrl,\n entrypoint,\n workingDirectory: process.cwd(),\n };\n}\n\nexport function validateConfig(config: PublishConfig): void {\n // Additional validation if needed\n if (!config.apiKey.startsWith(\"bb_\")) {\n console.warn(\n chalk.yellow(\n \"Warning: API key doesn't start with 'bb_'. Make sure you're using a valid Browserbase API key.\",\n ),\n );\n }\n}\n","import archiver from \"archiver\";\nimport chalk from \"chalk\";\nimport * as path from \"node:path\";\nimport * as fs from \"node:fs\";\n\ninterface ArchiveResult {\n buffer: Buffer;\n size: number;\n fileCount: number;\n}\n\nfunction loadGitignorePatterns(workingDirectory: string): string[] {\n const gitignorePath = path.join(workingDirectory, \".gitignore\");\n const defaultPatterns = [\n \"node_modules/**\",\n \".git/**\",\n \".env\",\n \".env.*\",\n \"*.log\",\n \".DS_Store\",\n \"dist/**\",\n \"build/**\",\n \"*.zip\",\n \"*.tar\",\n \"*.tar.gz\",\n \".vscode/**\",\n \".idea/**\",\n ];\n\n if (!fs.existsSync(gitignorePath)) {\n return defaultPatterns;\n }\n\n try {\n const gitignoreContent = fs.readFileSync(gitignorePath, \"utf-8\");\n const patterns = gitignoreContent\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith(\"#\"))\n .map((pattern) => {\n // Convert gitignore patterns to glob patterns for archiver\n if (pattern.endsWith(\"/\")) {\n return `${pattern}**`;\n }\n return pattern;\n });\n\n return [...defaultPatterns, ...patterns];\n } catch (error: unknown) {\n console.warn(\n chalk.yellow(\n error,\n \"Warning: Could not read .gitignore file, using defaults\",\n ),\n );\n return defaultPatterns;\n }\n}\n\nexport async function createArchive(\n workingDirectory: string,\n options?: {\n dryRun?: boolean;\n },\n): Promise<ArchiveResult> {\n return new Promise((resolve, reject) => {\n console.log(chalk.cyan(\"Creating archive...\"));\n\n const archive = archiver(\"tar\", {\n gzip: true,\n gzipOptions: { level: 9 }, // Maximum compression\n });\n\n const chunks: Buffer[] = [];\n let fileCount = 0;\n\n // Collect archive data in memory\n archive.on(\"data\", (chunk) => {\n chunks.push(chunk);\n });\n\n // Track files being added\n archive.on(\"entry\", (entry) => {\n if (!entry.stats?.isDirectory()) {\n fileCount++;\n if (options?.dryRun) {\n const relativePath = path.relative(workingDirectory, entry.name);\n console.log(chalk.gray(` + ${relativePath}`));\n }\n }\n });\n\n archive.on(\"end\", () => {\n const buffer = Buffer.concat(chunks);\n const sizeInMB = (buffer.length / (1024 * 1024)).toFixed(2);\n\n console.log(\n chalk.green(`✓ Archive created: ${fileCount} files, ${sizeInMB} MB`),\n );\n\n resolve({\n buffer,\n size: buffer.length,\n fileCount,\n });\n });\n\n archive.on(\"error\", (err) => {\n console.error(chalk.red(`Archive error: ${err.message}`));\n reject(err);\n });\n\n archive.on(\"warning\", (err) => {\n if (err.code === \"ENOENT\") {\n console.warn(chalk.yellow(`Warning: ${err.message}`));\n } else {\n reject(err);\n }\n });\n\n // Get ignore patterns\n const ignorePatterns = loadGitignorePatterns(workingDirectory);\n\n if (options?.dryRun) {\n console.log(chalk.gray(\"\\nIgnoring patterns:\"));\n ignorePatterns.forEach((pattern) => {\n console.log(chalk.gray(` - ${pattern}`));\n });\n console.log(chalk.gray(\"\\nIncluding files:\"));\n }\n\n // Add directory contents with ignore patterns\n archive.glob(\"**/*\", {\n cwd: workingDirectory,\n ignore: ignorePatterns,\n dot: true, // Include dotfiles (except those in ignore patterns)\n follow: false, // Don't follow symlinks\n });\n\n // Finalize the archive\n archive.finalize();\n });\n}\n\nexport function validateArchiveSize(\n size: number,\n maxSizeMB: number = 50,\n): void {\n const sizeInMB = size / (1024 * 1024);\n if (sizeInMB > maxSizeMB) {\n console.error(\n chalk.red(\n `Error: Archive size (${sizeInMB.toFixed(\n 2,\n )} MB) exceeds maximum allowed size (${maxSizeMB} MB)`,\n ),\n );\n console.log(\n chalk.gray(\n \"Consider adding more patterns to .gitignore to reduce archive size\",\n ),\n );\n process.exit(1);\n }\n}\n","import chalk from \"chalk\";\n\nimport { type PublishConfig } from \"./config.js\";\n\nexport interface BuildMetadata {\n entrypoint: string;\n projectId?: string;\n}\n\nexport interface UploadResult {\n buildId?: string;\n success: boolean;\n message?: string;\n}\n\nexport type BuildStatus = \"RUNNING\" | \"COMPLETED\" | \"FAILED\";\n\nexport interface BuildStatusResponse {\n id: string;\n status: BuildStatus;\n}\n\nexport async function uploadBuild(\n config: PublishConfig,\n archiveBuffer: Buffer,\n options?: {\n dryRun?: boolean;\n },\n): Promise<UploadResult> {\n if (options?.dryRun) {\n console.log(chalk.cyan(\"\\n[Dry run] Would upload to:\"));\n console.log(chalk.gray(` URL: ${config.apiUrl}/v1/functions/builds`));\n console.log(chalk.gray(` Project ID: ${config.projectId}`));\n console.log(chalk.gray(` Entrypoint: ${config.entrypoint}`));\n console.log(\n chalk.gray(\n ` Archive size: ${(archiveBuffer.length / (1024 * 1024)).toFixed(2)} MB`,\n ),\n );\n return {\n success: true,\n message: \"Dry run completed successfully\",\n };\n }\n\n console.log(chalk.cyan(\"\\nUploading build...\"));\n\n try {\n // Create form data\n const formData = new FormData();\n\n // Add metadata\n const metadata: BuildMetadata = {\n entrypoint: config.entrypoint,\n projectId: config.projectId,\n };\n formData.append(\"metadata\", JSON.stringify(metadata));\n\n // Add archive file as a blob\n const blob = new Blob([archiveBuffer], { type: \"application/gzip\" });\n formData.append(\"archive\", blob, \"archive.tar.gz\");\n\n // Make the request\n const url = `${config.apiUrl}/v1/functions/builds`;\n console.log(chalk.gray(`Uploading to: ${url}`));\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"x-bb-api-key\": config.apiKey,\n },\n body: formData,\n });\n\n // Handle response\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}: ${response.statusText}`;\n\n try {\n const errorBody = await response.json();\n if (\n typeof errorBody === \"object\" &&\n errorBody !== null &&\n (\"message\" in errorBody || \"error\" in errorBody)\n ) {\n const typedErrorBody = errorBody as {\n message?: string;\n error?: string;\n };\n errorMessage =\n typedErrorBody.message || typedErrorBody.error || errorMessage;\n }\n } catch {\n // If response is not JSON, try text\n try {\n const textBody = await response.text();\n if (textBody) {\n errorMessage = textBody;\n }\n } catch {\n // Keep default error message\n }\n }\n\n console.error(chalk.red(`Upload failed: ${errorMessage}`));\n return {\n success: false,\n message: errorMessage,\n };\n }\n\n // Parse successful response\n let responseData: { id?: string } = {};\n try {\n const jsonResponse = await response.json();\n if (typeof jsonResponse === \"object\" && jsonResponse !== null) {\n responseData = jsonResponse as { id?: string };\n }\n } catch {\n // Response might not be JSON\n }\n\n if (!responseData.id) {\n console.error(\n chalk.red(\"Upload failed: No build ID received in response\"),\n );\n return {\n success: false,\n message: \"No build ID received in response\",\n };\n }\n\n console.log(chalk.green(\"✓ Build uploaded successfully\"));\n console.log(chalk.gray(`Build ID: ${responseData.id}`));\n\n return {\n success: true,\n buildId: responseData.id,\n message: \"Build uploaded successfully\",\n };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error occurred\";\n console.error(chalk.red(`Upload error: ${errorMessage}`));\n\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ECONNREFUSED\"\n ) {\n console.log(\n chalk.yellow(\n `\\nCannot connect to ${config.apiUrl}. Make sure the API server is running.`,\n ),\n );\n }\n\n return {\n success: false,\n message: errorMessage,\n };\n }\n}\n\nasync function getBuildStatus(\n config: PublishConfig,\n buildId: string,\n): Promise<BuildStatusResponse | null> {\n try {\n const url = `${config.apiUrl}/v1/functions/builds/${buildId}`;\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"x-bb-api-key\": config.apiKey,\n },\n });\n\n if (!response.ok) {\n console.error(\n chalk.red(`Failed to get build status: HTTP ${response.status}`),\n );\n return null;\n }\n\n const data = await response.json();\n return data as BuildStatusResponse;\n } catch (error) {\n console.error(\n chalk.red(\n `Error fetching build status: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n ),\n );\n return null;\n }\n}\n\nexport async function pollBuildStatus(\n config: PublishConfig,\n buildId: string,\n options?: {\n intervalMs?: number;\n maxAttempts?: number;\n },\n): Promise<BuildStatusResponse | null> {\n const intervalMs = options?.intervalMs ?? 2000; // Default 2 seconds\n const maxAttempts = options?.maxAttempts ?? 60; // Default 2 minutes max (60 * 2s)\n\n console.log(chalk.cyan(\"\\nWaiting for build to complete...\"));\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const status = await getBuildStatus(config, buildId);\n\n if (!status) {\n console.error(chalk.red(\"Failed to get build status\"));\n return null;\n }\n\n // Show progress indicator\n process.stdout.write(\n `\\r${chalk.gray(`Status: ${status.status}... (${attempt + 1}/${maxAttempts})`)}`,\n );\n\n if (status.status !== \"RUNNING\") {\n process.stdout.write(\"\\r\" + \" \".repeat(50) + \"\\r\"); // Clear the progress line\n\n if (status.status === \"COMPLETED\") {\n console.log(chalk.green(\"✓ Build completed successfully\"));\n } else if (status.status === \"FAILED\") {\n console.error(chalk.red(\"✗ Build failed\"));\n }\n\n return status;\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n\n process.stdout.write(\"\\r\" + \" \".repeat(50) + \"\\r\"); // Clear the progress line\n console.error(chalk.yellow(\"Build is still running after maximum wait time\"));\n return null;\n}\n","import chalk from \"chalk\";\n\nimport { loadConfig, validateConfig } from \"./config.js\";\nimport { createArchive, validateArchiveSize } from \"./archiver.js\";\nimport { uploadBuild, pollBuildStatus } from \"./api-client.js\";\n\nexport interface PublishOptions {\n entrypoint?: string;\n apiUrl?: string;\n dryRun?: boolean;\n}\n\nexport async function publishFunction(options: PublishOptions): Promise<void> {\n console.log(chalk.bold.cyan(\"\\nBrowserbase Functions - Publish\\n\"));\n\n try {\n // Load and validate configuration\n const configOptions: { entrypoint?: string; apiUrl?: string } = {};\n if (options.entrypoint !== undefined) {\n configOptions.entrypoint = options.entrypoint;\n }\n if (options.apiUrl !== undefined) {\n configOptions.apiUrl = options.apiUrl;\n }\n const config = loadConfig(configOptions);\n\n validateConfig(config);\n\n console.log(chalk.gray(`Working directory: ${config.workingDirectory}`));\n console.log(chalk.gray(`Entrypoint: ${config.entrypoint}`));\n console.log(chalk.gray(`API URL: ${config.apiUrl}`));\n console.log(chalk.gray(`Project ID: ${config.projectId}`));\n\n if (options.dryRun) {\n console.log(\n chalk.yellow(\"\\n[Dry run mode - no files will be uploaded]\\n\"),\n );\n }\n\n // Create archive\n const archiveOptions: { dryRun?: boolean } = {};\n if (options.dryRun !== undefined) {\n archiveOptions.dryRun = options.dryRun;\n }\n const archive = await createArchive(\n config.workingDirectory,\n archiveOptions,\n );\n\n // Validate archive size\n validateArchiveSize(archive.size);\n\n // Upload build\n const uploadOptions: { dryRun?: boolean } = {};\n if (options.dryRun !== undefined) {\n uploadOptions.dryRun = options.dryRun;\n }\n const result = await uploadBuild(config, archive.buffer, uploadOptions);\n\n if (!result.success) {\n console.error(chalk.red(\"\\n✗ Publish failed\"));\n process.exit(1);\n }\n\n // Success!\n if (options.dryRun) {\n console.log(chalk.bold.green(\"\\n✓ Dry run completed successfully!\"));\n console.log(\n chalk.cyan(\n \"\\nYour function would have been published. Run without --dry-run to publish.\",\n ),\n );\n } else {\n console.log(chalk.bold.green(\"\\n✓ Function uploaded successfully!\"));\n\n if (result.buildId) {\n console.log(chalk.gray(`\\nBuild ID: ${result.buildId}`));\n\n // Poll for build status\n const buildStatus = await pollBuildStatus(config, result.buildId);\n\n if (buildStatus?.status === \"COMPLETED\") {\n console.log(\n chalk.bold.green(\n \"\\n🎉 Your function has been deployed and is ready for invocation!\",\n ),\n );\n } else if (buildStatus?.status === \"FAILED\") {\n console.error(chalk.red(\"\\n✗ Build failed during processing\"));\n process.exit(1);\n } else {\n console.log(\n chalk.yellow(\n \"\\nBuild status could not be determined. Check the dashboard for updates.\",\n ),\n );\n }\n } else {\n console.log(\n chalk.cyan(\n \"\\nYour function will be available for invocation once the build is processed.\",\n ),\n );\n }\n }\n } catch (error: unknown) {\n console.error(\n chalk.red(\n `\\n✗ Publish failed: ${(error as { message?: string }).message ?? \"unknown error\"}`,\n ),\n );\n\n // if (error.stack && process.env.DEBUG) {\n // console.error(chalk.gray(error.stack));\n // }\n\n process.exit(1);\n }\n}\n","import { ServerResponse } from \"http\";\nimport { randomUUID } from \"crypto\";\nimport chalk from \"chalk\";\nimport type { FunctionInvocationContext } from \"../../schemas/invocation.js\";\n\ninterface HeldConnection {\n response: ServerResponse;\n timestamp: number;\n}\n\nexport interface InvocationPayload {\n functionName: string;\n params: unknown;\n context: FunctionInvocationContext;\n}\n\nexport interface RuntimeError {\n errorMessage: string;\n errorType: string;\n stackTrace: string[];\n}\n\n/**\n * Interface for managing the lifecycle of invocations, bridging between external invoke requests\n * and the function runtime's polling mechanism.\n */\nexport interface IInvocationBridge {\n /**\n * Set a callback to be called when a session should be cleaned up.\n */\n setSessionCleanupCallback(\n callback: (sessionId: string) => Promise<void>,\n ): void;\n\n /**\n * Hold a connection from the runtime waiting for the next invocation.\n * This corresponds to the SDK calling GET /invocation/next.\n */\n holdNextConnection(response: ServerResponse): void;\n\n /**\n * Trigger an invocation by completing the held /next connection with invoke data\n * and holding the invoke connection until the function completes.\n */\n triggerInvocation(\n functionName: string,\n params: unknown,\n context: FunctionInvocationContext,\n invokeResponse: ServerResponse,\n ): boolean;\n\n /**\n * Complete the held invoke connection with a successful response.\n */\n completeWithSuccess(requestId: string, result: unknown): boolean;\n\n /**\n * Complete the held invoke connection with an error response.\n */\n completeWithError(requestId: string, error: RuntimeError): boolean;\n\n /**\n * Check if the bridge is ready to accept invocations.\n */\n isReady(): boolean;\n\n /**\n * Check if there's an active invocation.\n */\n hasActiveInvocation(): boolean;\n\n /**\n * Get the current request ID if there's an active invocation.\n */\n getCurrentRequestId(): string | null;\n\n /**\n * Check if the runtime has connected at least once.\n */\n isRuntimeConnected(): boolean;\n}\n\n/**\n * Manages the lifecycle of invocations, bridging between external invoke requests\n * and the function runtime's polling mechanism.\n */\nexport class InvocationBridge implements IInvocationBridge {\n private nextConnection: HeldConnection | null = null;\n private invokeConnection: HeldConnection | null = null;\n private currentRequestId: string | null = null;\n private currentFunctionName: string | null = null;\n private currentSessionId: string | null = null;\n private sessionCleanupCallback:\n | ((sessionId: string) => Promise<void>)\n | null = null;\n private verbose: boolean;\n private runtimeConnectedOnce: boolean = false;\n\n constructor(verbose: boolean = false) {\n this.verbose = verbose;\n }\n\n /**\n * Set a callback to be called when a session should be cleaned up.\n */\n public setSessionCleanupCallback(\n callback: (sessionId: string) => Promise<void>,\n ): void {\n this.sessionCleanupCallback = callback;\n }\n\n /**\n * Hold a connection from the runtime waiting for the next invocation.\n * This corresponds to the SDK calling GET /invocation/next.\n */\n public holdNextConnection(response: ServerResponse): void {\n if (this.nextConnection) {\n // If there's already a held connection, close the old one\n this.nextConnection.response.writeHead(503, {\n \"Content-Type\": \"application/json\",\n });\n this.nextConnection.response.end(\n JSON.stringify({ error: \"Another runtime connected\" }),\n );\n }\n\n this.nextConnection = {\n response,\n timestamp: Date.now(),\n };\n\n // Mark that runtime has connected at least once\n this.runtimeConnectedOnce = true;\n\n if (this.verbose) {\n console.log(\n chalk.cyan(\"🔌 Function runtime connected, ready for invocations\"),\n );\n }\n }\n\n /**\n * Trigger an invocation by completing the held /next connection with invoke data\n * and holding the invoke connection until the function completes.\n */\n public triggerInvocation(\n functionName: string,\n params: unknown,\n context: FunctionInvocationContext,\n invokeResponse: ServerResponse,\n ): boolean {\n // Check if runtime is ready (has a held /next connection)\n if (!this.nextConnection) {\n if (this.verbose) {\n console.log(\n chalk.yellow(\"⚠️ No runtime connected to handle invocation\"),\n );\n }\n return false;\n }\n\n // Check if there's already an active invocation\n if (this.invokeConnection) {\n if (this.verbose) {\n console.log(\n chalk.yellow(\"⚠️ Another invocation is already in progress\"),\n );\n }\n return false;\n }\n\n // Generate a request ID for this invocation\n const requestId = randomUUID();\n this.currentRequestId = requestId;\n this.currentFunctionName = functionName;\n this.currentSessionId = context.session.id;\n\n // Hold the invoke connection\n this.invokeConnection = {\n response: invokeResponse,\n timestamp: Date.now(),\n };\n\n // Complete the held /next connection with the invocation payload\n const payload: InvocationPayload = {\n functionName,\n params,\n context,\n };\n\n // Set Lambda runtime headers\n this.nextConnection.response.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Lambda-Runtime-Aws-Request-Id\": requestId,\n \"Lambda-Runtime-Deadline-Ms\": String(Date.now() + 300000), // 5 minutes from now\n \"Lambda-Runtime-Invoked-Function-Arn\": `arn:aws:lambda:us-east-1:000000000000:function:${functionName}`,\n });\n\n this.nextConnection.response.end(JSON.stringify(payload));\n this.nextConnection = null;\n\n console.log(\n chalk.blue(\n `🚀 Invoking function '${functionName}' (request-id: ${requestId})`,\n ),\n );\n\n return true;\n }\n\n /**\n * Complete the held invoke connection with a successful response.\n */\n public completeWithSuccess(requestId: string, result: unknown): boolean {\n // Validate request ID matches\n if (requestId !== this.currentRequestId) {\n if (this.verbose) {\n console.log(\n chalk.yellow(\n `⚠️ Request ID mismatch: expected ${this.currentRequestId}, got ${requestId}`,\n ),\n );\n }\n return false;\n }\n\n // Check if there's an active invocation\n if (!this.invokeConnection) {\n if (this.verbose) {\n console.log(chalk.yellow(\"⚠️ No active invocation to complete\"));\n }\n return false;\n }\n\n // Complete the held invoke connection\n this.invokeConnection.response.writeHead(200, {\n \"Content-Type\": \"application/json\",\n });\n this.invokeConnection.response.end(JSON.stringify(result ?? {}));\n\n console.log(\n chalk.green(\n `✓ Function '${this.currentFunctionName}' completed successfully`,\n ),\n );\n\n // Clean up session if callback is set\n if (this.sessionCleanupCallback && this.currentSessionId) {\n this.sessionCleanupCallback(this.currentSessionId).catch((error) => {\n console.error(chalk.red(\"Failed to cleanup session:\"), error);\n });\n }\n\n // Clean up state\n this.invokeConnection = null;\n this.currentRequestId = null;\n this.currentFunctionName = null;\n this.currentSessionId = null;\n\n return true;\n }\n\n /**\n * Complete the held invoke connection with an error response.\n */\n public completeWithError(requestId: string, error: RuntimeError): boolean {\n // Validate request ID matches\n if (requestId !== this.currentRequestId) {\n if (this.verbose) {\n console.log(\n chalk.yellow(\n `⚠️ Request ID mismatch: expected ${this.currentRequestId}, got ${requestId}`,\n ),\n );\n }\n return false;\n }\n\n // Check if there's an active invocation\n if (!this.invokeConnection) {\n if (this.verbose) {\n console.log(chalk.yellow(\"⚠️ No active invocation to complete\"));\n }\n return false;\n }\n\n // Complete the held invoke connection with error\n this.invokeConnection.response.writeHead(500, {\n \"Content-Type\": \"application/json\",\n });\n this.invokeConnection.response.end(\n JSON.stringify({\n error: {\n message: error.errorMessage,\n type: error.errorType,\n stackTrace: error.stackTrace,\n },\n }),\n );\n\n console.log(\n chalk.red(\n `✗ Function '${this.currentFunctionName}' failed: ${error.errorMessage}`,\n ),\n );\n\n // Clean up session if callback is set\n if (this.sessionCleanupCallback && this.currentSessionId) {\n this.sessionCleanupCallback(this.currentSessionId).catch((error) => {\n console.error(chalk.red(\"Failed to cleanup session:\"), error);\n });\n }\n\n // Clean up state\n this.invokeConnection = null;\n this.currentRequestId = null;\n this.currentFunctionName = null;\n this.currentSessionId = null;\n\n return true;\n }\n\n /**\n * Check if the bridge is ready to accept invocations.\n */\n public isReady(): boolean {\n return this.nextConnection !== null && this.invokeConnection === null;\n }\n\n /**\n * Check if there's an active invocation.\n */\n public hasActiveInvocation(): boolean {\n return this.invokeConnection !== null;\n }\n\n /**\n * Get the current request ID if there's an active invocation.\n */\n public getCurrentRequestId(): string | null {\n return this.currentRequestId;\n }\n\n /**\n * Check if the runtime has connected at least once.\n */\n public isRuntimeConnected(): boolean {\n return this.runtimeConnectedOnce && this.nextConnection !== null;\n }\n}\n","import Browserbase from \"@browserbasehq/sdk\";\nimport chalk from \"chalk\";\n\nexport interface SessionConfig {\n [key: string]: unknown;\n}\n\nexport interface Session {\n id: string;\n connectUrl: string;\n}\n\n/**\n * Interface for managing remote browser sessions\n */\nexport interface IRemoteBrowserManager {\n /**\n * Initialize the browser manager and check credentials\n */\n initialize(): Promise<void>;\n\n /**\n * Create a new browser session\n */\n createSession(sessionConfig?: SessionConfig): Promise<Session>;\n\n /**\n * Close a browser session\n */\n closeSession(sessionId: string): Promise<void>;\n\n /**\n * Get the project ID\n */\n getProjectId(): string;\n\n /**\n * Check if the manager is initialized\n */\n isInitialized(): boolean;\n}\n\n/**\n * Manages remote browser sessions using Browserbase\n */\nexport class RemoteBrowserManager implements IRemoteBrowserManager {\n private browserbaseClient: Browserbase | null = null;\n private projectId: string;\n private apiKey: string;\n private initialized: boolean = false;\n\n constructor() {\n const foundProjectId = process.env[\"BB_PROJECT_ID\"];\n const foundApiKey = process.env[\"BB_API_KEY\"];\n\n if (!foundProjectId || !foundApiKey) {\n console.error(\n chalk.red(\"✗ Browserbase credentials not found.\\n\") +\n chalk.red(\n \" Please set BB_PROJECT_ID and BB_API_KEY in your .env file.\\n\",\n ) +\n chalk.gray(\n \" Copy .env.example to .env and fill in your credentials.\",\n ),\n );\n throw new Error(\"Missing Browserbase credentials\");\n }\n\n this.projectId = foundProjectId;\n this.apiKey = foundApiKey;\n }\n\n /**\n * Initialize the browser manager and check credentials\n */\n public async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Creating a new Browserbase client is sufficient to assume connection\n this.browserbaseClient = new Browserbase({\n apiKey: this.apiKey,\n });\n\n this.initialized = true;\n console.log(chalk.green(\"✓ Browserbase client initialized\"));\n }\n\n /**\n * Create a new browser session\n */\n public async createSession(sessionConfig?: SessionConfig): Promise<Session> {\n if (!this.browserbaseClient) {\n throw new Error(\"Browser manager not initialized\");\n }\n\n console.log(chalk.cyan(`Creating browser session...`));\n\n const createdSession = await this.browserbaseClient.sessions.create({\n projectId: this.projectId,\n ...sessionConfig,\n });\n\n const session: Session = {\n id: createdSession.id,\n connectUrl: createdSession.connectUrl,\n };\n\n console.log(chalk.green(`✓ Browser session created: ${session.id}`));\n return session;\n }\n\n /**\n * Close a browser session\n */\n public async closeSession(sessionId: string): Promise<void> {\n if (!this.browserbaseClient) {\n throw new Error(\"Browser manager not initialized\");\n }\n\n try {\n console.log(chalk.cyan(`Closing browser session: ${sessionId}...`));\n await this.browserbaseClient.sessions.update(sessionId, {\n projectId: this.projectId,\n status: \"REQUEST_RELEASE\",\n });\n console.log(chalk.green(`✓ Browser session closed: ${sessionId}`));\n } catch (error) {\n // Session might already be closed or expired, log but don't throw\n console.warn(\n chalk.yellow(`⚠️ Could not close session ${sessionId}:`),\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n /**\n * Get the project ID\n */\n public getProjectId(): string {\n return this.projectId;\n }\n\n /**\n * Check if the manager is initialized\n */\n public isInitialized(): boolean {\n return this.initialized;\n }\n}\n","import { readFileSync, existsSync, readdirSync } from \"fs\";\nimport { join } from \"path\";\nimport chalk from \"chalk\";\nimport type { PersistedFunctionManifest } from \"../../../types/definition.js\";\nimport type { JSONSchemaInput } from \"../../../types/schema.js\";\n\n/**\n * Interface for managing function manifests\n */\nexport interface IManifestStore {\n /**\n * Load manifests from the filesystem\n */\n loadManifests(): void;\n\n /**\n * Get a manifest by function name\n */\n getManifest(\n functionName: string,\n ): PersistedFunctionManifest<JSONSchemaInput> | undefined;\n\n /**\n * Get the total number of loaded manifests\n */\n getSize(): number;\n\n /**\n * Check if a manifest exists for the given function name\n */\n hasManifest(functionName: string): boolean;\n\n /**\n * Get all loaded manifest names\n */\n getManifestNames(): string[];\n}\n\n/**\n * Implementation of manifest store for managing function manifests\n */\nexport class ManifestStore implements IManifestStore {\n private manifests = new Map<\n string,\n PersistedFunctionManifest<JSONSchemaInput>\n >();\n private manifestsPath: string;\n\n constructor(manifestsPath?: string) {\n this.manifestsPath =\n manifestsPath ||\n join(process.cwd(), \".browserbase\", \"functions\", \"manifests\");\n }\n\n /**\n * Load function manifests from the filesystem\n */\n public loadManifests(): void {\n if (!existsSync(this.manifestsPath)) {\n console.log(chalk.yellow(`⚠️ No ${this.manifestsPath} directory found`));\n console.log(\n chalk.gray(\" Run your entrypoint file first to generate manifests\"),\n );\n return;\n }\n\n try {\n const files = readdirSync(this.manifestsPath);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n for (const file of jsonFiles) {\n const filePath = join(this.manifestsPath, file);\n const content = readFileSync(filePath, \"utf-8\");\n const manifest = JSON.parse(\n content,\n ) as PersistedFunctionManifest<JSONSchemaInput>;\n\n this.manifests.set(manifest.name, manifest);\n console.log(\n chalk.gray(` Loaded manifest for function: ${manifest.name}`),\n );\n }\n\n if (this.manifests.size > 0) {\n console.log(\n chalk.green(`✓ Loaded ${this.manifests.size} function manifest(s)`),\n );\n } else {\n console.log(\n chalk.yellow(\n \"⚠️ No function manifests found in .browserbase directory\",\n ),\n );\n }\n } catch (error) {\n console.error(chalk.red(\"Failed to load function manifests:\"), error);\n }\n }\n\n /**\n * Get a manifest by function name\n */\n public getManifest(\n functionName: string,\n ): PersistedFunctionManifest<JSONSchemaInput> | undefined {\n return this.manifests.get(functionName);\n }\n\n /**\n * Get the total number of loaded manifests\n */\n public getSize(): number {\n return this.manifests.size;\n }\n\n /**\n * Check if a manifest exists for the given function name\n */\n public hasManifest(functionName: string): boolean {\n return this.manifests.has(functionName);\n }\n\n /**\n * Get all loaded manifest names\n */\n public getManifestNames(): string[] {\n return Array.from(this.manifests.keys());\n }\n}\n","import { IncomingMessage } from \"http\";\nimport { z } from \"zod\";\n\n/**\n * Interface for request parsing operations\n */\nexport interface IRequestParser {\n /**\n * Parse JSON body from an incoming request\n */\n parseJsonBody(req: IncomingMessage): Promise<unknown>;\n\n /**\n * Parse and validate JSON body with a Zod schema\n */\n parseAndValidate<T>(req: IncomingMessage, schema: z.ZodType<T>): Promise<T>;\n}\n\n/**\n * Request parser implementation\n */\nexport const requestParser: IRequestParser = {\n async parseJsonBody(req: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let body = \"\";\n\n req.on(\"data\", (chunk) => {\n body += chunk.toString();\n });\n\n req.on(\"end\", () => {\n try {\n const parsed = body ? JSON.parse(body) : {};\n resolve(parsed);\n } catch (error: unknown) {\n reject(new Error(\"Invalid JSON body\", { cause: error }));\n }\n });\n\n req.on(\"error\", reject);\n });\n },\n\n async parseAndValidate<T>(\n req: IncomingMessage,\n schema: z.ZodType<T>,\n ): Promise<T> {\n const body = await this.parseJsonBody(req);\n return schema.parse(body);\n },\n};\n","import { ServerResponse } from \"http\";\n\n/**\n * Standard response format for errors\n */\nexport interface ErrorResponse {\n error: string;\n message?: string;\n details?: unknown;\n}\n\n/**\n * Standard response format for success\n */\nexport interface SuccessResponse<T = unknown> {\n status: string;\n data?: T;\n}\n\n/**\n * Interface for response building operations\n */\nexport interface IResponseBuilder {\n /**\n * Send a JSON response with the given status code\n */\n sendJson(res: ServerResponse, statusCode: number, data: unknown): void;\n\n /**\n * Send a success response\n */\n sendSuccess<T = unknown>(\n res: ServerResponse,\n data?: T,\n statusCode?: number,\n ): void;\n\n /**\n * Send an error response\n */\n sendError(\n res: ServerResponse,\n error: string,\n statusCode?: number,\n message?: string,\n details?: unknown,\n ): void;\n\n /**\n * Send a 400 Bad Request error\n */\n sendBadRequest(res: ServerResponse, message: string, details?: unknown): void;\n\n /**\n * Send a 404 Not Found error\n */\n sendNotFound(res: ServerResponse, message: string): void;\n\n /**\n * Send a 500 Internal Server Error\n */\n sendInternalError(\n res: ServerResponse,\n message?: string,\n details?: unknown,\n ): void;\n\n /**\n * Send a 503 Service Unavailable error\n */\n sendServiceUnavailable(res: ServerResponse, message: string): void;\n\n /**\n * Send a 202 Accepted response\n */\n sendAccepted(res: ServerResponse, data?: unknown): void;\n}\n\n/**\n * Response builder implementation\n */\nexport const responseBuilder: IResponseBuilder = {\n sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.writeHead(statusCode, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n },\n\n sendSuccess<T = unknown>(\n res: ServerResponse,\n data?: T,\n statusCode: number = 200,\n ): void {\n const response: SuccessResponse<T> = {\n status: \"success\",\n ...(data !== undefined && { data }),\n };\n this.sendJson(res, statusCode, response);\n },\n\n sendError(\n res: ServerResponse,\n error: string,\n statusCode: number = 500,\n message?: string,\n details?: unknown,\n ): void {\n const response: ErrorResponse = {\n error,\n };\n if (message) {\n response.message = message;\n }\n if (details) {\n response.details = details;\n }\n this.sendJson(res, statusCode, response);\n },\n\n sendBadRequest(\n res: ServerResponse,\n message: string,\n details?: unknown,\n ): void {\n this.sendError(res, \"Bad Request\", 400, message, details);\n },\n\n sendNotFound(res: ServerResponse, message: string): void {\n this.sendError(res, \"Not Found\", 404, message);\n },\n\n sendInternalError(\n res: ServerResponse,\n message: string = \"An internal error occurred\",\n details?: unknown,\n ): void {\n this.sendError(res, \"Internal Server Error\", 500, message, details);\n },\n\n sendServiceUnavailable(res: ServerResponse, message: string): void {\n this.sendError(res, \"Service Unavailable\", 503, message);\n },\n\n sendAccepted(res: ServerResponse, data?: unknown): void {\n const response = data || { status: \"accepted\" };\n this.sendJson(res, 202, response);\n },\n};\n","import z from \"zod\";\n\nexport const FunctionInvocationContextSessionDetails = z.object({\n id: z.string(),\n connectUrl: z.string(),\n});\n\nexport type FunctionInvocationContextSessionDetails = z.infer<\n typeof FunctionInvocationContextSessionDetails\n>;\n\nexport const FunctionInvocationContext = z.object({\n session: FunctionInvocationContextSessionDetails,\n});\n\nexport type FunctionInvocationContext = z.infer<\n typeof FunctionInvocationContext\n>;\n","import z from \"zod\";\nimport { FunctionInvocationContext } from \"./invocation.js\";\n\nexport const RuntimeEventPayload = z.object({\n functionName: z.string().min(1),\n params: z.looseObject({}), // Allow passthrough of unknown (all) keys\n context: FunctionInvocationContext,\n});\n\nexport type RuntimeEventPayload = z.infer<typeof RuntimeEventPayload>;\n\nexport const RuntimeEvent = z.object({\n requestId: z.string().min(1),\n event: RuntimeEventPayload,\n});\n\nexport type RuntimeEvent = z.infer<typeof RuntimeEvent>;\n\nexport const RuntimeError = z.object({\n errorMessage: z.string().min(1),\n errorType: z.string().min(1),\n stackTrace: z.array(z.string().min(1)),\n});\n\nexport type RuntimeError = z.infer<typeof RuntimeError>;\n","import { IncomingMessage, ServerResponse } from \"http\";\nimport { z } from \"zod\";\nimport chalk from \"chalk\";\nimport { type IInvocationBridge } from \"../bridge.js\";\nimport { type IRemoteBrowserManager } from \"../browser-manager.js\";\nimport { type IManifestStore } from \"./manifest-store.js\";\nimport { requestParser } from \"./request-parser.js\";\nimport { responseBuilder } from \"./response-builder.js\";\nimport { RuntimeError } from \"../../../schemas/events.js\";\nimport { FunctionInvocationContext } from \"../../../schemas/invocation.js\";\n\n/**\n * Dependencies required by the request handlers\n */\nexport interface RequestHandlerDependencies {\n bridge: IInvocationBridge;\n browserManager: IRemoteBrowserManager;\n manifestStore: IManifestStore;\n}\n\n/**\n * Interface for request handlers\n */\nexport interface IRequestHandlers {\n /**\n * Handle GET /2018-06-01/runtime/invocation/next\n * This endpoint is called by the runtime to get the next invocation.\n * We hold the connection until an invocation arrives.\n */\n handleInvocationNext(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void>;\n\n /**\n * Handle POST /v1/functions/:name/invoke\n * This endpoint is called by external clients to invoke a function.\n */\n handleFunctionInvoke(\n req: IncomingMessage,\n res: ServerResponse,\n functionName: string,\n ): Promise<void>;\n\n /**\n * Handle POST /2018-06-01/runtime/invocation/:requestId/response\n * This endpoint is called by the runtime when a function completes successfully.\n */\n handleInvocationResponse(\n req: IncomingMessage,\n res: ServerResponse,\n requestId: string,\n ): Promise<void>;\n\n /**\n * Handle POST /2018-06-01/runtime/invocation/:requestId/error\n * This endpoint is called by the runtime when a function fails.\n */\n handleInvocationError(\n req: IncomingMessage,\n res: ServerResponse,\n requestId: string,\n ): Promise<void>;\n}\n\n/**\n * Implementation of request handlers for the dev server\n */\nexport class DevServerHandlers implements IRequestHandlers {\n private readonly bridge: IInvocationBridge;\n private readonly browserManager: IRemoteBrowserManager;\n private readonly manifestStore: IManifestStore;\n\n constructor(deps: RequestHandlerDependencies) {\n this.bridge = deps.bridge;\n this.browserManager = deps.browserManager;\n this.manifestStore = deps.manifestStore;\n\n // Set up the session cleanup callback in the bridge\n this.bridge.setSessionCleanupCallback(async (sessionId: string) => {\n await this.cleanupSession(sessionId);\n });\n }\n\n /**\n * Handle GET /2018-06-01/runtime/invocation/next\n */\n public async handleInvocationNext(\n _req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n // Hold the connection in the bridge\n this.bridge.holdNextConnection(res);\n\n // The response will be completed later when an invocation arrives\n // via triggerInvocation in the bridge\n }\n\n /**\n * Handle POST /v1/functions/:name/invoke\n */\n public async handleFunctionInvoke(\n req: IncomingMessage,\n res: ServerResponse,\n functionName: string,\n ): Promise<void> {\n try {\n // Define the invoke request schema\n const invokeSchema = z.object({\n functionName: z.string().optional(),\n params: z.unknown().default({}),\n context: FunctionInvocationContext.optional(),\n });\n\n // Parse and validate the request body\n const validatedData = await requestParser.parseAndValidate(\n req,\n invokeSchema,\n );\n\n // Use function name from URL path\n const finalFunctionName = functionName || validatedData.functionName;\n\n if (!finalFunctionName) {\n responseBuilder.sendBadRequest(res, \"Function name is required\");\n return;\n }\n\n // Look up function manifest to get sessionConfig\n const manifest = this.manifestStore.getManifest(finalFunctionName);\n\n if (!manifest) {\n console.error(\n chalk.red(`✗ Function \"${finalFunctionName}\" not found in registry`),\n );\n console.error(\n chalk.gray(\n \" Make sure the function is defined in your entrypoint file\",\n ),\n );\n responseBuilder.sendNotFound(\n res,\n `Function \"${finalFunctionName}\" not found in registry. Make sure it is defined with defineFn() in your entrypoint file.`,\n );\n return;\n }\n\n // Always create a browser session\n let session: { id: string; connectUrl: string };\n\n try {\n console.log(\n chalk.cyan(`Creating browser session for ${finalFunctionName}...`),\n );\n\n // Create session with function's sessionConfig if available\n const sessionConfig = manifest?.config?.sessionConfig || {};\n session = await this.browserManager.createSession(sessionConfig);\n } catch (error) {\n console.error(chalk.red(\"Failed to create browser session:\"), error);\n responseBuilder.sendInternalError(\n res,\n \"Failed to create browser session\",\n error instanceof Error ? error.message : String(error),\n );\n return;\n }\n\n // Build context with the created session\n const context = validatedData.context || {\n invocation: {\n id: crypto.randomUUID(),\n region: \"local\",\n },\n session: session,\n };\n\n // Always use the created session\n context.session = session;\n\n // Try to trigger the invocation\n const success = this.bridge.triggerInvocation(\n finalFunctionName,\n validatedData.params,\n context,\n res,\n );\n\n if (!success) {\n // Runtime not ready or another invocation in progress\n // Clean up the session we just created since we won't use it\n await this.cleanupSession(session.id);\n\n responseBuilder.sendServiceUnavailable(\n res,\n this.bridge.hasActiveInvocation()\n ? \"Another invocation is in progress\"\n : \"No runtime connected\",\n );\n return;\n }\n\n // The response will be completed later when the function completes\n // via completeWithSuccess or completeWithError in the bridge\n } catch (error) {\n if (error instanceof z.ZodError) {\n responseBuilder.sendBadRequest(res, \"Invalid request body\", error);\n } else {\n console.error(chalk.red(\"Error handling invoke:\"), error);\n responseBuilder.sendInternalError(res);\n }\n }\n }\n\n /**\n * Handle POST /2018-06-01/runtime/invocation/:requestId/response\n */\n public async handleInvocationResponse(\n req: IncomingMessage,\n res: ServerResponse,\n requestId: string,\n ): Promise<void> {\n try {\n // Parse the response body\n const body = await requestParser.parseJsonBody(req);\n\n // Complete the invocation with success\n const success = this.bridge.completeWithSuccess(requestId, body);\n\n if (!success) {\n responseBuilder.sendBadRequest(\n res,\n \"No matching invocation or request ID mismatch\",\n );\n return;\n }\n\n // Send acknowledgment to the runtime\n responseBuilder.sendAccepted(res);\n } catch (error) {\n console.error(chalk.red(\"Error handling response:\"), error);\n responseBuilder.sendInternalError(res);\n }\n }\n\n /**\n * Handle POST /2018-06-01/runtime/invocation/:requestId/error\n */\n public async handleInvocationError(\n req: IncomingMessage,\n res: ServerResponse,\n requestId: string,\n ): Promise<void> {\n try {\n // Parse and validate the error body using SDK schema\n const validatedError = await requestParser.parseAndValidate(\n req,\n RuntimeError,\n );\n\n // Complete the invocation with error\n const success = this.bridge.completeWithError(requestId, validatedError);\n\n if (!success) {\n responseBuilder.sendBadRequest(\n res,\n \"No matching invocation or request ID mismatch\",\n );\n return;\n }\n\n // Send acknowledgment to the runtime\n responseBuilder.sendAccepted(res);\n } catch (error) {\n if (error instanceof z.ZodError) {\n responseBuilder.sendBadRequest(res, \"Invalid error format\", error);\n } else {\n console.error(chalk.red(\"Error handling error report:\"), error);\n responseBuilder.sendInternalError(res);\n }\n }\n }\n\n /**\n * Private method to cleanup a browser session\n */\n private async cleanupSession(sessionId: string): Promise<void> {\n try {\n await this.browserManager.closeSession(sessionId);\n } catch (error) {\n console.error(\n chalk.red(`Failed to cleanup session ${sessionId}:`),\n error,\n );\n }\n }\n}\n","import { createServer, Server, IncomingMessage, ServerResponse } from \"http\";\nimport chalk from \"chalk\";\nimport { type IInvocationBridge } from \"./bridge.js\";\nimport { type IRemoteBrowserManager } from \"./browser-manager.js\";\nimport { type IRequestHandlers } from \"./handlers/index.js\";\n\nexport interface ServerOptions {\n port: number;\n host: string;\n bridge: IInvocationBridge;\n browserManager: IRemoteBrowserManager;\n handlers: IRequestHandlers;\n}\n\nexport interface RequestHandlerDeps {\n bridge: IInvocationBridge;\n browserManager: IRemoteBrowserManager;\n handlers: IRequestHandlers;\n}\n\n/**\n * Main request handler for the dev server\n * Extracted for testability\n */\nexport async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n deps: RequestHandlerDeps,\n): Promise<void> {\n const { handlers } = deps;\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const method = req.method || \"GET\";\n const path = url.pathname;\n\n console.log(chalk.gray(`[${method}] ${path}`));\n\n // Set CORS headers for local development\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\n // Handle preflight requests\n if (method === \"OPTIONS\") {\n res.writeHead(200);\n res.end();\n return;\n }\n\n try {\n // Route: GET / (healthcheck)\n if (method === \"GET\" && path === \"/\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true }));\n return;\n }\n\n // Route: GET /2018-06-01/runtime/invocation/next\n if (method === \"GET\" && path === \"/2018-06-01/runtime/invocation/next\") {\n await handlers.handleInvocationNext(req, res);\n return;\n }\n\n // Route: POST /v1/functions/:name/invoke\n const invokeMatch = path.match(/^\\/v1\\/functions\\/([^/]+)\\/invoke$/);\n if (method === \"POST\" && invokeMatch && invokeMatch[1]) {\n const functionName = invokeMatch[1];\n await handlers.handleFunctionInvoke(req, res, functionName);\n return;\n }\n\n // Route: POST /2018-06-01/runtime/invocation/:requestId/response\n const responseMatch = path.match(\n /^\\/2018-06-01\\/runtime\\/invocation\\/([^/]+)\\/response$/,\n );\n if (method === \"POST\" && responseMatch && responseMatch[1]) {\n const requestId = responseMatch[1];\n await handlers.handleInvocationResponse(req, res, requestId);\n return;\n }\n\n // Route: POST /2018-06-01/runtime/invocation/:requestId/error\n const errorMatch = path.match(\n /^\\/2018-06-01\\/runtime\\/invocation\\/([^/]+)\\/error$/,\n );\n if (method === \"POST\" && errorMatch && errorMatch[1]) {\n const requestId = errorMatch[1];\n await handlers.handleInvocationError(req, res, requestId);\n return;\n }\n\n // 404 for unknown routes\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n } catch (error) {\n console.error(chalk.red(\"Server error:\"), error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal server error\" }));\n }\n}\n\nexport async function startServer(options: ServerOptions): Promise<Server> {\n const { port, host, bridge, browserManager, handlers } = options;\n\n const server = createServer(\n async (req: IncomingMessage, res: ServerResponse) => {\n await handleRequest(req, res, { bridge, browserManager, handlers });\n },\n );\n\n return new Promise((resolve, reject) => {\n server.listen(port, host, () => {\n resolve(server);\n });\n\n server.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EADDRINUSE\") {\n reject(new Error(`Port ${port} is already in use`));\n } else if (error.code === \"EACCES\") {\n reject(new Error(`Permission denied to bind to port ${port}`));\n } else {\n reject(error);\n }\n });\n });\n}\n","import { spawn, ChildProcess } from \"child_process\";\nimport chalk from \"chalk\";\n\nexport interface ProcessManagerOptions {\n entrypoint: string;\n runtimeApiUrl: string;\n verbose: boolean;\n}\n\n/**\n * Interface for managing the lifecycle of the user's function process.\n * Spawns tsx watch to enable hot reloading during development.\n */\nexport interface IProcessManager {\n /**\n * Start the user's function process using tsx watch.\n */\n start(): Promise<void>;\n\n /**\n * Stop the user's function process.\n */\n stop(): Promise<void>;\n\n /**\n * Check if the process is currently running.\n */\n isRunning(): boolean;\n}\n\n/**\n * Manages the lifecycle of the user's function process.\n * Spawns tsx watch to enable hot reloading during development.\n */\nexport class ProcessManager implements IProcessManager {\n private process: ChildProcess | null = null;\n private entrypoint: string;\n private runtimeApiUrl: string;\n private verbose: boolean;\n private isShuttingDown = false;\n\n constructor(options: ProcessManagerOptions) {\n this.entrypoint = options.entrypoint;\n this.runtimeApiUrl = options.runtimeApiUrl;\n this.verbose = options.verbose;\n }\n\n /**\n * Start the user's function process using tsx watch.\n */\n public async start(): Promise<void> {\n if (this.process) {\n throw new Error(\"Process is already running\");\n }\n\n if (this.verbose) {\n console.log(chalk.gray(`Starting runtime process...`));\n console.log(\n chalk.gray(\n ` Command: tsx watch --clear-screen=false ${this.entrypoint}`,\n ),\n );\n console.log(chalk.gray(` Working directory: ${process.cwd()}`));\n console.log(chalk.gray(` Runtime API: ${this.runtimeApiUrl}`));\n }\n\n // Spawn tsx watch with the user's entrypoint\n this.process = spawn(\n \"tsx\",\n [\"watch\", \"--clear-screen=false\", this.entrypoint],\n {\n cwd: process.cwd(),\n env: {\n ...process.env,\n AWS_LAMBDA_RUNTIME_API: this.runtimeApiUrl,\n BB_FUNCTIONS_PHASE: \"runtime\",\n NODE_ENV: \"local\",\n },\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n },\n );\n\n // Handle stdout\n this.process.stdout?.on(\"data\", (data) => {\n const lines = data.toString().trim().split(\"\\n\");\n lines.forEach((line: string) => {\n if (line.trim()) {\n console.log(chalk.blue(\"[Runtime]\"), line);\n }\n });\n });\n\n // Handle stderr\n this.process.stderr?.on(\"data\", (data) => {\n const lines = data.toString().trim().split(\"\\n\");\n lines.forEach((line: string) => {\n if (line.trim()) {\n // Check if it's a tsx watch message\n if (line.includes(\"Watching for file changes\")) {\n console.log(chalk.green(\"✓ Runtime watching for file changes\"));\n } else if (line.includes(\"Restarting\")) {\n console.log(\n chalk.yellow(\"↻ Runtime restarting due to file change...\"),\n );\n } else {\n console.error(chalk.red(\"[Runtime Error]\"), line);\n }\n }\n });\n });\n\n // Handle process exit\n this.process.on(\"exit\", (code, signal) => {\n if (!this.isShuttingDown) {\n if (code !== 0) {\n console.error(\n chalk.red(\n `✗ Runtime process exited unexpectedly with code ${code}`,\n ),\n );\n if (signal) {\n console.error(chalk.red(` Signal: ${signal}`));\n }\n } else {\n console.log(chalk.gray(\"Runtime process exited\"));\n }\n this.process = null;\n }\n });\n\n // Handle process errors\n this.process.on(\"error\", (error) => {\n if ((error as Error & { code: string }).code === \"ENOENT\") {\n console.error(\n chalk.red(\"✗ Failed to start runtime: tsx not found\"),\n chalk.yellow(\n \"\\n Make sure tsx is installed: npm install -g tsx or pnpm add tsx\",\n ),\n );\n } else {\n console.error(chalk.red(\"✗ Failed to start runtime process:\"), error);\n }\n this.process = null;\n });\n\n // Give the process a moment to start\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n if (!this.process || this.process.exitCode !== null) {\n throw new Error(\"Failed to start runtime process\");\n }\n\n console.log(chalk.green(\"✓ Runtime process started\"));\n }\n\n /**\n * Stop the user's function process.\n */\n public async stop(): Promise<void> {\n if (!this.process) {\n return;\n }\n\n this.isShuttingDown = true;\n\n if (this.verbose) {\n console.log(chalk.gray(\"Stopping runtime process...\"));\n }\n\n return new Promise((resolve) => {\n if (!this.process) {\n resolve();\n return;\n }\n\n // Set a timeout to force kill if graceful shutdown fails\n const killTimeout = setTimeout(() => {\n if (this.process) {\n console.log(chalk.yellow(\"⚠️ Force killing runtime process\"));\n this.process.kill(\"SIGKILL\");\n }\n }, 5000);\n\n this.process.on(\"exit\", () => {\n clearTimeout(killTimeout);\n this.process = null;\n console.log(chalk.green(\"✓ Runtime process stopped\"));\n resolve();\n });\n\n // Try graceful shutdown first\n this.process.kill(\"SIGTERM\");\n });\n }\n\n /**\n * Check if the process is currently running.\n */\n public isRunning(): boolean {\n return this.process !== null && this.process.exitCode === null;\n }\n}\n","import chalk from \"chalk\";\nimport { startServer } from \"./server.js\";\nimport { InvocationBridge } from \"./bridge.js\";\nimport { ProcessManager } from \"./process.js\";\nimport { RemoteBrowserManager } from \"./browser-manager.js\";\nimport { DevServerHandlers } from \"./handlers/index.js\";\nimport \"dotenv/config\";\nimport { ManifestStore } from \"./handlers/manifest-store.js\";\nimport type { Server } from \"node:http\";\n\nexport interface DevServerOptions {\n entrypoint: string;\n port: number;\n host: string;\n verbose: boolean;\n}\n\nexport async function startDevServer(options: DevServerOptions): Promise<void> {\n const { entrypoint, port, host, verbose } = options;\n\n // Check if we're in production mode\n if (process.env[\"NODE_ENV\"] === \"production\") {\n console.warn(\n chalk.yellow(\n \"⚠️ Warning: Running dev server in production mode. This is not recommended.\",\n ),\n );\n }\n\n // Set the runtime API URL\n const runtimeApiUrl = `${host}:${port}`;\n\n if (verbose) {\n console.log(chalk.gray(`Runtime API URL: ${runtimeApiUrl}`));\n }\n\n // Create the invocation bridge\n const bridge = new InvocationBridge(verbose);\n\n // Create the browser manager\n const browserManager = new RemoteBrowserManager();\n await browserManager.initialize();\n\n // Create and initialize the manifest store\n const manifestStore = new ManifestStore();\n manifestStore.loadManifests();\n\n // Create the handlers with all dependencies\n const handlers = new DevServerHandlers({\n bridge,\n browserManager,\n manifestStore,\n });\n\n // Create the process manager\n const processManager = new ProcessManager({\n entrypoint,\n runtimeApiUrl,\n verbose,\n });\n\n // Start the server\n let server: Server | null = null;\n\n try {\n // Start the server first\n server = await startServer({\n port,\n host,\n bridge,\n browserManager,\n handlers,\n });\n\n console.log(\n chalk.green(`✓ Development server listening on http://${host}:${port}`),\n );\n\n // Then start the user's function process\n console.log(chalk.cyan(\"Starting runtime process...\"));\n await processManager.start();\n\n // Wait for runtime to connect with retry logic\n const maxWaitTime = 10000; // 10 seconds max\n const pollInterval = 200; // Check every 200ms\n const startTime = Date.now();\n let runtimeConnected = false;\n\n while (Date.now() - startTime < maxWaitTime) {\n if (bridge.isRuntimeConnected()) {\n runtimeConnected = true;\n console.log(chalk.green(\"✓ Runtime connected and ready\"));\n // Reload manifests after runtime starts as it may have created them\n manifestStore.loadManifests();\n break;\n }\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n if (!runtimeConnected) {\n console.log(\n chalk.yellow(\n \"⚠️ Runtime is taking longer than expected to connect...\",\n ),\n );\n // Still try to reload manifests in case they were written\n manifestStore.loadManifests();\n }\n\n // Handle graceful shutdown\n const shutdown = async () => {\n console.log(chalk.cyan(\"\\n📦 Shutting down...\"));\n\n // Stop the user process first\n await processManager.stop();\n\n // Then close the server\n return new Promise<void>((resolve) => {\n server?.close(() => {\n console.log(chalk.green(\"✓ Server closed\"));\n resolve();\n });\n });\n };\n\n // Handle process termination\n process.on(\"SIGINT\", async () => {\n await shutdown();\n process.exit(0);\n });\n\n process.on(\"SIGTERM\", async () => {\n await shutdown();\n process.exit(0);\n });\n } catch (error) {\n console.error(chalk.red(\"Failed to start:\"), error);\n\n // Clean up on error\n if (processManager.isRunning()) {\n await processManager.stop();\n }\n if (server) {\n server.close();\n }\n\n throw error;\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { startDevServer } from \"./dev/index.js\";\n\n// Version is injected at build time\ndeclare const __CLI_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name(\"bb\")\n .description(\"Browserbase Functions CLI\")\n .version(__CLI_VERSION__);\n\nprogram\n .command(\"dev\")\n .description(\n \"Start a local development server for testing Browserbase Functions\",\n )\n .argument(\n \"<entrypoint>\",\n \"Path to the TypeScript/JavaScript file that imports all your functions\",\n )\n .option(\"-p, --port <number>\", \"Port to listen on\", \"14113\")\n .option(\"-h, --host <string>\", \"Host to bind to\", \"127.0.0.1\")\n .action(async (entrypoint, options) => {\n try {\n // Validate entrypoint file exists\n const fs = await import(\"fs\");\n const path = await import(\"path\");\n\n const entrypointPath = path.resolve(entrypoint);\n if (!fs.existsSync(entrypointPath)) {\n console.error(\n chalk.red(`Error: Entrypoint file not found: ${entrypointPath}`),\n );\n process.exit(1);\n }\n\n // Validate file extension\n const ext = path.extname(entrypointPath);\n if (![\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\"].includes(ext)) {\n console.error(\n chalk.red(\n `Error: Invalid file extension. Expected .ts, .tsx, .js, .jsx, .mjs, or .cjs`,\n ),\n );\n process.exit(1);\n }\n\n const port = parseInt(options.port, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error(\n chalk.red(\"Error: Invalid port number. Must be between 1 and 65535.\"),\n );\n process.exit(1);\n }\n\n console.log(\n chalk.cyan(\"Starting Browserbase Functions development server...\"),\n );\n console.log(chalk.gray(`Entrypoint: ${entrypointPath}`));\n\n await startDevServer({\n entrypoint: entrypointPath,\n port,\n host: options.host,\n verbose: options.verbose,\n });\n } catch (error) {\n console.error(chalk.red(\"Failed to start development server:\"), error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"publish\")\n .description(\"Publish your Browserbase Function to the cloud\")\n .argument(\n \"<entrypoint>\",\n \"Path to the TypeScript/JavaScript file that imports all your functions\",\n )\n .option(\"-u, --api-url <url>\", \"API endpoint URL\")\n .option(\"--dry-run\", \"Show what would be published without uploading\")\n .action(async (entrypoint, options) => {\n try {\n const { publishFunction } = await import(\"./publish/index.js\");\n await publishFunction({\n entrypoint: entrypoint,\n apiUrl: options.apiUrl,\n dryRun: options.dryRun,\n });\n } catch (error) {\n console.error(chalk.red(\"Publish failed:\"), error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var a = require('zod');
4
+ var path = require('path');
5
+ var fs = require('fs');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var a__default = /*#__PURE__*/_interopDefault(a);
10
+
11
+ var b=Object.defineProperty;var M=(n,t,e)=>t in n?b(n,t,{enumerable:true,configurable:true,writable:true,value:e}):n[t]=e;var s=(n,t,e)=>M(n,typeof t!="symbol"?t+"":t,e);var m=class extends Error{constructor(t){super(t);}},f=class extends Error{constructor(t){super(t);}},l=class extends Error{constructor(t){super(t);}},d=class extends Error{constructor(t){super(t);}};var N=a__default.default.object({id:a__default.default.string(),connectUrl:a__default.default.string()}),w=a__default.default.object({session:N});var x=a__default.default.object({functionName:a__default.default.string().min(1),params:a__default.default.looseObject({}),context:w});a__default.default.object({requestId:a__default.default.string().min(1),event:x});a__default.default.object({errorMessage:a__default.default.string().min(1),errorType:a__default.default.string().min(1),stackTrace:a__default.default.array(a__default.default.string().min(1))});var y=class{constructor(t,e){s(this,"runtimeApi");s(this,"baseUrl");s(this,"registry");this.runtimeApi=e,this.baseUrl=`http://${this.runtimeApi}/2018-06-01/runtime`,this.registry=t;}async waitForNextInvocation(){let t=await fetch(`${this.baseUrl}/invocation/next`);if(!t.ok)throw new f(`Next invocation failed: ${t.status} ${t.statusText}`);let e=t.headers.get("Lambda-Runtime-Aws-Request-Id")||"unknown",o=t.headers.get("Lambda-Runtime-Trace-Id");o&&(process.env._X_AMZN_TRACE_ID=o);let i=await t.text(),r=JSON.parse(i),c=x.safeParse(r);if(!c.success)throw new Error("Failed to parse event into runtime event");let p=c.data;return {requestId:e,event:p}}getFunctionDefinitionByName(t){return this.registry.getByName(t)}executeFunction(t){return this.registry.execute(t.functionName,t.params??{},t.context)}async handleSuccess(t,e){let o=await fetch(`${this.baseUrl}/invocation/${encodeURIComponent(t)}/response`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)});if(!o.ok)throw new l(`Failed to post response: ${o.status} ${o.statusText}`)}async handleFailure(t,e){let o=E(e),i=await fetch(`${this.baseUrl}/invocation/${encodeURIComponent(t)}/error`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o)});if(!i.ok)throw new d(`Failed to post error: ${i.status} ${i.statusText}`)}};function E(n){if(n instanceof Error)return {errorMessage:n.message,errorType:n.name,stackTrace:n.stack?.split("/n")??[]};let t="An unknown error occurred",e="UnknownError",o=[];return typeof n=="string"?{errorMessage:n,errorType:e,stackTrace:o}:typeof n!="object"||n===null?{errorMessage:String(n),errorType:e,stackTrace:o}:("message"in n&&typeof n.message=="string"&&(t=n.message),"name"in n&&typeof n.name=="string"&&(e=n.name),"stack"in n&&Array.isArray(n.stack)&&typeof n.stack[0]=="string"&&(o=n.stack),{errorMessage:t,errorType:e,stackTrace:o})}async function P(n,t){try{let{requestId:e,event:o}=await n.waitForNextInvocation();console.log(`Received invocation with requestId: ${e}`);let{functionName:i}=o,r=n.getFunctionDefinitionByName(i);if(console.log(`Found definition for "${i}": ${JSON.stringify(r)}`),!r)throw new Error(`Function "${i}" not found in registry`);let c;try{console.log(`Executing function: ${i}`),c=await n.executeFunction(o),console.log(`Received result: ${JSON.stringify(c)}`);}catch(p){console.error("Handler error:",p),await n.handleFailure(e,p);return}await n.handleSuccess(e,c),console.log(`Function "${i}" completed successfully`);}catch(e){console.error("Fatal error in runtime loop:",e),t(e);}}async function I(n,t){for(;;)await P(n,t);}var h=class{constructor(){s(this,"_functions",new Map);}register(t,e,o){this._functions.set(t,{name:t,handler:e,config:o});}getByName(t){return this._functions.get(t)??null}async execute(t,e,o){let i=this._functions.get(t);if(!i)throw new m(`Couldn't find function with name "${t}" in registry`);let r=await i.handler(o,e);return console.log("handlerResult",r),r}get size(){return this._functions.size}};var v=class{constructor(t){s(this,"_environment");s(this,"_runtimeApi");s(this,"_phase");this._environment=S(t,"NODE_ENV","local"),this._runtimeApi=S(t,"AWS_LAMBDA_RUNTIME_API","127.0.0.1:14113"),this._phase=S(t,"BB_FUNCTIONS_PHASE","runtime");}get environment(){return this._environment}get runtimeApi(){return this._runtimeApi}get phase(){return this._phase}};function S(n,t,e){let o=n[t];return o||e}function k(n,t,e){e&&(fs.existsSync(t)&&fs.rmSync(t,{recursive:true}),fs.mkdirSync(t,{recursive:true}));let o=A(n);fs.writeFileSync(path.join(t,`${n.name}.json`),JSON.stringify(o,null,2));}function A(n){let{name:t,config:e}=n,{parametersSchema:o,...i}=e,r={...i};return o&&(r.parametersSchema=$(o)),{name:t,config:r}}function $(n){return n instanceof a__default.default.ZodObject?a__default.default.toJSONSchema(n):{}}function D(n,t,e={}){if(F.register(n,t,e),u.phase==="introspect"||u.environment==="local"){let o=path.join(process.cwd(),".browserbase","functions","manifests"),i=F.size===1;k({name:n,config:e},o,i);}}var u=new v(process.env),F=new h,z=new y(F,u.runtimeApi);function H(n){console.error("Received fatal error from invocation loop",n),process.exit(1);}u.phase==="runtime"&&I(z,H).catch(n=>{console.error("Fatal runtime error:",n),process.exit(1);});
12
+
13
+ exports.defineFn = D;
14
+ exports.environmentManager = u;
15
+ exports.functionsRegistry = F;
16
+ exports.runtimeClient = z;
17
+ //# sourceMappingURL=index.cjs.map
18
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/errors.ts","../src/schemas/invocation.ts","../src/schemas/events.ts","../src/runtime/index.ts","../src/runtime/loop.ts","../src/runtime/registry.ts","../src/utils/env.ts","../src/define/helpers.ts","../src/define/index.ts","../src/index.ts"],"names":["FunctionNotFoundInRegistryError","message","GetNextInvocationError","PostResultError","PostErrorError","FunctionInvocationContextSessionDetails","z","FunctionInvocationContext","RuntimeEventPayload","RuntimeClient","registry","runtimeApi","__publicField","response","requestId","traceId","text","parsedData","safeParseResult","event","name","result","error","runtimeError","formatRuntimeError","type","stack","waitForAndHandleInvocation","runtimeClient","handleFatalError","functionName","functionDefinition","runInvocationLoop","handleProductionFailure","FunctionRegistry","handler","config","params","context","foundDefinition","handlerResult","EnvironmentManager","processEnv","getOrDefault","env","key","dflt","val","writeManifestToDisk","manifest","manifestsDir","isFirstInvocation","existsSync","rmSync","mkdirSync","persistedManifest","buildPersistedFunctionManifest","writeFileSync","join","parametersSchema","configWithoutSchema","processedConfig","buildPersistedJsonSchema","input","defineFn","functionsRegistry","environmentManager","handleInvocationLoopFailure"],"mappings":"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","file":"index.cjs","sourcesContent":["export class FunctionNotFoundInRegistryError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class GetNextInvocationError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class PostResultError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class PostErrorError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n","import z from \"zod\";\n\nexport const FunctionInvocationContextSessionDetails = z.object({\n id: z.string(),\n connectUrl: z.string(),\n});\n\nexport type FunctionInvocationContextSessionDetails = z.infer<\n typeof FunctionInvocationContextSessionDetails\n>;\n\nexport const FunctionInvocationContext = z.object({\n session: FunctionInvocationContextSessionDetails,\n});\n\nexport type FunctionInvocationContext = z.infer<\n typeof FunctionInvocationContext\n>;\n","import z from \"zod\";\nimport { FunctionInvocationContext } from \"./invocation.js\";\n\nexport const RuntimeEventPayload = z.object({\n functionName: z.string().min(1),\n params: z.looseObject({}), // Allow passthrough of unknown (all) keys\n context: FunctionInvocationContext,\n});\n\nexport type RuntimeEventPayload = z.infer<typeof RuntimeEventPayload>;\n\nexport const RuntimeEvent = z.object({\n requestId: z.string().min(1),\n event: RuntimeEventPayload,\n});\n\nexport type RuntimeEvent = z.infer<typeof RuntimeEvent>;\n\nexport const RuntimeError = z.object({\n errorMessage: z.string().min(1),\n errorType: z.string().min(1),\n stackTrace: z.array(z.string().min(1)),\n});\n\nexport type RuntimeError = z.infer<typeof RuntimeError>;\n","import type { FunctionRegistry } from \"../runtime/registry.js\";\nimport {\n GetNextInvocationError,\n PostErrorError,\n PostResultError,\n} from \"../utils/errors.js\";\nimport {\n RuntimeError,\n RuntimeEvent,\n RuntimeEventPayload,\n} from \"../schemas/events.js\";\nimport type { FunctionManifest } from \"../types/definition.js\";\nimport type { FunctionHandlerCallbackReturnValue } from \"../types/handler.js\";\n\nexport interface IRuntimeClient {\n waitForNextInvocation(): Promise<RuntimeEvent>;\n getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;\n\n executeFunction(\n event: RuntimeEventPayload,\n ): Promise<FunctionHandlerCallbackReturnValue>;\n\n handleSuccess(\n requestId: string,\n result: FunctionHandlerCallbackReturnValue,\n ): Promise<void>;\n\n handleFailure(requestId: string, error: unknown): Promise<void>;\n}\n\nexport class RuntimeClient implements IRuntimeClient {\n private runtimeApi: string;\n private baseUrl: string;\n private registry: FunctionRegistry;\n\n constructor(registry: FunctionRegistry, runtimeApi: string) {\n this.runtimeApi = runtimeApi;\n this.baseUrl = `http://${this.runtimeApi}/2018-06-01/runtime`;\n this.registry = registry;\n }\n\n public async waitForNextInvocation(): Promise<RuntimeEvent> {\n const response = await fetch(`${this.baseUrl}/invocation/next`);\n if (!response.ok) {\n throw new GetNextInvocationError(\n `Next invocation failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const requestId =\n response.headers.get(\"Lambda-Runtime-Aws-Request-Id\") || \"unknown\";\n const traceId = response.headers.get(\"Lambda-Runtime-Trace-Id\");\n\n // This is to allow the X-Ray SDK to trace across invocations\n if (traceId) {\n process.env[\"_X_AMZN_TRACE_ID\"] = traceId;\n }\n\n const text = await response.text();\n const parsedData = JSON.parse(text);\n\n const safeParseResult = RuntimeEventPayload.safeParse(parsedData);\n if (!safeParseResult.success) {\n // TODO: type error\n throw new Error(\"Failed to parse event into runtime event\");\n }\n\n const event = safeParseResult.data;\n return { requestId, event };\n }\n\n public getFunctionDefinitionByName(\n name: string,\n ): FunctionManifest<unknown> | null {\n return this.registry.getByName(name);\n }\n\n public executeFunction(\n event: RuntimeEventPayload,\n ): Promise<FunctionHandlerCallbackReturnValue> {\n return this.registry.execute(\n event.functionName,\n event.params ?? {},\n event.context,\n );\n }\n\n public async handleSuccess(\n requestId: string,\n result: FunctionHandlerCallbackReturnValue,\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/invocation/${encodeURIComponent(requestId)}/response`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(result),\n },\n );\n\n if (!response.ok) {\n throw new PostResultError(\n `Failed to post response: ${response.status} ${response.statusText}`,\n );\n }\n }\n\n public async handleFailure(requestId: string, error: unknown): Promise<void> {\n const runtimeError = formatRuntimeError(error);\n\n const response = await fetch(\n `${this.baseUrl}/invocation/${encodeURIComponent(requestId)}/error`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(runtimeError),\n },\n );\n\n if (!response.ok) {\n throw new PostErrorError(\n `Failed to post error: ${response.status} ${response.statusText}`,\n );\n }\n }\n}\n\nfunction formatRuntimeError(error: unknown): RuntimeError {\n if (error instanceof Error) {\n return {\n errorMessage: error.message,\n errorType: error.name,\n stackTrace: error.stack?.split(\"/n\") ?? [],\n };\n }\n\n let message = \"An unknown error occurred\";\n let type = \"UnknownError\";\n let stack = [] as string[];\n\n if (typeof error === \"string\") {\n return {\n errorMessage: error,\n errorType: type,\n stackTrace: stack,\n };\n }\n\n if (typeof error !== \"object\" || error === null) {\n return {\n errorMessage: String(error),\n errorType: type,\n stackTrace: stack,\n };\n }\n\n if (\"message\" in error && typeof error.message === \"string\") {\n message = error.message;\n }\n\n if (\"name\" in error && typeof error.name === \"string\") {\n type = error.name;\n }\n\n if (\n \"stack\" in error &&\n Array.isArray(error.stack) &&\n typeof error.stack[0] === \"string\"\n ) {\n stack = error.stack;\n }\n\n return {\n errorMessage: message,\n errorType: type,\n stackTrace: stack,\n };\n}\n","import type { IRuntimeClient } from \"./index.js\";\n\nexport async function waitForAndHandleInvocation(\n runtimeClient: IRuntimeClient,\n handleFatalError: (error: unknown) => void,\n) {\n // Any errors caught by this block will be considered fatal system errors\n try {\n const { requestId, event } = await runtimeClient.waitForNextInvocation();\n console.log(`Received invocation with requestId: ${requestId}`);\n const { functionName } = event;\n\n // Validate that the specified function is in the registry.\n // If not, throw a system error as this means we've set up the DB wrong\n // and that the system thinks that function is here when it's not.\n // NOTE: If the user finds a way to circumvent the SDK setup intentionally,\n // NOTE: we could see this error when the DB is correct.\n const functionDefinition =\n runtimeClient.getFunctionDefinitionByName(functionName);\n\n console.log(\n `Found definition for \"${functionName}\": ${JSON.stringify(functionDefinition)}`,\n );\n\n // TODO: type this error\n if (!functionDefinition) {\n throw new Error(`Function \"${functionName}\" not found in registry`);\n }\n\n // Any errors caught by this block will be considered user code errors\n let result;\n try {\n console.log(`Executing function: ${functionName}`);\n result = await runtimeClient.executeFunction(event);\n console.log(`Received result: ${JSON.stringify(result)}`);\n } catch (error: unknown) {\n console.error(\"Handler error:\", error);\n await runtimeClient.handleFailure(requestId, error);\n return; // This invocation is done - don't call handleSuccess\n }\n\n await runtimeClient.handleSuccess(requestId, result);\n console.log(`Function \"${functionName}\" completed successfully`);\n } catch (error: unknown) {\n console.error(\"Fatal error in runtime loop:\", error);\n handleFatalError(error);\n }\n}\n\nexport async function runInvocationLoop(\n runtimeClient: IRuntimeClient,\n handleProductionFailure: (error: unknown) => void,\n): Promise<void> {\n while (true) {\n await waitForAndHandleInvocation(runtimeClient, handleProductionFailure);\n }\n}\n","import { FunctionNotFoundInRegistryError } from \"../utils/errors.js\";\n\nimport type { FunctionInvocationContext } from \"../schemas/invocation.js\";\nimport type { FunctionManifest } from \"../types/definition.js\";\nimport type { FunctionHandlerCallbackReturnValue } from \"../types/handler.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nexport interface IFunctionRegistry {\n register<S extends JSONSchemaInput>(\n name: FunctionManifest<S>[\"name\"],\n handler: FunctionManifest<S>[\"handler\"],\n config: FunctionManifest<S>[\"config\"],\n ): void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- this would need to be generic based on the `register` call\n getByName(name: string): FunctionManifest<any> | null;\n\n execute(\n name: string,\n params: object,\n context: FunctionInvocationContext,\n ): Promise<FunctionHandlerCallbackReturnValue>;\n\n get size(): number;\n}\n\nexport class FunctionRegistry implements IFunctionRegistry {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- this would need to be generic based on the `register` call\n private _functions = new Map<string, FunctionManifest<any>>();\n\n register<S extends JSONSchemaInput>(\n name: FunctionManifest<S>[\"name\"],\n handler: FunctionManifest<S>[\"handler\"],\n config: FunctionManifest<S>[\"config\"],\n ) {\n this._functions.set(name, {\n name,\n handler,\n config,\n });\n }\n\n public getByName(name: string): FunctionManifest<unknown> | null {\n return this._functions.get(name) ?? null;\n }\n\n async execute(\n name: string,\n params: object,\n context: FunctionInvocationContext,\n ) {\n const foundDefinition = this._functions.get(name);\n if (!foundDefinition) {\n throw new FunctionNotFoundInRegistryError(\n `Couldn't find function with name \"${name}\" in registry`,\n );\n }\n\n const handlerResult = await foundDefinition.handler(context, params);\n\n // TODO: Remove when we have a better structured logging story\n console.log(\"handlerResult\", handlerResult);\n\n return handlerResult;\n }\n\n get size() {\n return this._functions.size;\n }\n}\n","export interface IEnvironmentManager {\n get environment(): string;\n get runtimeApi(): string;\n get phase(): string;\n}\n\nexport class EnvironmentManager {\n /// Whether we're running these locally or deployed (\"production\").\n /// Locally we are more forgiving on failures, and will change logging.\n private _environment: \"local\" | \"production\";\n\n /// The URL that is used to alert the runtime to the status of the invocation.\n /// Locally this will point to the URL of the dev server being run, in prod this\n /// will point to the runtime's internal endpoints.\n private _runtimeApi: string;\n\n /// We need to handle running a function differently than we handle\n /// deploying a function. The \"runtime\" phase is when we're trying to\n /// run a function by name (either locally or in prod). The \"build\"\n /// phase is when we're generating local manifest files to send to\n /// the Browserbase API. Defaults to runtime phase.\n private _phase: \"runtime\" | \"introspect\";\n\n constructor(processEnv: NodeJS.ProcessEnv) {\n this._environment = getOrDefault<typeof this._environment>(\n processEnv,\n \"NODE_ENV\",\n \"local\",\n );\n\n this._runtimeApi = getOrDefault<typeof this._runtimeApi>(\n processEnv,\n \"AWS_LAMBDA_RUNTIME_API\",\n \"127.0.0.1:14113\",\n );\n\n this._phase = getOrDefault<typeof this._phase>(\n processEnv,\n \"BB_FUNCTIONS_PHASE\",\n \"runtime\",\n );\n }\n\n get environment() {\n return this._environment;\n }\n\n get runtimeApi() {\n return this._runtimeApi;\n }\n\n get phase() {\n return this._phase;\n }\n}\n\nfunction getOrDefault<T>(env: NodeJS.ProcessEnv, key: string, dflt: T): T {\n const val = env[key];\n if (!val) {\n return dflt;\n }\n return val as T;\n}\n","import { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport z from \"zod\";\n\nimport type {\n FunctionManifest,\n PersistedFunctionManifest,\n} from \"../types/definition.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nexport function writeManifestToDisk<S extends JSONSchemaInput>(\n manifest: FunctionManifest<S>,\n manifestsDir: string,\n isFirstInvocation: boolean,\n) {\n if (isFirstInvocation) {\n // Clear manifests directory if it exists to remove stale menifests\n if (existsSync(manifestsDir)) {\n rmSync(manifestsDir, { recursive: true });\n }\n\n mkdirSync(manifestsDir, { recursive: true });\n }\n\n const persistedManifest = buildPersistedFunctionManifest(manifest);\n\n writeFileSync(\n join(manifestsDir, `${manifest.name}.json`),\n JSON.stringify(persistedManifest, null, 2),\n );\n}\n\nexport function buildPersistedFunctionManifest<S extends JSONSchemaInput>(\n manifest: FunctionManifest<S>,\n): PersistedFunctionManifest<S> {\n const { name, config } = manifest;\n const { parametersSchema, ...configWithoutSchema } = config;\n\n const processedConfig: PersistedFunctionManifest<S>[\"config\"] = {\n ...configWithoutSchema,\n };\n\n if (parametersSchema) {\n processedConfig.parametersSchema =\n buildPersistedJsonSchema(parametersSchema);\n }\n\n const processedManifest: PersistedFunctionManifest<S> = {\n name,\n config: processedConfig,\n };\n\n return processedManifest;\n}\n\nexport function buildPersistedJsonSchema(input: JSONSchemaInput): object {\n if (input instanceof z.ZodObject) {\n return z.toJSONSchema(input);\n }\n\n return {};\n}\n","import { join } from \"node:path\";\n\nimport type { FunctionConfiguration } from \"../types/definition.js\";\nimport type { FunctionHandler } from \"../types/handler.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nimport { writeManifestToDisk } from \"./helpers.js\";\n\n// Singleton imports\nimport { environmentManager, functionsRegistry } from \"../index.js\";\n\n/// TODO: Write good documentation here\nexport function defineFn<S extends JSONSchemaInput = unknown>(\n name: string,\n handler: FunctionHandler<S>,\n config: FunctionConfiguration<S> = {},\n): void {\n functionsRegistry.register(name, handler, config);\n\n if (\n // The CLI needs \"local\" to know how to create sessions with\n // non-default configurations during the local dev flow\n environmentManager.phase === \"introspect\" ||\n environmentManager.environment === \"local\"\n ) {\n const manifestsDir = join(\n process.cwd(),\n \".browserbase\",\n \"functions\",\n \"manifests\",\n );\n\n const isFirstInvocation = functionsRegistry.size === 1;\n\n writeManifestToDisk(\n { name, handler, config },\n manifestsDir,\n isFirstInvocation,\n );\n }\n}\n","import { RuntimeClient } from \"./runtime/index.js\";\nimport { runInvocationLoop } from \"./runtime/loop.js\";\nimport { FunctionRegistry } from \"./runtime/registry.js\";\nimport { EnvironmentManager } from \"./utils/env.js\";\n\nexport { defineFn } from \"./define/index.js\";\n\nexport const environmentManager = new EnvironmentManager(process.env);\nexport const functionsRegistry = new FunctionRegistry();\nexport const runtimeClient = new RuntimeClient(\n functionsRegistry,\n environmentManager.runtimeApi,\n);\n\nfunction handleInvocationLoopFailure(error: unknown): void {\n console.error(\"Received fatal error from invocation loop\", error);\n process.exit(1);\n}\n// We only want to listen for invocations iff we're in the \"runtime\" phase\nif (environmentManager.phase === \"runtime\") {\n runInvocationLoop(runtimeClient, handleInvocationLoopFailure).catch(\n (error: unknown) => {\n console.error(\"Fatal runtime error:\", error);\n process.exit(1);\n },\n );\n}\n"]}
@@ -0,0 +1,112 @@
1
+ import * as z from 'zod';
2
+ import z__default from 'zod';
3
+ import Browserbase from '@browserbasehq/sdk';
4
+
5
+ declare const FunctionInvocationContext: z__default.ZodObject<{
6
+ session: z__default.ZodObject<{
7
+ id: z__default.ZodString;
8
+ connectUrl: z__default.ZodString;
9
+ }, z__default.z.core.$strip>;
10
+ }, z__default.z.core.$strip>;
11
+ type FunctionInvocationContext = z__default.infer<typeof FunctionInvocationContext>;
12
+
13
+ type JSONValue = string | number | boolean | null | JSONValue[] | {
14
+ [k: string]: JSONValue;
15
+ };
16
+ type JSONObject = {
17
+ [k: string]: JSONValue;
18
+ };
19
+
20
+ type JSONSchemaInput = z.ZodObject | unknown | void;
21
+
22
+ type FunctionHandler<S extends JSONSchemaInput> = (context: FunctionInvocationContext, params: S extends JSONSchemaInput ? z__default.infer<S> : unknown) => Promise<FunctionHandlerCallbackReturnValue> | FunctionHandlerCallbackReturnValue;
23
+ type FunctionHandlerCallbackReturnValue = JSONObject | void;
24
+
25
+ interface FunctionManifest<S extends JSONSchemaInput> {
26
+ name: string;
27
+ handler: FunctionHandler<S>;
28
+ config: FunctionConfiguration<S>;
29
+ }
30
+ interface FunctionConfiguration<S extends JSONSchemaInput> {
31
+ sessionConfig?: SessionConfiguration;
32
+ parametersSchema?: S;
33
+ }
34
+ interface SessionConfiguration extends Omit<Browserbase.SessionCreateParams, "projectId"> {
35
+ }
36
+
37
+ interface IFunctionRegistry {
38
+ register<S extends JSONSchemaInput>(name: FunctionManifest<S>["name"], handler: FunctionManifest<S>["handler"], config: FunctionManifest<S>["config"]): void;
39
+ getByName(name: string): FunctionManifest<any> | null;
40
+ execute(name: string, params: object, context: FunctionInvocationContext): Promise<FunctionHandlerCallbackReturnValue>;
41
+ get size(): number;
42
+ }
43
+ declare class FunctionRegistry implements IFunctionRegistry {
44
+ private _functions;
45
+ register<S extends JSONSchemaInput>(name: FunctionManifest<S>["name"], handler: FunctionManifest<S>["handler"], config: FunctionManifest<S>["config"]): void;
46
+ getByName(name: string): FunctionManifest<unknown> | null;
47
+ execute(name: string, params: object, context: FunctionInvocationContext): Promise<FunctionHandlerCallbackReturnValue>;
48
+ get size(): number;
49
+ }
50
+
51
+ declare const RuntimeEventPayload: z__default.ZodObject<{
52
+ functionName: z__default.ZodString;
53
+ params: z__default.ZodObject<{}, z__default.z.core.$loose>;
54
+ context: z__default.ZodObject<{
55
+ session: z__default.ZodObject<{
56
+ id: z__default.ZodString;
57
+ connectUrl: z__default.ZodString;
58
+ }, z__default.z.core.$strip>;
59
+ }, z__default.z.core.$strip>;
60
+ }, z__default.z.core.$strip>;
61
+ type RuntimeEventPayload = z__default.infer<typeof RuntimeEventPayload>;
62
+ declare const RuntimeEvent: z__default.ZodObject<{
63
+ requestId: z__default.ZodString;
64
+ event: z__default.ZodObject<{
65
+ functionName: z__default.ZodString;
66
+ params: z__default.ZodObject<{}, z__default.z.core.$loose>;
67
+ context: z__default.ZodObject<{
68
+ session: z__default.ZodObject<{
69
+ id: z__default.ZodString;
70
+ connectUrl: z__default.ZodString;
71
+ }, z__default.z.core.$strip>;
72
+ }, z__default.z.core.$strip>;
73
+ }, z__default.z.core.$strip>;
74
+ }, z__default.z.core.$strip>;
75
+ type RuntimeEvent = z__default.infer<typeof RuntimeEvent>;
76
+
77
+ interface IRuntimeClient {
78
+ waitForNextInvocation(): Promise<RuntimeEvent>;
79
+ getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;
80
+ executeFunction(event: RuntimeEventPayload): Promise<FunctionHandlerCallbackReturnValue>;
81
+ handleSuccess(requestId: string, result: FunctionHandlerCallbackReturnValue): Promise<void>;
82
+ handleFailure(requestId: string, error: unknown): Promise<void>;
83
+ }
84
+ declare class RuntimeClient implements IRuntimeClient {
85
+ private runtimeApi;
86
+ private baseUrl;
87
+ private registry;
88
+ constructor(registry: FunctionRegistry, runtimeApi: string);
89
+ waitForNextInvocation(): Promise<RuntimeEvent>;
90
+ getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;
91
+ executeFunction(event: RuntimeEventPayload): Promise<FunctionHandlerCallbackReturnValue>;
92
+ handleSuccess(requestId: string, result: FunctionHandlerCallbackReturnValue): Promise<void>;
93
+ handleFailure(requestId: string, error: unknown): Promise<void>;
94
+ }
95
+
96
+ declare class EnvironmentManager {
97
+ private _environment;
98
+ private _runtimeApi;
99
+ private _phase;
100
+ constructor(processEnv: NodeJS.ProcessEnv);
101
+ get environment(): "local" | "production";
102
+ get runtimeApi(): string;
103
+ get phase(): "runtime" | "introspect";
104
+ }
105
+
106
+ declare function defineFn<S extends JSONSchemaInput = unknown>(name: string, handler: FunctionHandler<S>, config?: FunctionConfiguration<S>): void;
107
+
108
+ declare const environmentManager: EnvironmentManager;
109
+ declare const functionsRegistry: FunctionRegistry;
110
+ declare const runtimeClient: RuntimeClient;
111
+
112
+ export { defineFn, environmentManager, functionsRegistry, runtimeClient };
@@ -0,0 +1,112 @@
1
+ import * as z from 'zod';
2
+ import z__default from 'zod';
3
+ import Browserbase from '@browserbasehq/sdk';
4
+
5
+ declare const FunctionInvocationContext: z__default.ZodObject<{
6
+ session: z__default.ZodObject<{
7
+ id: z__default.ZodString;
8
+ connectUrl: z__default.ZodString;
9
+ }, z__default.z.core.$strip>;
10
+ }, z__default.z.core.$strip>;
11
+ type FunctionInvocationContext = z__default.infer<typeof FunctionInvocationContext>;
12
+
13
+ type JSONValue = string | number | boolean | null | JSONValue[] | {
14
+ [k: string]: JSONValue;
15
+ };
16
+ type JSONObject = {
17
+ [k: string]: JSONValue;
18
+ };
19
+
20
+ type JSONSchemaInput = z.ZodObject | unknown | void;
21
+
22
+ type FunctionHandler<S extends JSONSchemaInput> = (context: FunctionInvocationContext, params: S extends JSONSchemaInput ? z__default.infer<S> : unknown) => Promise<FunctionHandlerCallbackReturnValue> | FunctionHandlerCallbackReturnValue;
23
+ type FunctionHandlerCallbackReturnValue = JSONObject | void;
24
+
25
+ interface FunctionManifest<S extends JSONSchemaInput> {
26
+ name: string;
27
+ handler: FunctionHandler<S>;
28
+ config: FunctionConfiguration<S>;
29
+ }
30
+ interface FunctionConfiguration<S extends JSONSchemaInput> {
31
+ sessionConfig?: SessionConfiguration;
32
+ parametersSchema?: S;
33
+ }
34
+ interface SessionConfiguration extends Omit<Browserbase.SessionCreateParams, "projectId"> {
35
+ }
36
+
37
+ interface IFunctionRegistry {
38
+ register<S extends JSONSchemaInput>(name: FunctionManifest<S>["name"], handler: FunctionManifest<S>["handler"], config: FunctionManifest<S>["config"]): void;
39
+ getByName(name: string): FunctionManifest<any> | null;
40
+ execute(name: string, params: object, context: FunctionInvocationContext): Promise<FunctionHandlerCallbackReturnValue>;
41
+ get size(): number;
42
+ }
43
+ declare class FunctionRegistry implements IFunctionRegistry {
44
+ private _functions;
45
+ register<S extends JSONSchemaInput>(name: FunctionManifest<S>["name"], handler: FunctionManifest<S>["handler"], config: FunctionManifest<S>["config"]): void;
46
+ getByName(name: string): FunctionManifest<unknown> | null;
47
+ execute(name: string, params: object, context: FunctionInvocationContext): Promise<FunctionHandlerCallbackReturnValue>;
48
+ get size(): number;
49
+ }
50
+
51
+ declare const RuntimeEventPayload: z__default.ZodObject<{
52
+ functionName: z__default.ZodString;
53
+ params: z__default.ZodObject<{}, z__default.z.core.$loose>;
54
+ context: z__default.ZodObject<{
55
+ session: z__default.ZodObject<{
56
+ id: z__default.ZodString;
57
+ connectUrl: z__default.ZodString;
58
+ }, z__default.z.core.$strip>;
59
+ }, z__default.z.core.$strip>;
60
+ }, z__default.z.core.$strip>;
61
+ type RuntimeEventPayload = z__default.infer<typeof RuntimeEventPayload>;
62
+ declare const RuntimeEvent: z__default.ZodObject<{
63
+ requestId: z__default.ZodString;
64
+ event: z__default.ZodObject<{
65
+ functionName: z__default.ZodString;
66
+ params: z__default.ZodObject<{}, z__default.z.core.$loose>;
67
+ context: z__default.ZodObject<{
68
+ session: z__default.ZodObject<{
69
+ id: z__default.ZodString;
70
+ connectUrl: z__default.ZodString;
71
+ }, z__default.z.core.$strip>;
72
+ }, z__default.z.core.$strip>;
73
+ }, z__default.z.core.$strip>;
74
+ }, z__default.z.core.$strip>;
75
+ type RuntimeEvent = z__default.infer<typeof RuntimeEvent>;
76
+
77
+ interface IRuntimeClient {
78
+ waitForNextInvocation(): Promise<RuntimeEvent>;
79
+ getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;
80
+ executeFunction(event: RuntimeEventPayload): Promise<FunctionHandlerCallbackReturnValue>;
81
+ handleSuccess(requestId: string, result: FunctionHandlerCallbackReturnValue): Promise<void>;
82
+ handleFailure(requestId: string, error: unknown): Promise<void>;
83
+ }
84
+ declare class RuntimeClient implements IRuntimeClient {
85
+ private runtimeApi;
86
+ private baseUrl;
87
+ private registry;
88
+ constructor(registry: FunctionRegistry, runtimeApi: string);
89
+ waitForNextInvocation(): Promise<RuntimeEvent>;
90
+ getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;
91
+ executeFunction(event: RuntimeEventPayload): Promise<FunctionHandlerCallbackReturnValue>;
92
+ handleSuccess(requestId: string, result: FunctionHandlerCallbackReturnValue): Promise<void>;
93
+ handleFailure(requestId: string, error: unknown): Promise<void>;
94
+ }
95
+
96
+ declare class EnvironmentManager {
97
+ private _environment;
98
+ private _runtimeApi;
99
+ private _phase;
100
+ constructor(processEnv: NodeJS.ProcessEnv);
101
+ get environment(): "local" | "production";
102
+ get runtimeApi(): string;
103
+ get phase(): "runtime" | "introspect";
104
+ }
105
+
106
+ declare function defineFn<S extends JSONSchemaInput = unknown>(name: string, handler: FunctionHandler<S>, config?: FunctionConfiguration<S>): void;
107
+
108
+ declare const environmentManager: EnvironmentManager;
109
+ declare const functionsRegistry: FunctionRegistry;
110
+ declare const runtimeClient: RuntimeClient;
111
+
112
+ export { defineFn, environmentManager, functionsRegistry, runtimeClient };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import a from 'zod';
2
+ import { join } from 'path';
3
+ import { existsSync, rmSync, mkdirSync, writeFileSync } from 'fs';
4
+
5
+ var b=Object.defineProperty;var M=(n,t,e)=>t in n?b(n,t,{enumerable:true,configurable:true,writable:true,value:e}):n[t]=e;var s=(n,t,e)=>M(n,typeof t!="symbol"?t+"":t,e);var m=class extends Error{constructor(t){super(t);}},f=class extends Error{constructor(t){super(t);}},l=class extends Error{constructor(t){super(t);}},d=class extends Error{constructor(t){super(t);}};var N=a.object({id:a.string(),connectUrl:a.string()}),w=a.object({session:N});var x=a.object({functionName:a.string().min(1),params:a.looseObject({}),context:w});a.object({requestId:a.string().min(1),event:x});a.object({errorMessage:a.string().min(1),errorType:a.string().min(1),stackTrace:a.array(a.string().min(1))});var y=class{constructor(t,e){s(this,"runtimeApi");s(this,"baseUrl");s(this,"registry");this.runtimeApi=e,this.baseUrl=`http://${this.runtimeApi}/2018-06-01/runtime`,this.registry=t;}async waitForNextInvocation(){let t=await fetch(`${this.baseUrl}/invocation/next`);if(!t.ok)throw new f(`Next invocation failed: ${t.status} ${t.statusText}`);let e=t.headers.get("Lambda-Runtime-Aws-Request-Id")||"unknown",o=t.headers.get("Lambda-Runtime-Trace-Id");o&&(process.env._X_AMZN_TRACE_ID=o);let i=await t.text(),r=JSON.parse(i),c=x.safeParse(r);if(!c.success)throw new Error("Failed to parse event into runtime event");let p=c.data;return {requestId:e,event:p}}getFunctionDefinitionByName(t){return this.registry.getByName(t)}executeFunction(t){return this.registry.execute(t.functionName,t.params??{},t.context)}async handleSuccess(t,e){let o=await fetch(`${this.baseUrl}/invocation/${encodeURIComponent(t)}/response`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)});if(!o.ok)throw new l(`Failed to post response: ${o.status} ${o.statusText}`)}async handleFailure(t,e){let o=E(e),i=await fetch(`${this.baseUrl}/invocation/${encodeURIComponent(t)}/error`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o)});if(!i.ok)throw new d(`Failed to post error: ${i.status} ${i.statusText}`)}};function E(n){if(n instanceof Error)return {errorMessage:n.message,errorType:n.name,stackTrace:n.stack?.split("/n")??[]};let t="An unknown error occurred",e="UnknownError",o=[];return typeof n=="string"?{errorMessage:n,errorType:e,stackTrace:o}:typeof n!="object"||n===null?{errorMessage:String(n),errorType:e,stackTrace:o}:("message"in n&&typeof n.message=="string"&&(t=n.message),"name"in n&&typeof n.name=="string"&&(e=n.name),"stack"in n&&Array.isArray(n.stack)&&typeof n.stack[0]=="string"&&(o=n.stack),{errorMessage:t,errorType:e,stackTrace:o})}async function P(n,t){try{let{requestId:e,event:o}=await n.waitForNextInvocation();console.log(`Received invocation with requestId: ${e}`);let{functionName:i}=o,r=n.getFunctionDefinitionByName(i);if(console.log(`Found definition for "${i}": ${JSON.stringify(r)}`),!r)throw new Error(`Function "${i}" not found in registry`);let c;try{console.log(`Executing function: ${i}`),c=await n.executeFunction(o),console.log(`Received result: ${JSON.stringify(c)}`);}catch(p){console.error("Handler error:",p),await n.handleFailure(e,p);return}await n.handleSuccess(e,c),console.log(`Function "${i}" completed successfully`);}catch(e){console.error("Fatal error in runtime loop:",e),t(e);}}async function I(n,t){for(;;)await P(n,t);}var h=class{constructor(){s(this,"_functions",new Map);}register(t,e,o){this._functions.set(t,{name:t,handler:e,config:o});}getByName(t){return this._functions.get(t)??null}async execute(t,e,o){let i=this._functions.get(t);if(!i)throw new m(`Couldn't find function with name "${t}" in registry`);let r=await i.handler(o,e);return console.log("handlerResult",r),r}get size(){return this._functions.size}};var v=class{constructor(t){s(this,"_environment");s(this,"_runtimeApi");s(this,"_phase");this._environment=S(t,"NODE_ENV","local"),this._runtimeApi=S(t,"AWS_LAMBDA_RUNTIME_API","127.0.0.1:14113"),this._phase=S(t,"BB_FUNCTIONS_PHASE","runtime");}get environment(){return this._environment}get runtimeApi(){return this._runtimeApi}get phase(){return this._phase}};function S(n,t,e){let o=n[t];return o||e}function k(n,t,e){e&&(existsSync(t)&&rmSync(t,{recursive:true}),mkdirSync(t,{recursive:true}));let o=A(n);writeFileSync(join(t,`${n.name}.json`),JSON.stringify(o,null,2));}function A(n){let{name:t,config:e}=n,{parametersSchema:o,...i}=e,r={...i};return o&&(r.parametersSchema=$(o)),{name:t,config:r}}function $(n){return n instanceof a.ZodObject?a.toJSONSchema(n):{}}function D(n,t,e={}){if(F.register(n,t,e),u.phase==="introspect"||u.environment==="local"){let o=join(process.cwd(),".browserbase","functions","manifests"),i=F.size===1;k({name:n,config:e},o,i);}}var u=new v(process.env),F=new h,z=new y(F,u.runtimeApi);function H(n){console.error("Received fatal error from invocation loop",n),process.exit(1);}u.phase==="runtime"&&I(z,H).catch(n=>{console.error("Fatal runtime error:",n),process.exit(1);});
6
+
7
+ export { D as defineFn, u as environmentManager, F as functionsRegistry, z as runtimeClient };
8
+ //# sourceMappingURL=index.js.map
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/errors.ts","../src/schemas/invocation.ts","../src/schemas/events.ts","../src/runtime/index.ts","../src/runtime/loop.ts","../src/runtime/registry.ts","../src/utils/env.ts","../src/define/helpers.ts","../src/define/index.ts","../src/index.ts"],"names":["FunctionNotFoundInRegistryError","message","GetNextInvocationError","PostResultError","PostErrorError","FunctionInvocationContextSessionDetails","z","FunctionInvocationContext","RuntimeEventPayload","RuntimeClient","registry","runtimeApi","__publicField","response","requestId","traceId","text","parsedData","safeParseResult","event","name","result","error","runtimeError","formatRuntimeError","type","stack","waitForAndHandleInvocation","runtimeClient","handleFatalError","functionName","functionDefinition","runInvocationLoop","handleProductionFailure","FunctionRegistry","handler","config","params","context","foundDefinition","handlerResult","EnvironmentManager","processEnv","getOrDefault","env","key","dflt","val","writeManifestToDisk","manifest","manifestsDir","isFirstInvocation","existsSync","rmSync","mkdirSync","persistedManifest","buildPersistedFunctionManifest","writeFileSync","join","parametersSchema","configWithoutSchema","processedConfig","buildPersistedJsonSchema","input","defineFn","functionsRegistry","environmentManager","handleInvocationLoopFailure"],"mappings":"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","file":"index.js","sourcesContent":["export class FunctionNotFoundInRegistryError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class GetNextInvocationError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class PostResultError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class PostErrorError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n","import z from \"zod\";\n\nexport const FunctionInvocationContextSessionDetails = z.object({\n id: z.string(),\n connectUrl: z.string(),\n});\n\nexport type FunctionInvocationContextSessionDetails = z.infer<\n typeof FunctionInvocationContextSessionDetails\n>;\n\nexport const FunctionInvocationContext = z.object({\n session: FunctionInvocationContextSessionDetails,\n});\n\nexport type FunctionInvocationContext = z.infer<\n typeof FunctionInvocationContext\n>;\n","import z from \"zod\";\nimport { FunctionInvocationContext } from \"./invocation.js\";\n\nexport const RuntimeEventPayload = z.object({\n functionName: z.string().min(1),\n params: z.looseObject({}), // Allow passthrough of unknown (all) keys\n context: FunctionInvocationContext,\n});\n\nexport type RuntimeEventPayload = z.infer<typeof RuntimeEventPayload>;\n\nexport const RuntimeEvent = z.object({\n requestId: z.string().min(1),\n event: RuntimeEventPayload,\n});\n\nexport type RuntimeEvent = z.infer<typeof RuntimeEvent>;\n\nexport const RuntimeError = z.object({\n errorMessage: z.string().min(1),\n errorType: z.string().min(1),\n stackTrace: z.array(z.string().min(1)),\n});\n\nexport type RuntimeError = z.infer<typeof RuntimeError>;\n","import type { FunctionRegistry } from \"../runtime/registry.js\";\nimport {\n GetNextInvocationError,\n PostErrorError,\n PostResultError,\n} from \"../utils/errors.js\";\nimport {\n RuntimeError,\n RuntimeEvent,\n RuntimeEventPayload,\n} from \"../schemas/events.js\";\nimport type { FunctionManifest } from \"../types/definition.js\";\nimport type { FunctionHandlerCallbackReturnValue } from \"../types/handler.js\";\n\nexport interface IRuntimeClient {\n waitForNextInvocation(): Promise<RuntimeEvent>;\n getFunctionDefinitionByName(name: string): FunctionManifest<unknown> | null;\n\n executeFunction(\n event: RuntimeEventPayload,\n ): Promise<FunctionHandlerCallbackReturnValue>;\n\n handleSuccess(\n requestId: string,\n result: FunctionHandlerCallbackReturnValue,\n ): Promise<void>;\n\n handleFailure(requestId: string, error: unknown): Promise<void>;\n}\n\nexport class RuntimeClient implements IRuntimeClient {\n private runtimeApi: string;\n private baseUrl: string;\n private registry: FunctionRegistry;\n\n constructor(registry: FunctionRegistry, runtimeApi: string) {\n this.runtimeApi = runtimeApi;\n this.baseUrl = `http://${this.runtimeApi}/2018-06-01/runtime`;\n this.registry = registry;\n }\n\n public async waitForNextInvocation(): Promise<RuntimeEvent> {\n const response = await fetch(`${this.baseUrl}/invocation/next`);\n if (!response.ok) {\n throw new GetNextInvocationError(\n `Next invocation failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const requestId =\n response.headers.get(\"Lambda-Runtime-Aws-Request-Id\") || \"unknown\";\n const traceId = response.headers.get(\"Lambda-Runtime-Trace-Id\");\n\n // This is to allow the X-Ray SDK to trace across invocations\n if (traceId) {\n process.env[\"_X_AMZN_TRACE_ID\"] = traceId;\n }\n\n const text = await response.text();\n const parsedData = JSON.parse(text);\n\n const safeParseResult = RuntimeEventPayload.safeParse(parsedData);\n if (!safeParseResult.success) {\n // TODO: type error\n throw new Error(\"Failed to parse event into runtime event\");\n }\n\n const event = safeParseResult.data;\n return { requestId, event };\n }\n\n public getFunctionDefinitionByName(\n name: string,\n ): FunctionManifest<unknown> | null {\n return this.registry.getByName(name);\n }\n\n public executeFunction(\n event: RuntimeEventPayload,\n ): Promise<FunctionHandlerCallbackReturnValue> {\n return this.registry.execute(\n event.functionName,\n event.params ?? {},\n event.context,\n );\n }\n\n public async handleSuccess(\n requestId: string,\n result: FunctionHandlerCallbackReturnValue,\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/invocation/${encodeURIComponent(requestId)}/response`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(result),\n },\n );\n\n if (!response.ok) {\n throw new PostResultError(\n `Failed to post response: ${response.status} ${response.statusText}`,\n );\n }\n }\n\n public async handleFailure(requestId: string, error: unknown): Promise<void> {\n const runtimeError = formatRuntimeError(error);\n\n const response = await fetch(\n `${this.baseUrl}/invocation/${encodeURIComponent(requestId)}/error`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(runtimeError),\n },\n );\n\n if (!response.ok) {\n throw new PostErrorError(\n `Failed to post error: ${response.status} ${response.statusText}`,\n );\n }\n }\n}\n\nfunction formatRuntimeError(error: unknown): RuntimeError {\n if (error instanceof Error) {\n return {\n errorMessage: error.message,\n errorType: error.name,\n stackTrace: error.stack?.split(\"/n\") ?? [],\n };\n }\n\n let message = \"An unknown error occurred\";\n let type = \"UnknownError\";\n let stack = [] as string[];\n\n if (typeof error === \"string\") {\n return {\n errorMessage: error,\n errorType: type,\n stackTrace: stack,\n };\n }\n\n if (typeof error !== \"object\" || error === null) {\n return {\n errorMessage: String(error),\n errorType: type,\n stackTrace: stack,\n };\n }\n\n if (\"message\" in error && typeof error.message === \"string\") {\n message = error.message;\n }\n\n if (\"name\" in error && typeof error.name === \"string\") {\n type = error.name;\n }\n\n if (\n \"stack\" in error &&\n Array.isArray(error.stack) &&\n typeof error.stack[0] === \"string\"\n ) {\n stack = error.stack;\n }\n\n return {\n errorMessage: message,\n errorType: type,\n stackTrace: stack,\n };\n}\n","import type { IRuntimeClient } from \"./index.js\";\n\nexport async function waitForAndHandleInvocation(\n runtimeClient: IRuntimeClient,\n handleFatalError: (error: unknown) => void,\n) {\n // Any errors caught by this block will be considered fatal system errors\n try {\n const { requestId, event } = await runtimeClient.waitForNextInvocation();\n console.log(`Received invocation with requestId: ${requestId}`);\n const { functionName } = event;\n\n // Validate that the specified function is in the registry.\n // If not, throw a system error as this means we've set up the DB wrong\n // and that the system thinks that function is here when it's not.\n // NOTE: If the user finds a way to circumvent the SDK setup intentionally,\n // NOTE: we could see this error when the DB is correct.\n const functionDefinition =\n runtimeClient.getFunctionDefinitionByName(functionName);\n\n console.log(\n `Found definition for \"${functionName}\": ${JSON.stringify(functionDefinition)}`,\n );\n\n // TODO: type this error\n if (!functionDefinition) {\n throw new Error(`Function \"${functionName}\" not found in registry`);\n }\n\n // Any errors caught by this block will be considered user code errors\n let result;\n try {\n console.log(`Executing function: ${functionName}`);\n result = await runtimeClient.executeFunction(event);\n console.log(`Received result: ${JSON.stringify(result)}`);\n } catch (error: unknown) {\n console.error(\"Handler error:\", error);\n await runtimeClient.handleFailure(requestId, error);\n return; // This invocation is done - don't call handleSuccess\n }\n\n await runtimeClient.handleSuccess(requestId, result);\n console.log(`Function \"${functionName}\" completed successfully`);\n } catch (error: unknown) {\n console.error(\"Fatal error in runtime loop:\", error);\n handleFatalError(error);\n }\n}\n\nexport async function runInvocationLoop(\n runtimeClient: IRuntimeClient,\n handleProductionFailure: (error: unknown) => void,\n): Promise<void> {\n while (true) {\n await waitForAndHandleInvocation(runtimeClient, handleProductionFailure);\n }\n}\n","import { FunctionNotFoundInRegistryError } from \"../utils/errors.js\";\n\nimport type { FunctionInvocationContext } from \"../schemas/invocation.js\";\nimport type { FunctionManifest } from \"../types/definition.js\";\nimport type { FunctionHandlerCallbackReturnValue } from \"../types/handler.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nexport interface IFunctionRegistry {\n register<S extends JSONSchemaInput>(\n name: FunctionManifest<S>[\"name\"],\n handler: FunctionManifest<S>[\"handler\"],\n config: FunctionManifest<S>[\"config\"],\n ): void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- this would need to be generic based on the `register` call\n getByName(name: string): FunctionManifest<any> | null;\n\n execute(\n name: string,\n params: object,\n context: FunctionInvocationContext,\n ): Promise<FunctionHandlerCallbackReturnValue>;\n\n get size(): number;\n}\n\nexport class FunctionRegistry implements IFunctionRegistry {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- this would need to be generic based on the `register` call\n private _functions = new Map<string, FunctionManifest<any>>();\n\n register<S extends JSONSchemaInput>(\n name: FunctionManifest<S>[\"name\"],\n handler: FunctionManifest<S>[\"handler\"],\n config: FunctionManifest<S>[\"config\"],\n ) {\n this._functions.set(name, {\n name,\n handler,\n config,\n });\n }\n\n public getByName(name: string): FunctionManifest<unknown> | null {\n return this._functions.get(name) ?? null;\n }\n\n async execute(\n name: string,\n params: object,\n context: FunctionInvocationContext,\n ) {\n const foundDefinition = this._functions.get(name);\n if (!foundDefinition) {\n throw new FunctionNotFoundInRegistryError(\n `Couldn't find function with name \"${name}\" in registry`,\n );\n }\n\n const handlerResult = await foundDefinition.handler(context, params);\n\n // TODO: Remove when we have a better structured logging story\n console.log(\"handlerResult\", handlerResult);\n\n return handlerResult;\n }\n\n get size() {\n return this._functions.size;\n }\n}\n","export interface IEnvironmentManager {\n get environment(): string;\n get runtimeApi(): string;\n get phase(): string;\n}\n\nexport class EnvironmentManager {\n /// Whether we're running these locally or deployed (\"production\").\n /// Locally we are more forgiving on failures, and will change logging.\n private _environment: \"local\" | \"production\";\n\n /// The URL that is used to alert the runtime to the status of the invocation.\n /// Locally this will point to the URL of the dev server being run, in prod this\n /// will point to the runtime's internal endpoints.\n private _runtimeApi: string;\n\n /// We need to handle running a function differently than we handle\n /// deploying a function. The \"runtime\" phase is when we're trying to\n /// run a function by name (either locally or in prod). The \"build\"\n /// phase is when we're generating local manifest files to send to\n /// the Browserbase API. Defaults to runtime phase.\n private _phase: \"runtime\" | \"introspect\";\n\n constructor(processEnv: NodeJS.ProcessEnv) {\n this._environment = getOrDefault<typeof this._environment>(\n processEnv,\n \"NODE_ENV\",\n \"local\",\n );\n\n this._runtimeApi = getOrDefault<typeof this._runtimeApi>(\n processEnv,\n \"AWS_LAMBDA_RUNTIME_API\",\n \"127.0.0.1:14113\",\n );\n\n this._phase = getOrDefault<typeof this._phase>(\n processEnv,\n \"BB_FUNCTIONS_PHASE\",\n \"runtime\",\n );\n }\n\n get environment() {\n return this._environment;\n }\n\n get runtimeApi() {\n return this._runtimeApi;\n }\n\n get phase() {\n return this._phase;\n }\n}\n\nfunction getOrDefault<T>(env: NodeJS.ProcessEnv, key: string, dflt: T): T {\n const val = env[key];\n if (!val) {\n return dflt;\n }\n return val as T;\n}\n","import { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport z from \"zod\";\n\nimport type {\n FunctionManifest,\n PersistedFunctionManifest,\n} from \"../types/definition.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nexport function writeManifestToDisk<S extends JSONSchemaInput>(\n manifest: FunctionManifest<S>,\n manifestsDir: string,\n isFirstInvocation: boolean,\n) {\n if (isFirstInvocation) {\n // Clear manifests directory if it exists to remove stale menifests\n if (existsSync(manifestsDir)) {\n rmSync(manifestsDir, { recursive: true });\n }\n\n mkdirSync(manifestsDir, { recursive: true });\n }\n\n const persistedManifest = buildPersistedFunctionManifest(manifest);\n\n writeFileSync(\n join(manifestsDir, `${manifest.name}.json`),\n JSON.stringify(persistedManifest, null, 2),\n );\n}\n\nexport function buildPersistedFunctionManifest<S extends JSONSchemaInput>(\n manifest: FunctionManifest<S>,\n): PersistedFunctionManifest<S> {\n const { name, config } = manifest;\n const { parametersSchema, ...configWithoutSchema } = config;\n\n const processedConfig: PersistedFunctionManifest<S>[\"config\"] = {\n ...configWithoutSchema,\n };\n\n if (parametersSchema) {\n processedConfig.parametersSchema =\n buildPersistedJsonSchema(parametersSchema);\n }\n\n const processedManifest: PersistedFunctionManifest<S> = {\n name,\n config: processedConfig,\n };\n\n return processedManifest;\n}\n\nexport function buildPersistedJsonSchema(input: JSONSchemaInput): object {\n if (input instanceof z.ZodObject) {\n return z.toJSONSchema(input);\n }\n\n return {};\n}\n","import { join } from \"node:path\";\n\nimport type { FunctionConfiguration } from \"../types/definition.js\";\nimport type { FunctionHandler } from \"../types/handler.js\";\nimport type { JSONSchemaInput } from \"../types/schema.js\";\n\nimport { writeManifestToDisk } from \"./helpers.js\";\n\n// Singleton imports\nimport { environmentManager, functionsRegistry } from \"../index.js\";\n\n/// TODO: Write good documentation here\nexport function defineFn<S extends JSONSchemaInput = unknown>(\n name: string,\n handler: FunctionHandler<S>,\n config: FunctionConfiguration<S> = {},\n): void {\n functionsRegistry.register(name, handler, config);\n\n if (\n // The CLI needs \"local\" to know how to create sessions with\n // non-default configurations during the local dev flow\n environmentManager.phase === \"introspect\" ||\n environmentManager.environment === \"local\"\n ) {\n const manifestsDir = join(\n process.cwd(),\n \".browserbase\",\n \"functions\",\n \"manifests\",\n );\n\n const isFirstInvocation = functionsRegistry.size === 1;\n\n writeManifestToDisk(\n { name, handler, config },\n manifestsDir,\n isFirstInvocation,\n );\n }\n}\n","import { RuntimeClient } from \"./runtime/index.js\";\nimport { runInvocationLoop } from \"./runtime/loop.js\";\nimport { FunctionRegistry } from \"./runtime/registry.js\";\nimport { EnvironmentManager } from \"./utils/env.js\";\n\nexport { defineFn } from \"./define/index.js\";\n\nexport const environmentManager = new EnvironmentManager(process.env);\nexport const functionsRegistry = new FunctionRegistry();\nexport const runtimeClient = new RuntimeClient(\n functionsRegistry,\n environmentManager.runtimeApi,\n);\n\nfunction handleInvocationLoopFailure(error: unknown): void {\n console.error(\"Received fatal error from invocation loop\", error);\n process.exit(1);\n}\n// We only want to listen for invocations iff we're in the \"runtime\" phase\nif (environmentManager.phase === \"runtime\") {\n runInvocationLoop(runtimeClient, handleInvocationLoopFailure).catch(\n (error: unknown) => {\n console.error(\"Fatal runtime error:\", error);\n process.exit(1);\n },\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@browserbasehq/sdk-functions",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "require": "./dist/index.cjs",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "main": "./dist/index.cjs",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "bin": {
17
+ "bb": "./dist/cli.js"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "sideEffects": [
23
+ "./dist/index.js"
24
+ ],
25
+ "scripts": {
26
+ "build": "$npm_execpath run lint && rm -rf dist && tsup",
27
+ "build:tests": "tsc --project tsconfig.test.json",
28
+ "eslint": "eslint ./src",
29
+ "eslint:fix": "eslint --fix ./src",
30
+ "lint": "$npm_execpath run eslint && $npm_execpath run prettier && $npm_execpath run typecheck",
31
+ "prettier": "prettier . --check --cache",
32
+ "prettier:fix": "prettier . --write --cache",
33
+ "test": "$npm_execpath build:tests && node --test dist-test/**/*.test.js",
34
+ "test:only": "$npm_execpath build:tests && node --test-only --test dist-test/**/*.test.js",
35
+ "typecheck": "tsc --noEmit"
36
+ },
37
+ "keywords": [],
38
+ "author": "",
39
+ "license": "ISC",
40
+ "packageManager": "pnpm@10.12.1",
41
+ "devDependencies": {
42
+ "@eslint/js": "^9.35.0",
43
+ "@types/archiver": "^7.0.0",
44
+ "@types/node": "^24.3.1",
45
+ "eslint": "^9.35.0",
46
+ "globals": "^16.3.0",
47
+ "jiti": "^2.5.1",
48
+ "prettier": "3.6.2",
49
+ "ts-node": "^10.9.2",
50
+ "tsconfig-paths": "^4.2.0",
51
+ "tsup": "^8.5.0",
52
+ "typescript": "^5.9.2",
53
+ "typescript-eslint": "^8.42.0"
54
+ },
55
+ "dependencies": {
56
+ "@browserbasehq/sdk": "^2.6.0",
57
+ "@std/expect": "jsr:^1.0.17",
58
+ "archiver": "^7.0.1",
59
+ "chalk": "^5.6.2",
60
+ "commander": "^14.0.2",
61
+ "dotenv": "^17.2.3",
62
+ "tsx": "^4.20.5",
63
+ "zod": "^4.1.5"
64
+ }
65
+ }