New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@devbookhq/sdk

Package Overview
Dependencies
Maintainers
2
Versions
152
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@devbookhq/sdk - npm Package Compare versions

Comparing version 2.4.5 to 2.5.0

dist/cjs/utils/promise.d.ts

2

dist/cjs/index.js

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var s=require("rpc-websocket-client");require("cross-fetch/polyfill");var i=require("openapi-typescript-fetch");function t(s,i,t,e){return new(t||(t=Promise))((function(o,n){function r(s){try{c(e.next(s))}catch(s){n(s)}}function l(s){try{c(e.throw(s))}catch(s){n(s)}}function c(s){var i;s.done?o(s.value):(i=s.value,i instanceof t?i:new t((function(s){s(i)}))).then(r,l)}c((e=e.apply(s,i||[])).next())}))}const e=i.Fetcher.for();function o(s){return new Promise((i=>setTimeout(i,s)))}e.configure({baseUrl:"https://ondevbook.com"});class n{constructor(s,i=!1){this.logID=s,this.isEnabled=i}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}const r=e.path("/sessions").method("post").create({api_key:!0}),l=e.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});var c;exports.CodeSnippetExecState=void 0,(c=exports.CodeSnippetExecState||(exports.CodeSnippetExecState={})).Running="Running",c.Stopped="Stopped";function d(s){let i="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",e=t.length;for(let o=0;o<s;o++)i+=t.charAt(Math.floor(Math.random()*e));return i}var h;exports.OutType=void 0,(h=exports.OutType||(exports.OutType={})).Stdout="Stdout",h.Stderr="Stderr",exports.Session=class extends class{constructor(i){this.opts=i,this.isOpen=!1,this.rpc=new s.RpcWebSocketClient,this.subscribers=[],this.logger=new n("Session",i.debug),this.logger.log(`Session for code snippet "${i.id}" initialized`)}call(s,i){return t(this,void 0,void 0,(function*(){return this.rpc.call(s,i)}))}unsubscribe(s){return t(this,void 0,void 0,(function*(){const i=this.subscribers.find((i=>i.subscriptionID===s));i&&(yield this.call(`${i.method}_unsubscribe`,[null==i?void 0:i.subscriptionID]),this.subscribers=this.subscribers.filter((s=>s!==i)),this.logger.log(`Unsubscribed from "${i.method}"`))}))}subscribe(s,i,...e){return t(this,void 0,void 0,(function*(){const t=yield this.call(`${s}_subscribe`,e);if("string"!=typeof t)throw new Error(`Cannot subscribe to ${s} with params ${e}. Expected response to be a subscription ID, instead got ${JSON.stringify(t)}`);return this.subscribers.push({subscriptionID:t,handler:i,method:s}),this.logger.log(`Subscribed to "${s}_${e}" with id "${t}"`),t}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const i=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${i}`:i}close(){var s,i,e;return t(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subscriptionID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(e=null===(i=this.opts)||void 0===i?void 0:i.onClose)||void 0===e||e.call(i),this.logger.log("Disconected from the session")}}))}open(){return t(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield r({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof r.Error){const i=s.getActualType();if(400===i.status)throw new Error(`Error creating session - (${i.status}) bad request: ${i.data.message}`);if(401===i.status)throw new Error(`Error creating session - (${i.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${i.data.message}`);if(500===i.status)throw new Error(`Error creating session - (${i.status}) server error: ${i.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const i=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let e,n,l=!1;const c=new Promise(((s,i)=>{e=()=>{l||(l=!0,s())},n=()=>{l||(l=!0,i())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==e||e()})),this.rpc.onClose((s=>t(this,void 0,void 0,(function*(){var t,e,r,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(e=(t=this.opts).onDisconnect)||void 0===e||e.call(t),yield o(100),this.logger.log("Reconnecting to session:",this.session);try{yield this.rpc.connect(i),null===(l=(r=this.opts).onReconnect)||void 0===l||l.call(r),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==n||n()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(i)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield c}))}handleNotification(s){this.subscribers.filter((i=>{var t;return i.subscriptionID===(null===(t=s.params)||void 0===t?void 0:t.subscription)})).forEach((i=>{var t;return i.handler(null===(t=s.params)||void 0===t?void 0:t.result)}))}refresh(s){return t(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield o(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield l({sessionID:s,api_key:this.opts.apiKey})}catch(i){if(i instanceof l.Error){const t=i.getActualType();if(404===t.status)return void this.logger.error(`Error refreshing session - (${t.status}): ${t.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${t.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var i,e,o,n;return t(this,void 0,void 0,(function*(){yield s.open.call(this),yield Promise.all([(null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStderr)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(o=this.codeSnippetOpts)||void 0===o?void 0:o.onStdout)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe("codeSnippet",this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0]),this.codeSnippet={run:(s,i={})=>t(this,void 0,void 0,(function*(){var t,e;const o=yield this.call("codeSnippet_run",[s,i]);return null===(e=null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStateChange)||void 0===e||e.call(t,o),o})),stop:()=>t(this,void 0,void 0,(function*(){var s,i;const t=yield this.call("codeSnippet_stop");return null===(i=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===i||i.call(s,t),t}))},this.filesystem={listAllFiles:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem_listAllFiles",[s])})),removeFile:s=>t(this,void 0,void 0,(function*(){yield this.call("filesystem_removeFile",[s])})),writeFile:(s,i)=>t(this,void 0,void 0,(function*(){yield this.call("filesystem_writeFile",[s,i])})),readFile:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem_readFile",[s])}))},this.terminal={killProcess:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal_killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:i,size:e,activeTerminalID:o})=>t(this,void 0,void 0,(function*(){const n=yield this.call("terminal_start",[o||"",e.cols,e.rows]);if("string"!=typeof n)throw new Error("Cannot initialize terminal");const[r,l]=yield Promise.all([this.subscribe("terminal",s,"onData",n),i?this.subscribe("terminal",i,"onChildProcessesChange",n):void 0]);return{terminalID:n,destroy:()=>t(this,void 0,void 0,(function*(){yield Promise.all([this.unsubscribe(r),l?this.unsubscribe(l):void 0,yield this.call("terminal_destroy",[n])])})),sendData:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal_data",[n,s])})),resize:({cols:s,rows:i})=>t(this,void 0,void 0,(function*(){yield this.call("terminal_resize",[n,s,i])}))}}))},this.process={start:({cmd:s,onStdout:i,onStderr:e,onExit:o,envVars:n={},rootdir:r="/",processID:l=d(12)})=>t(this,void 0,void 0,(function*(){const[c,d,h]=yield Promise.all([o?this.subscribe("process",o,"onExit",l):void 0,i?this.subscribe("process",i,"onStdout",l):void 0,e?this.subscribe("process",e,"onStderr",l):void 0]);return yield this.call("process_start",[l,s,n,r]),{processID:l,kill:()=>t(this,void 0,void 0,(function*(){c&&(yield this.unsubscribe(c)),yield Promise.all([d?this.unsubscribe(d):void 0,h?this.unsubscribe(h):void 0,this.call("process_kill",[l])]),null==o||o()})),sendStdin:s=>t(this,void 0,void 0,(function*(){yield this.call("process_stdin",[l,s])}))}}))}}))}},exports.api=e;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var s=require("rpc-websocket-client");require("cross-fetch/polyfill");var e=require("openapi-typescript-fetch");function i(s,e,i,t){return new(i||(i=Promise))((function(o,n){function r(s){try{c(t.next(s))}catch(s){n(s)}}function l(s){try{c(t.throw(s))}catch(s){n(s)}}function c(s){var e;s.done?o(s.value):(e=s.value,e instanceof i?e:new i((function(s){s(e)}))).then(r,l)}c((t=t.apply(s,e||[])).next())}))}const t=e.Fetcher.for();function o(s){return new Promise((e=>setTimeout(e,s)))}t.configure({baseUrl:"https://ondevbook.com"});class n{constructor(s,e=!1){this.logID=s,this.isEnabled=e}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}function r(s){return"fulfilled"===s.status}function l(s){if(!s.every((s=>"fulfilled"===s.status)))return s.reduce(((s,e,i)=>"rejected"===e.status?s+"\n"+`[${i}]: `+`${JSON.stringify(e)}`:s),"errors:\n")}function c(){let s,e;const i=new Promise(((i,t)=>{s=i,e=t}));return{resolve:s,reject:e,promise:i}}const d=t.path("/sessions").method("post").create({api_key:!0}),h=t.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});var a;exports.CodeSnippetExecState=void 0,(a=exports.CodeSnippetExecState||(exports.CodeSnippetExecState={})).Running="Running",a.Stopped="Stopped";function u(s){let e="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=i.length;for(let o=0;o<s;o++)e+=i.charAt(Math.floor(Math.random()*t));return e}var p;exports.OutType=void 0,(p=exports.OutType||(exports.OutType={})).Stdout="Stdout",p.Stderr="Stderr",exports.Session=class extends class{constructor(e){this.opts=e,this.isOpen=!1,this.rpc=new s.RpcWebSocketClient,this.subscribers=[],this.logger=new n("Session",e.debug),this.logger.log(`Session for code snippet "${e.id}" initialized`)}call(s,e,t){return i(this,void 0,void 0,(function*(){return this.logger.log(`${s}_${e}`,t),this.rpc.call(`${s}_${e}`,t)}))}handleSubscriptions(...s){return i(this,void 0,void 0,(function*(){const e=yield Promise.allSettled(s);if(e.every((s=>"fulfilled"===s.status)))return e.map((s=>"fulfilled"===s.status?s.value:void 0));throw yield Promise.all(e.filter(r).map((s=>s.value?this.unsubscribe(s.value):void 0))),new Error(l(e))}))}unsubscribe(s){return i(this,void 0,void 0,(function*(){const e=this.subscribers.find((e=>e.subID===s));e&&(yield this.call(e.service,"unsubscribe",[e.subID]),this.subscribers=this.subscribers.filter((s=>s!==e)),this.logger.log(`Unsubscribed from "${e.service}"`))}))}subscribe(s,e,t,...o){return i(this,void 0,void 0,(function*(){const i=yield this.call(s,"subscribe",[t,...o]);if("string"!=typeof i)throw new Error(`Cannot subscribe to ${s}_${t}${o.length>0?" with params ["+o.join(", ")+"]":""}. Expected response should have been a subscription ID, instead we got ${JSON.stringify(i)}`);return this.subscribers.push({subID:i,handler:e,service:s}),this.logger.log(`Subscribed to "${s}_${t}"${o.length>0?" with params ["+o.join(", ")+"] and":""} with id "${i}"`),i}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const e=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${e}`:e}close(){var s,e,t;return i(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(t=null===(e=this.opts)||void 0===e?void 0:e.onClose)||void 0===t||t.call(e),this.logger.log("Disconected from the session")}}))}open(){return i(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield d({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof d.Error){const e=s.getActualType();if(400===e.status)throw new Error(`Error creating session - (${e.status}) bad request: ${e.data.message}`);if(401===e.status)throw new Error(`Error creating session - (${e.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${e.data.message}`);if(500===e.status)throw new Error(`Error creating session - (${e.status}) server error: ${e.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const e=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let t,n,r=!1;const l=new Promise(((s,e)=>{t=()=>{r||(r=!0,s())},n=()=>{r||(r=!0,e())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==t||t()})),this.rpc.onClose((s=>i(this,void 0,void 0,(function*(){var i,t,r,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(t=(i=this.opts).onDisconnect)||void 0===t||t.call(i),yield o(100),this.logger.log("Reconnecting to session:",this.session);try{this.subscribers=[],yield this.rpc.connect(e),null===(l=(r=this.opts).onReconnect)||void 0===l||l.call(r),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==n||n()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(e)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield l}))}handleNotification(s){this.subscribers.filter((e=>{var i;return e.subID===(null===(i=s.params)||void 0===i?void 0:i.subscription)})).forEach((e=>{var i;return e.handler(null===(i=s.params)||void 0===i?void 0:i.result)}))}refresh(s){return i(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield o(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield h({sessionID:s,api_key:this.opts.apiKey})}catch(e){if(e instanceof h.Error){const i=e.getActualType();if(404===i.status)return void this.logger.error(`Error refreshing session - (${i.status}): ${i.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${i.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var e,t,o,n;return i(this,void 0,void 0,(function*(){yield s.open.call(this),yield this.handleSubscriptions((null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStateChange)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStderr)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(o=this.codeSnippetOpts)||void 0===o?void 0:o.onStdout)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe("codeSnippet",this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0),this.codeSnippet={run:(s,e={})=>i(this,void 0,void 0,(function*(){var i,t;const o=yield this.call("codeSnippet","run",[s,e]);return null===(t=null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)||void 0===t||t.call(i,o),o})),stop:()=>i(this,void 0,void 0,(function*(){var s,e;const i=yield this.call("codeSnippet","stop");return null===(e=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===e||e.call(s,i),i}))},this.filesystem={listAllFiles:s=>i(this,void 0,void 0,(function*(){return yield this.call("filesystem","listAllFiles",[s])})),removeFile:s=>i(this,void 0,void 0,(function*(){yield this.call("filesystem","removeFile",[s])})),writeFile:(s,e)=>i(this,void 0,void 0,(function*(){yield this.call("filesystem","writeFile",[s,e])})),readFile:s=>i(this,void 0,void 0,(function*(){return yield this.call("filesystem","readFile",[s])}))},this.terminal={killProcess:s=>i(this,void 0,void 0,(function*(){yield this.call("terminal","killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:e,size:t,terminalID:o=u(12)})=>i(this,void 0,void 0,(function*(){const[n,c]=yield this.handleSubscriptions(this.subscribe("terminal",s,"onData",o),e?this.subscribe("terminal",e,"onChildProcessesChange",o):void 0);try{yield this.call("terminal","start",[o,t.cols,t.rows])}catch(s){const e=l(yield Promise.allSettled([this.unsubscribe(n),c?this.unsubscribe(c):void 0]));throw e&&this.logger.error(e),s}return{terminalID:o,destroy:()=>i(this,void 0,void 0,(function*(){!function(s){if(s.some((s=>"rejected"===s.status)))throw new Error(l(s));s.filter(r).map((s=>s.value))}(yield Promise.allSettled([this.unsubscribe(n),c?this.unsubscribe(c):void 0,yield this.call("terminal","destroy",[o])]))})),sendData:s=>i(this,void 0,void 0,(function*(){yield this.call("terminal","data",[o,s])})),resize:({cols:s,rows:e})=>i(this,void 0,void 0,(function*(){yield this.call("terminal","resize",[o,s,e])}))}}))},this.process={start:({cmd:s,onStdout:e,onStderr:t,onExit:o,envVars:n={},rootdir:r="/",processID:d=u(12)})=>i(this,void 0,void 0,(function*(){const{promise:h,resolve:a}=c(),[u,p,v]=yield this.handleSubscriptions(this.subscribe("process",a,"onExit",d),e?this.subscribe("process",e,"onStdout",d):void 0,t?this.subscribe("process",t,"onStderr",d):void 0),{promise:g,resolve:f}=c();h.then((()=>i(this,void 0,void 0,(function*(){const s=l(yield Promise.allSettled([this.unsubscribe(u),p?this.unsubscribe(p):void 0,v?this.unsubscribe(v):void 0]));s&&this.logger.error(s),null==o||o(),f()}))));try{yield this.call("process","start",[d,s,n,r])}catch(s){throw a(),yield g,s}return{processID:d,kill:()=>i(this,void 0,void 0,(function*(){try{yield this.call("process","kill",[d])}finally{a(),yield g}})),sendStdin:s=>i(this,void 0,void 0,(function*(){yield this.call("process","stdin",[d,s])}))}}))}}))}},exports.api=t;
//# sourceMappingURL=index.js.map
import { OutStderrResponse, OutStdoutResponse } from './out';
import { EnvVars } from './envVars';
export declare const codeSnippetMethod = "codeSnippet";
export declare const codeSnippetService = "codeSnippet";
export declare enum CodeSnippetExecState {

@@ -5,0 +5,0 @@ Running = "Running",

@@ -1,2 +0,2 @@

export declare const filesystemMethod = "filesystem";
export declare const filesystemService = "filesystem";
export interface FileInfo {

@@ -3,0 +3,0 @@ isDir: boolean;

import { EnvVars } from './envVars';
import { OutStdoutResponse, OutStderrResponse } from './out';
export declare const processMethod = "process";
export declare const processService = "process";
export interface Process {

@@ -5,0 +5,0 @@ readonly sendStdin: (data: string) => Promise<void>;

import { components } from '../api';
import Logger from '../utils/logger';
import { processService } from './process';
import { codeSnippetService } from './codeSnippet';
import { filesystemService } from './filesystem';
import { terminalService } from './terminal';
declare type SubscriptionHandler = (result: any) => void;
declare type Service = typeof processService | typeof codeSnippetService | typeof filesystemService | typeof terminalService;
export declare type CloseHandler = () => void;

@@ -26,5 +31,8 @@ export declare type DisconnectHandler = () => void;

constructor(opts: SessionConnectionOpts);
protected call(method: string, params?: any[]): Promise<unknown>;
protected unsubscribe(subscriptionID: string): Promise<void>;
protected subscribe(method: string, handler: SubscriptionHandler, ...params: any): Promise<string>;
protected call(service: Service, method: string, params?: any[]): Promise<unknown>;
protected handleSubscriptions<T extends (ReturnType<SessionConnection['subscribe']> | undefined)[]>(...subs: T): Promise<{
[P in keyof T]: Awaited<T[P]>;
}>;
protected unsubscribe(subID: string): Promise<void>;
protected subscribe(service: Service, handler: SubscriptionHandler, method: string, ...params: any[]): Promise<string>;
/**

@@ -31,0 +39,0 @@ * Get the hostname for the session or for the specified session's port.

@@ -1,2 +0,2 @@

export declare const terminalMethod = "terminal";
export declare const terminalService = "terminal";
export interface TerminalSession {

@@ -24,4 +24,4 @@ readonly sendData: (data: string) => Promise<void>;

};
activeTerminalID?: string;
terminalID?: string;
}) => Promise<TerminalSession>;
}

@@ -1,2 +0,2 @@

import{RpcWebSocketClient as s}from"rpc-websocket-client";import"cross-fetch/polyfill";import{Fetcher as i}from"openapi-typescript-fetch";function t(s,i,t,e){return new(t||(t=Promise))((function(o,n){function r(s){try{c(e.next(s))}catch(s){n(s)}}function l(s){try{c(e.throw(s))}catch(s){n(s)}}function c(s){var i;s.done?o(s.value):(i=s.value,i instanceof t?i:new t((function(s){s(i)}))).then(r,l)}c((e=e.apply(s,i||[])).next())}))}const e=i.for();function o(s){return new Promise((i=>setTimeout(i,s)))}e.configure({baseUrl:"https://ondevbook.com"});class n{constructor(s,i=!1){this.logID=s,this.isEnabled=i}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}const r=e.path("/sessions").method("post").create({api_key:!0}),l=e.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});var c;!function(s){s.Running="Running",s.Stopped="Stopped"}(c||(c={}));function d(s){let i="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",e=t.length;for(let o=0;o<s;o++)i+=t.charAt(Math.floor(Math.random()*e));return i}class h extends class{constructor(i){this.opts=i,this.isOpen=!1,this.rpc=new s,this.subscribers=[],this.logger=new n("Session",i.debug),this.logger.log(`Session for code snippet "${i.id}" initialized`)}call(s,i){return t(this,void 0,void 0,(function*(){return this.rpc.call(s,i)}))}unsubscribe(s){return t(this,void 0,void 0,(function*(){const i=this.subscribers.find((i=>i.subscriptionID===s));i&&(yield this.call(`${i.method}_unsubscribe`,[null==i?void 0:i.subscriptionID]),this.subscribers=this.subscribers.filter((s=>s!==i)),this.logger.log(`Unsubscribed from "${i.method}"`))}))}subscribe(s,i,...e){return t(this,void 0,void 0,(function*(){const t=yield this.call(`${s}_subscribe`,e);if("string"!=typeof t)throw new Error(`Cannot subscribe to ${s} with params ${e}. Expected response to be a subscription ID, instead got ${JSON.stringify(t)}`);return this.subscribers.push({subscriptionID:t,handler:i,method:s}),this.logger.log(`Subscribed to "${s}_${e}" with id "${t}"`),t}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const i=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${i}`:i}close(){var s,i,e;return t(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subscriptionID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(e=null===(i=this.opts)||void 0===i?void 0:i.onClose)||void 0===e||e.call(i),this.logger.log("Disconected from the session")}}))}open(){return t(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield r({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof r.Error){const i=s.getActualType();if(400===i.status)throw new Error(`Error creating session - (${i.status}) bad request: ${i.data.message}`);if(401===i.status)throw new Error(`Error creating session - (${i.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${i.data.message}`);if(500===i.status)throw new Error(`Error creating session - (${i.status}) server error: ${i.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const i=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let e,n,l=!1;const c=new Promise(((s,i)=>{e=()=>{l||(l=!0,s())},n=()=>{l||(l=!0,i())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==e||e()})),this.rpc.onClose((s=>t(this,void 0,void 0,(function*(){var t,e,r,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(e=(t=this.opts).onDisconnect)||void 0===e||e.call(t),yield o(100),this.logger.log("Reconnecting to session:",this.session);try{yield this.rpc.connect(i),null===(l=(r=this.opts).onReconnect)||void 0===l||l.call(r),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==n||n()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(i)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield c}))}handleNotification(s){this.subscribers.filter((i=>{var t;return i.subscriptionID===(null===(t=s.params)||void 0===t?void 0:t.subscription)})).forEach((i=>{var t;return i.handler(null===(t=s.params)||void 0===t?void 0:t.result)}))}refresh(s){return t(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield o(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield l({sessionID:s,api_key:this.opts.apiKey})}catch(i){if(i instanceof l.Error){const t=i.getActualType();if(404===t.status)return void this.logger.error(`Error refreshing session - (${t.status}): ${t.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${t.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var i,e,o,n;return t(this,void 0,void 0,(function*(){yield s.open.call(this),yield Promise.all([(null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStderr)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(o=this.codeSnippetOpts)||void 0===o?void 0:o.onStdout)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe("codeSnippet",this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0]),this.codeSnippet={run:(s,i={})=>t(this,void 0,void 0,(function*(){var t,e;const o=yield this.call("codeSnippet_run",[s,i]);return null===(e=null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStateChange)||void 0===e||e.call(t,o),o})),stop:()=>t(this,void 0,void 0,(function*(){var s,i;const t=yield this.call("codeSnippet_stop");return null===(i=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===i||i.call(s,t),t}))},this.filesystem={listAllFiles:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem_listAllFiles",[s])})),removeFile:s=>t(this,void 0,void 0,(function*(){yield this.call("filesystem_removeFile",[s])})),writeFile:(s,i)=>t(this,void 0,void 0,(function*(){yield this.call("filesystem_writeFile",[s,i])})),readFile:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem_readFile",[s])}))},this.terminal={killProcess:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal_killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:i,size:e,activeTerminalID:o})=>t(this,void 0,void 0,(function*(){const n=yield this.call("terminal_start",[o||"",e.cols,e.rows]);if("string"!=typeof n)throw new Error("Cannot initialize terminal");const[r,l]=yield Promise.all([this.subscribe("terminal",s,"onData",n),i?this.subscribe("terminal",i,"onChildProcessesChange",n):void 0]);return{terminalID:n,destroy:()=>t(this,void 0,void 0,(function*(){yield Promise.all([this.unsubscribe(r),l?this.unsubscribe(l):void 0,yield this.call("terminal_destroy",[n])])})),sendData:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal_data",[n,s])})),resize:({cols:s,rows:i})=>t(this,void 0,void 0,(function*(){yield this.call("terminal_resize",[n,s,i])}))}}))},this.process={start:({cmd:s,onStdout:i,onStderr:e,onExit:o,envVars:n={},rootdir:r="/",processID:l=d(12)})=>t(this,void 0,void 0,(function*(){const[c,d,h]=yield Promise.all([o?this.subscribe("process",o,"onExit",l):void 0,i?this.subscribe("process",i,"onStdout",l):void 0,e?this.subscribe("process",e,"onStderr",l):void 0]);return yield this.call("process_start",[l,s,n,r]),{processID:l,kill:()=>t(this,void 0,void 0,(function*(){c&&(yield this.unsubscribe(c)),yield Promise.all([d?this.unsubscribe(d):void 0,h?this.unsubscribe(h):void 0,this.call("process_kill",[l])]),null==o||o()})),sendStdin:s=>t(this,void 0,void 0,(function*(){yield this.call("process_stdin",[l,s])}))}}))}}))}}var a;!function(s){s.Stdout="Stdout",s.Stderr="Stderr"}(a||(a={}));export{c as CodeSnippetExecState,a as OutType,h as Session,e as api};
import{RpcWebSocketClient as s}from"rpc-websocket-client";import"cross-fetch/polyfill";import{Fetcher as i}from"openapi-typescript-fetch";function t(s,i,t,e){return new(t||(t=Promise))((function(o,n){function r(s){try{c(e.next(s))}catch(s){n(s)}}function l(s){try{c(e.throw(s))}catch(s){n(s)}}function c(s){var i;s.done?o(s.value):(i=s.value,i instanceof t?i:new t((function(s){s(i)}))).then(r,l)}c((e=e.apply(s,i||[])).next())}))}const e=i.for();function o(s){return new Promise((i=>setTimeout(i,s)))}e.configure({baseUrl:"https://ondevbook.com"});class n{constructor(s,i=!1){this.logID=s,this.isEnabled=i}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}function r(s){return"fulfilled"===s.status}function l(s){if(!s.every((s=>"fulfilled"===s.status)))return s.reduce(((s,i,t)=>"rejected"===i.status?s+"\n"+`[${t}]: `+`${JSON.stringify(i)}`:s),"errors:\n")}function c(){let s,i;const t=new Promise(((t,e)=>{s=t,i=e}));return{resolve:s,reject:i,promise:t}}const d=e.path("/sessions").method("post").create({api_key:!0}),h=e.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});var a;!function(s){s.Running="Running",s.Stopped="Stopped"}(a||(a={}));function u(s){let i="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",e=t.length;for(let o=0;o<s;o++)i+=t.charAt(Math.floor(Math.random()*e));return i}class p extends class{constructor(i){this.opts=i,this.isOpen=!1,this.rpc=new s,this.subscribers=[],this.logger=new n("Session",i.debug),this.logger.log(`Session for code snippet "${i.id}" initialized`)}call(s,i,e){return t(this,void 0,void 0,(function*(){return this.logger.log(`${s}_${i}`,e),this.rpc.call(`${s}_${i}`,e)}))}handleSubscriptions(...s){return t(this,void 0,void 0,(function*(){const i=yield Promise.allSettled(s);if(i.every((s=>"fulfilled"===s.status)))return i.map((s=>"fulfilled"===s.status?s.value:void 0));throw yield Promise.all(i.filter(r).map((s=>s.value?this.unsubscribe(s.value):void 0))),new Error(l(i))}))}unsubscribe(s){return t(this,void 0,void 0,(function*(){const i=this.subscribers.find((i=>i.subID===s));i&&(yield this.call(i.service,"unsubscribe",[i.subID]),this.subscribers=this.subscribers.filter((s=>s!==i)),this.logger.log(`Unsubscribed from "${i.service}"`))}))}subscribe(s,i,e,...o){return t(this,void 0,void 0,(function*(){const t=yield this.call(s,"subscribe",[e,...o]);if("string"!=typeof t)throw new Error(`Cannot subscribe to ${s}_${e}${o.length>0?" with params ["+o.join(", ")+"]":""}. Expected response should have been a subscription ID, instead we got ${JSON.stringify(t)}`);return this.subscribers.push({subID:t,handler:i,service:s}),this.logger.log(`Subscribed to "${s}_${e}"${o.length>0?" with params ["+o.join(", ")+"] and":""} with id "${t}"`),t}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const i=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${i}`:i}close(){var s,i,e;return t(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(e=null===(i=this.opts)||void 0===i?void 0:i.onClose)||void 0===e||e.call(i),this.logger.log("Disconected from the session")}}))}open(){return t(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield d({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof d.Error){const i=s.getActualType();if(400===i.status)throw new Error(`Error creating session - (${i.status}) bad request: ${i.data.message}`);if(401===i.status)throw new Error(`Error creating session - (${i.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${i.data.message}`);if(500===i.status)throw new Error(`Error creating session - (${i.status}) server error: ${i.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const i=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let e,n,r=!1;const l=new Promise(((s,i)=>{e=()=>{r||(r=!0,s())},n=()=>{r||(r=!0,i())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==e||e()})),this.rpc.onClose((s=>t(this,void 0,void 0,(function*(){var t,e,r,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(e=(t=this.opts).onDisconnect)||void 0===e||e.call(t),yield o(100),this.logger.log("Reconnecting to session:",this.session);try{this.subscribers=[],yield this.rpc.connect(i),null===(l=(r=this.opts).onReconnect)||void 0===l||l.call(r),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==n||n()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(i)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield l}))}handleNotification(s){this.subscribers.filter((i=>{var t;return i.subID===(null===(t=s.params)||void 0===t?void 0:t.subscription)})).forEach((i=>{var t;return i.handler(null===(t=s.params)||void 0===t?void 0:t.result)}))}refresh(s){return t(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield o(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield h({sessionID:s,api_key:this.opts.apiKey})}catch(i){if(i instanceof h.Error){const t=i.getActualType();if(404===t.status)return void this.logger.error(`Error refreshing session - (${t.status}): ${t.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${t.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var i,e,o,n;return t(this,void 0,void 0,(function*(){yield s.open.call(this),yield this.handleSubscriptions((null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStderr)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(o=this.codeSnippetOpts)||void 0===o?void 0:o.onStdout)?this.subscribe("codeSnippet",this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe("codeSnippet",this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0),this.codeSnippet={run:(s,i={})=>t(this,void 0,void 0,(function*(){var t,e;const o=yield this.call("codeSnippet","run",[s,i]);return null===(e=null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStateChange)||void 0===e||e.call(t,o),o})),stop:()=>t(this,void 0,void 0,(function*(){var s,i;const t=yield this.call("codeSnippet","stop");return null===(i=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===i||i.call(s,t),t}))},this.filesystem={listAllFiles:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem","listAllFiles",[s])})),removeFile:s=>t(this,void 0,void 0,(function*(){yield this.call("filesystem","removeFile",[s])})),writeFile:(s,i)=>t(this,void 0,void 0,(function*(){yield this.call("filesystem","writeFile",[s,i])})),readFile:s=>t(this,void 0,void 0,(function*(){return yield this.call("filesystem","readFile",[s])}))},this.terminal={killProcess:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal","killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:i,size:e,terminalID:o=u(12)})=>t(this,void 0,void 0,(function*(){const[n,c]=yield this.handleSubscriptions(this.subscribe("terminal",s,"onData",o),i?this.subscribe("terminal",i,"onChildProcessesChange",o):void 0);try{yield this.call("terminal","start",[o,e.cols,e.rows])}catch(s){const i=l(yield Promise.allSettled([this.unsubscribe(n),c?this.unsubscribe(c):void 0]));throw i&&this.logger.error(i),s}return{terminalID:o,destroy:()=>t(this,void 0,void 0,(function*(){!function(s){if(s.some((s=>"rejected"===s.status)))throw new Error(l(s));s.filter(r).map((s=>s.value))}(yield Promise.allSettled([this.unsubscribe(n),c?this.unsubscribe(c):void 0,yield this.call("terminal","destroy",[o])]))})),sendData:s=>t(this,void 0,void 0,(function*(){yield this.call("terminal","data",[o,s])})),resize:({cols:s,rows:i})=>t(this,void 0,void 0,(function*(){yield this.call("terminal","resize",[o,s,i])}))}}))},this.process={start:({cmd:s,onStdout:i,onStderr:e,onExit:o,envVars:n={},rootdir:r="/",processID:d=u(12)})=>t(this,void 0,void 0,(function*(){const{promise:h,resolve:a}=c(),[u,p,g]=yield this.handleSubscriptions(this.subscribe("process",a,"onExit",d),i?this.subscribe("process",i,"onStdout",d):void 0,e?this.subscribe("process",e,"onStderr",d):void 0),{promise:v,resolve:f}=c();h.then((()=>t(this,void 0,void 0,(function*(){const s=l(yield Promise.allSettled([this.unsubscribe(u),p?this.unsubscribe(p):void 0,g?this.unsubscribe(g):void 0]));s&&this.logger.error(s),null==o||o(),f()}))));try{yield this.call("process","start",[d,s,n,r])}catch(s){throw a(),yield v,s}return{processID:d,kill:()=>t(this,void 0,void 0,(function*(){try{yield this.call("process","kill",[d])}finally{a(),yield v}})),sendStdin:s=>t(this,void 0,void 0,(function*(){yield this.call("process","stdin",[d,s])}))}}))}}))}}var g;!function(s){s.Stdout="Stdout",s.Stderr="Stderr"}(g||(g={}));export{a as CodeSnippetExecState,g as OutType,p as Session,e as api};
//# sourceMappingURL=index.js.map
import { OutStderrResponse, OutStdoutResponse } from './out';
import { EnvVars } from './envVars';
export declare const codeSnippetMethod = "codeSnippet";
export declare const codeSnippetService = "codeSnippet";
export declare enum CodeSnippetExecState {

@@ -5,0 +5,0 @@ Running = "Running",

@@ -1,2 +0,2 @@

export declare const filesystemMethod = "filesystem";
export declare const filesystemService = "filesystem";
export interface FileInfo {

@@ -3,0 +3,0 @@ isDir: boolean;

import { EnvVars } from './envVars';
import { OutStdoutResponse, OutStderrResponse } from './out';
export declare const processMethod = "process";
export declare const processService = "process";
export interface Process {

@@ -5,0 +5,0 @@ readonly sendStdin: (data: string) => Promise<void>;

import { components } from '../api';
import Logger from '../utils/logger';
import { processService } from './process';
import { codeSnippetService } from './codeSnippet';
import { filesystemService } from './filesystem';
import { terminalService } from './terminal';
declare type SubscriptionHandler = (result: any) => void;
declare type Service = typeof processService | typeof codeSnippetService | typeof filesystemService | typeof terminalService;
export declare type CloseHandler = () => void;

@@ -26,5 +31,8 @@ export declare type DisconnectHandler = () => void;

constructor(opts: SessionConnectionOpts);
protected call(method: string, params?: any[]): Promise<unknown>;
protected unsubscribe(subscriptionID: string): Promise<void>;
protected subscribe(method: string, handler: SubscriptionHandler, ...params: any): Promise<string>;
protected call(service: Service, method: string, params?: any[]): Promise<unknown>;
protected handleSubscriptions<T extends (ReturnType<SessionConnection['subscribe']> | undefined)[]>(...subs: T): Promise<{
[P in keyof T]: Awaited<T[P]>;
}>;
protected unsubscribe(subID: string): Promise<void>;
protected subscribe(service: Service, handler: SubscriptionHandler, method: string, ...params: any[]): Promise<string>;
/**

@@ -31,0 +39,0 @@ * Get the hostname for the session or for the specified session's port.

@@ -1,2 +0,2 @@

export declare const terminalMethod = "terminal";
export declare const terminalService = "terminal";
export interface TerminalSession {

@@ -24,4 +24,4 @@ readonly sendData: (data: string) => Promise<void>;

};
activeTerminalID?: string;
terminalID?: string;
}) => Promise<TerminalSession>;
}

@@ -1,2 +0,2 @@

!function(s,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("rpc-websocket-client"),require("cross-fetch/polyfill"),require("openapi-typescript-fetch")):"function"==typeof define&&define.amd?define(["exports","rpc-websocket-client","cross-fetch/polyfill","openapi-typescript-fetch"],i):i((s="undefined"!=typeof globalThis?globalThis:s||self)["@devbookhq/sdk"]={},s.rpcWebsocketClient,null,s.openapiTypescriptFetch)}(this,(function(s,i,t,e){"use strict";function o(s,i,t,e){return new(t||(t=Promise))((function(o,n){function r(s){try{c(e.next(s))}catch(s){n(s)}}function l(s){try{c(e.throw(s))}catch(s){n(s)}}function c(s){var i;s.done?o(s.value):(i=s.value,i instanceof t?i:new t((function(s){s(i)}))).then(r,l)}c((e=e.apply(s,i||[])).next())}))}const n=e.Fetcher.for();function r(s){return new Promise((i=>setTimeout(i,s)))}n.configure({baseUrl:"https://ondevbook.com"});class l{constructor(s,i=!1){this.logID=s,this.isEnabled=i}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}const c=n.path("/sessions").method("post").create({api_key:!0}),d=n.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});const h="codeSnippet";var a;s.CodeSnippetExecState=void 0,(a=s.CodeSnippetExecState||(s.CodeSnippetExecState={})).Running="Running",a.Stopped="Stopped";const u="terminal",p="process";function g(s){let i="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",e=t.length;for(let o=0;o<s;o++)i+=t.charAt(Math.floor(Math.random()*e));return i}var v;s.OutType=void 0,(v=s.OutType||(s.OutType={})).Stdout="Stdout",v.Stderr="Stderr",s.Session=class extends class{constructor(s){this.opts=s,this.isOpen=!1,this.rpc=new i.RpcWebSocketClient,this.subscribers=[],this.logger=new l("Session",s.debug),this.logger.log(`Session for code snippet "${s.id}" initialized`)}call(s,i){return o(this,void 0,void 0,(function*(){return this.rpc.call(s,i)}))}unsubscribe(s){return o(this,void 0,void 0,(function*(){const i=this.subscribers.find((i=>i.subscriptionID===s));i&&(yield this.call(`${i.method}_unsubscribe`,[null==i?void 0:i.subscriptionID]),this.subscribers=this.subscribers.filter((s=>s!==i)),this.logger.log(`Unsubscribed from "${i.method}"`))}))}subscribe(s,i,...t){return o(this,void 0,void 0,(function*(){const e=yield this.call(`${s}_subscribe`,t);if("string"!=typeof e)throw new Error(`Cannot subscribe to ${s} with params ${t}. Expected response to be a subscription ID, instead got ${JSON.stringify(e)}`);return this.subscribers.push({subscriptionID:e,handler:i,method:s}),this.logger.log(`Subscribed to "${s}_${t}" with id "${e}"`),e}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const i=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${i}`:i}close(){var s,i,t;return o(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subscriptionID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(t=null===(i=this.opts)||void 0===i?void 0:i.onClose)||void 0===t||t.call(i),this.logger.log("Disconected from the session")}}))}open(){return o(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield c({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof c.Error){const i=s.getActualType();if(400===i.status)throw new Error(`Error creating session - (${i.status}) bad request: ${i.data.message}`);if(401===i.status)throw new Error(`Error creating session - (${i.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${i.data.message}`);if(500===i.status)throw new Error(`Error creating session - (${i.status}) server error: ${i.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const i=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let t,e,n=!1;const l=new Promise(((s,i)=>{t=()=>{n||(n=!0,s())},e=()=>{n||(n=!0,i())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==t||t()})),this.rpc.onClose((s=>o(this,void 0,void 0,(function*(){var t,o,n,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(o=(t=this.opts).onDisconnect)||void 0===o||o.call(t),yield r(100),this.logger.log("Reconnecting to session:",this.session);try{yield this.rpc.connect(i),null===(l=(n=this.opts).onReconnect)||void 0===l||l.call(n),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==e||e()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(i)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield l}))}handleNotification(s){this.subscribers.filter((i=>{var t;return i.subscriptionID===(null===(t=s.params)||void 0===t?void 0:t.subscription)})).forEach((i=>{var t;return i.handler(null===(t=s.params)||void 0===t?void 0:t.result)}))}refresh(s){return o(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield r(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield d({sessionID:s,api_key:this.opts.apiKey})}catch(i){if(i instanceof d.Error){const t=i.getActualType();if(404===t.status)return void this.logger.error(`Error refreshing session - (${t.status}): ${t.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${t.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var i,t,e,n;return o(this,void 0,void 0,(function*(){yield s.open.call(this),yield Promise.all([(null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)?this.subscribe(h,this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStderr)?this.subscribe(h,this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStdout)?this.subscribe(h,this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe(h,this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0]),this.codeSnippet={run:(s,i={})=>o(this,void 0,void 0,(function*(){var t,e;const o=yield this.call("codeSnippet_run",[s,i]);return null===(e=null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStateChange)||void 0===e||e.call(t,o),o})),stop:()=>o(this,void 0,void 0,(function*(){var s,i;const t=yield this.call("codeSnippet_stop");return null===(i=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===i||i.call(s,t),t}))},this.filesystem={listAllFiles:s=>o(this,void 0,void 0,(function*(){return yield this.call("filesystem_listAllFiles",[s])})),removeFile:s=>o(this,void 0,void 0,(function*(){yield this.call("filesystem_removeFile",[s])})),writeFile:(s,i)=>o(this,void 0,void 0,(function*(){yield this.call("filesystem_writeFile",[s,i])})),readFile:s=>o(this,void 0,void 0,(function*(){return yield this.call("filesystem_readFile",[s])}))},this.terminal={killProcess:s=>o(this,void 0,void 0,(function*(){yield this.call("terminal_killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:i,size:t,activeTerminalID:e})=>o(this,void 0,void 0,(function*(){const n=yield this.call("terminal_start",[e||"",t.cols,t.rows]);if("string"!=typeof n)throw new Error("Cannot initialize terminal");const[r,l]=yield Promise.all([this.subscribe(u,s,"onData",n),i?this.subscribe(u,i,"onChildProcessesChange",n):void 0]);return{terminalID:n,destroy:()=>o(this,void 0,void 0,(function*(){yield Promise.all([this.unsubscribe(r),l?this.unsubscribe(l):void 0,yield this.call("terminal_destroy",[n])])})),sendData:s=>o(this,void 0,void 0,(function*(){yield this.call("terminal_data",[n,s])})),resize:({cols:s,rows:i})=>o(this,void 0,void 0,(function*(){yield this.call("terminal_resize",[n,s,i])}))}}))},this.process={start:({cmd:s,onStdout:i,onStderr:t,onExit:e,envVars:n={},rootdir:r="/",processID:l=g(12)})=>o(this,void 0,void 0,(function*(){const[c,d,h]=yield Promise.all([e?this.subscribe(p,e,"onExit",l):void 0,i?this.subscribe(p,i,"onStdout",l):void 0,t?this.subscribe(p,t,"onStderr",l):void 0]);return yield this.call("process_start",[l,s,n,r]),{processID:l,kill:()=>o(this,void 0,void 0,(function*(){c&&(yield this.unsubscribe(c)),yield Promise.all([d?this.unsubscribe(d):void 0,h?this.unsubscribe(h):void 0,this.call("process_kill",[l])]),null==e||e()})),sendStdin:s=>o(this,void 0,void 0,(function*(){yield this.call("process_stdin",[l,s])}))}}))}}))}},s.api=n,Object.defineProperty(s,"__esModule",{value:!0})}));
!function(s,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("rpc-websocket-client"),require("cross-fetch/polyfill"),require("openapi-typescript-fetch")):"function"==typeof define&&define.amd?define(["exports","rpc-websocket-client","cross-fetch/polyfill","openapi-typescript-fetch"],i):i((s="undefined"!=typeof globalThis?globalThis:s||self)["@devbookhq/sdk"]={},s.rpcWebsocketClient,null,s.openapiTypescriptFetch)}(this,(function(s,i,t,e){"use strict";function o(s,i,t,e){return new(t||(t=Promise))((function(o,n){function r(s){try{c(e.next(s))}catch(s){n(s)}}function l(s){try{c(e.throw(s))}catch(s){n(s)}}function c(s){var i;s.done?o(s.value):(i=s.value,i instanceof t?i:new t((function(s){s(i)}))).then(r,l)}c((e=e.apply(s,i||[])).next())}))}const n=e.Fetcher.for();function r(s){return new Promise((i=>setTimeout(i,s)))}n.configure({baseUrl:"https://ondevbook.com"});class l{constructor(s,i=!1){this.logID=s,this.isEnabled=i}id(){return"function"==typeof this.logID?this.logID():this.logID}log(...s){this.isEnabled&&console.log(`[${this.id()}]`,...s)}error(...s){console.error(`[${this.id()} ERROR]`,...s)}}function c(s){return"fulfilled"===s.status}function d(s){if(!s.every((s=>"fulfilled"===s.status)))return s.reduce(((s,i,t)=>"rejected"===i.status?s+"\n"+`[${t}]: `+`${JSON.stringify(i)}`:s),"errors:\n")}function h(){let s,i;const t=new Promise(((t,e)=>{s=t,i=e}));return{resolve:s,reject:i,promise:t}}const u=n.path("/sessions").method("post").create({api_key:!0}),a=n.path("/sessions/{sessionID}/refresh").method("post").create({api_key:!0});const p="codeSnippet";var g;s.CodeSnippetExecState=void 0,(g=s.CodeSnippetExecState||(s.CodeSnippetExecState={})).Running="Running",g.Stopped="Stopped";const v="terminal",f="filesystem",b="process";function y(s){let i="";const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",e=t.length;for(let o=0;o<s;o++)i+=t.charAt(Math.floor(Math.random()*e));return i}var S;s.OutType=void 0,(S=s.OutType||(s.OutType={})).Stdout="Stdout",S.Stderr="Stderr",s.Session=class extends class{constructor(s){this.opts=s,this.isOpen=!1,this.rpc=new i.RpcWebSocketClient,this.subscribers=[],this.logger=new l("Session",s.debug),this.logger.log(`Session for code snippet "${s.id}" initialized`)}call(s,i,t){return o(this,void 0,void 0,(function*(){return this.logger.log(`${s}_${i}`,t),this.rpc.call(`${s}_${i}`,t)}))}handleSubscriptions(...s){return o(this,void 0,void 0,(function*(){const i=yield Promise.allSettled(s);if(i.every((s=>"fulfilled"===s.status)))return i.map((s=>"fulfilled"===s.status?s.value:void 0));throw yield Promise.all(i.filter(c).map((s=>s.value?this.unsubscribe(s.value):void 0))),new Error(d(i))}))}unsubscribe(s){return o(this,void 0,void 0,(function*(){const i=this.subscribers.find((i=>i.subID===s));i&&(yield this.call(i.service,"unsubscribe",[i.subID]),this.subscribers=this.subscribers.filter((s=>s!==i)),this.logger.log(`Unsubscribed from "${i.service}"`))}))}subscribe(s,i,t,...e){return o(this,void 0,void 0,(function*(){const o=yield this.call(s,"subscribe",[t,...e]);if("string"!=typeof o)throw new Error(`Cannot subscribe to ${s}_${t}${e.length>0?" with params ["+e.join(", ")+"]":""}. Expected response should have been a subscription ID, instead we got ${JSON.stringify(o)}`);return this.subscribers.push({subID:o,handler:i,service:s}),this.logger.log(`Subscribed to "${s}_${t}"${e.length>0?" with params ["+e.join(", ")+"] and":""} with id "${o}"`),o}))}getHostname(s){if(this.opts.__debug_hostname)return s&&"remote"===this.opts.__debug_devEnv?`${s}-${this.opts.__debug_hostname}`:s?`${this.opts.__debug_hostname}:${s}`:this.opts.__debug_hostname;if(!this.session)return;const i=`${this.session.sessionID}-${this.session.clientID}.ondevbook.com`;return s?`${s}-${i}`:i}close(){var s,i,t;return o(this,void 0,void 0,(function*(){if(this.isOpen){this.logger.log("Closing",this.session),this.isOpen=!1,this.logger.log("Unsubscribing...");(yield Promise.allSettled(this.subscribers.map((s=>this.unsubscribe(s.subID))))).forEach((s=>{"rejected"===s.status&&this.logger.log(`Failed to unsubscribe: "${s.reason}"`)})),null===(s=this.rpc.ws)||void 0===s||s.close(),null===(t=null===(i=this.opts)||void 0===i?void 0:i.onClose)||void 0===t||t.call(i),this.logger.log("Disconected from the session")}}))}open(){return o(this,void 0,void 0,(function*(){if(this.isOpen||this.session)throw new Error("Session connect was already called");if(this.isOpen=!0,!this.opts.__debug_hostname)try{const s=yield u({codeSnippetID:this.opts.id,editEnabled:this.opts.editEnabled,api_key:this.opts.apiKey});this.session=s.data,this.logger.log("Aquired session:",this.session),this.refresh(this.session.sessionID)}catch(s){if(s instanceof u.Error){const i=s.getActualType();if(400===i.status)throw new Error(`Error creating session - (${i.status}) bad request: ${i.data.message}`);if(401===i.status)throw new Error(`Error creating session - (${i.status}) unauthenticated (you need to be authenticated to start an session with persistent edits): ${i.data.message}`);if(500===i.status)throw new Error(`Error creating session - (${i.status}) server error: ${i.data.message}`);throw s}}const s=this.getHostname(8010);if(!s)throw new Error("Cannot get session's hostname");const i=`${"local"===this.opts.__debug_devEnv?"ws":"wss"}://${s}/ws`;this.rpc.onError((s=>{this.logger.log("Error in WS session:",this.session,s)}));let t,e,n=!1;const l=new Promise(((s,i)=>{t=()=>{n||(n=!0,s())},e=()=>{n||(n=!0,i())}}));this.rpc.onOpen((()=>{this.logger.log("Connected to session:",this.session),null==t||t()})),this.rpc.onClose((s=>o(this,void 0,void 0,(function*(){var t,o,n,l;if(this.logger.log("Closing WS connection to session:",this.session,s),this.isOpen){null===(o=(t=this.opts).onDisconnect)||void 0===o||o.call(t),yield r(100),this.logger.log("Reconnecting to session:",this.session);try{this.subscribers=[],yield this.rpc.connect(i),null===(l=(n=this.opts).onReconnect)||void 0===l||l.call(n),this.logger.log("Reconnected to session:",this.session)}catch(s){this.logger.log("Failed reconnecting to session:",this.session,s)}}else null==e||e()})))),this.rpc.onNotification.push(this.handleNotification.bind(this));try{this.logger.log("Connection to session:",this.session),yield this.rpc.connect(i)}catch(s){this.logger.log("Error connecting to session",this.session,s)}yield l}))}handleNotification(s){this.subscribers.filter((i=>{var t;return i.subID===(null===(t=s.params)||void 0===t?void 0:t.subscription)})).forEach((i=>{var t;return i.handler(null===(t=s.params)||void 0===t?void 0:t.result)}))}refresh(s){return o(this,void 0,void 0,(function*(){this.logger.log(`Started refreshing session "${s}"`);try{for(;;){if(!this.isOpen)return void this.logger.log("Cannot refresh session - it was closed",this.session);yield r(5e3);try{this.logger.log(`Refreshed session "${s}"`),yield a({sessionID:s,api_key:this.opts.apiKey})}catch(i){if(i instanceof a.Error){const t=i.getActualType();if(404===t.status)return void this.logger.error(`Error refreshing session - (${t.status}): ${t.data.message}`);this.logger.error(`Refreshing session "${s}" failed - (${t.status})`)}}}}finally{this.logger.log(`Stopped refreshing session "${s}"`),this.close()}}))}}{constructor(s){super(s),this.codeSnippetOpts=s.codeSnippet}open(){const s=Object.create(null,{open:{get:()=>super.open}});var i,t,e,n;return o(this,void 0,void 0,(function*(){yield s.open.call(this),yield this.handleSubscriptions((null===(i=this.codeSnippetOpts)||void 0===i?void 0:i.onStateChange)?this.subscribe(p,this.codeSnippetOpts.onStateChange,"state"):void 0,(null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStderr)?this.subscribe(p,this.codeSnippetOpts.onStderr,"stderr"):void 0,(null===(e=this.codeSnippetOpts)||void 0===e?void 0:e.onStdout)?this.subscribe(p,this.codeSnippetOpts.onStdout,"stdout"):void 0,(null===(n=this.codeSnippetOpts)||void 0===n?void 0:n.onScanPorts)?this.subscribe(p,this.codeSnippetOpts.onScanPorts,"scanOpenedPorts"):void 0),this.codeSnippet={run:(s,i={})=>o(this,void 0,void 0,(function*(){var t,e;const o=yield this.call(p,"run",[s,i]);return null===(e=null===(t=this.codeSnippetOpts)||void 0===t?void 0:t.onStateChange)||void 0===e||e.call(t,o),o})),stop:()=>o(this,void 0,void 0,(function*(){var s,i;const t=yield this.call(p,"stop");return null===(i=null===(s=this.codeSnippetOpts)||void 0===s?void 0:s.onStateChange)||void 0===i||i.call(s,t),t}))},this.filesystem={listAllFiles:s=>o(this,void 0,void 0,(function*(){return yield this.call(f,"listAllFiles",[s])})),removeFile:s=>o(this,void 0,void 0,(function*(){yield this.call(f,"removeFile",[s])})),writeFile:(s,i)=>o(this,void 0,void 0,(function*(){yield this.call(f,"writeFile",[s,i])})),readFile:s=>o(this,void 0,void 0,(function*(){return yield this.call(f,"readFile",[s])}))},this.terminal={killProcess:s=>o(this,void 0,void 0,(function*(){yield this.call(v,"killProcess",[s])})),createSession:({onData:s,onChildProcessesChange:i,size:t,terminalID:e=y(12)})=>o(this,void 0,void 0,(function*(){const[n,r]=yield this.handleSubscriptions(this.subscribe(v,s,"onData",e),i?this.subscribe(v,i,"onChildProcessesChange",e):void 0);try{yield this.call(v,"start",[e,t.cols,t.rows])}catch(s){const i=d(yield Promise.allSettled([this.unsubscribe(n),r?this.unsubscribe(r):void 0]));throw i&&this.logger.error(i),s}return{terminalID:e,destroy:()=>o(this,void 0,void 0,(function*(){!function(s){if(s.some((s=>"rejected"===s.status)))throw new Error(d(s));s.filter(c).map((s=>s.value))}(yield Promise.allSettled([this.unsubscribe(n),r?this.unsubscribe(r):void 0,yield this.call(v,"destroy",[e])]))})),sendData:s=>o(this,void 0,void 0,(function*(){yield this.call(v,"data",[e,s])})),resize:({cols:s,rows:i})=>o(this,void 0,void 0,(function*(){yield this.call(v,"resize",[e,s,i])}))}}))},this.process={start:({cmd:s,onStdout:i,onStderr:t,onExit:e,envVars:n={},rootdir:r="/",processID:l=y(12)})=>o(this,void 0,void 0,(function*(){const{promise:c,resolve:u}=h(),[a,p,g]=yield this.handleSubscriptions(this.subscribe(b,u,"onExit",l),i?this.subscribe(b,i,"onStdout",l):void 0,t?this.subscribe(b,t,"onStderr",l):void 0),{promise:v,resolve:f}=h();c.then((()=>o(this,void 0,void 0,(function*(){const s=d(yield Promise.allSettled([this.unsubscribe(a),p?this.unsubscribe(p):void 0,g?this.unsubscribe(g):void 0]));s&&this.logger.error(s),null==e||e(),f()}))));try{yield this.call(b,"start",[l,s,n,r])}catch(s){throw u(),yield v,s}return{processID:l,kill:()=>o(this,void 0,void 0,(function*(){try{yield this.call(b,"kill",[l])}finally{u(),yield v}})),sendStdin:s=>o(this,void 0,void 0,(function*(){yield this.call(b,"stdin",[l,s])}))}}))}}))}},s.api=n,Object.defineProperty(s,"__esModule",{value:!0})}));
//# sourceMappingURL=index.js.map
import { OutStderrResponse, OutStdoutResponse } from './out';
import { EnvVars } from './envVars';
export declare const codeSnippetMethod = "codeSnippet";
export declare const codeSnippetService = "codeSnippet";
export declare enum CodeSnippetExecState {

@@ -5,0 +5,0 @@ Running = "Running",

@@ -1,2 +0,2 @@

export declare const filesystemMethod = "filesystem";
export declare const filesystemService = "filesystem";
export interface FileInfo {

@@ -3,0 +3,0 @@ isDir: boolean;

import { EnvVars } from './envVars';
import { OutStdoutResponse, OutStderrResponse } from './out';
export declare const processMethod = "process";
export declare const processService = "process";
export interface Process {

@@ -5,0 +5,0 @@ readonly sendStdin: (data: string) => Promise<void>;

import { components } from '../api';
import Logger from '../utils/logger';
import { processService } from './process';
import { codeSnippetService } from './codeSnippet';
import { filesystemService } from './filesystem';
import { terminalService } from './terminal';
declare type SubscriptionHandler = (result: any) => void;
declare type Service = typeof processService | typeof codeSnippetService | typeof filesystemService | typeof terminalService;
export declare type CloseHandler = () => void;

@@ -26,5 +31,8 @@ export declare type DisconnectHandler = () => void;

constructor(opts: SessionConnectionOpts);
protected call(method: string, params?: any[]): Promise<unknown>;
protected unsubscribe(subscriptionID: string): Promise<void>;
protected subscribe(method: string, handler: SubscriptionHandler, ...params: any): Promise<string>;
protected call(service: Service, method: string, params?: any[]): Promise<unknown>;
protected handleSubscriptions<T extends (ReturnType<SessionConnection['subscribe']> | undefined)[]>(...subs: T): Promise<{
[P in keyof T]: Awaited<T[P]>;
}>;
protected unsubscribe(subID: string): Promise<void>;
protected subscribe(service: Service, handler: SubscriptionHandler, method: string, ...params: any[]): Promise<string>;
/**

@@ -31,0 +39,0 @@ * Get the hostname for the session or for the specified session's port.

@@ -1,2 +0,2 @@

export declare const terminalMethod = "terminal";
export declare const terminalService = "terminal";
export interface TerminalSession {

@@ -24,4 +24,4 @@ readonly sendData: (data: string) => Promise<void>;

};
activeTerminalID?: string;
terminalID?: string;
}) => Promise<TerminalSession>;
}
{
"name": "@devbookhq/sdk",
"version": "2.4.5",
"version": "2.5.0",
"description": "Devbook allows visitors of your docs to interact with and execute any code snippet or shell command in a private VM",

@@ -30,14 +30,14 @@ "homepage": "https://usedevbook.com",

"devDependencies": {
"@rollup/plugin-node-resolve": "^13.3.0",
"@types/node": "^18.7.8",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"eslint": "^8.22.0",
"@rollup/plugin-node-resolve": "^14.1.0",
"@types/node": "^18.7.20",
"@typescript-eslint/eslint-plugin": "^5.38.0",
"@typescript-eslint/parser": "^5.38.0",
"eslint": "^8.24.0",
"openapi-typescript": "^5.4.1",
"rollup": "^2.78.1",
"rollup": "^2.79.1",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-polyfill-node": "^0.10.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.33.0",
"typescript": "^4.7.4"
"rollup-plugin-typescript2": "^0.34.0",
"typescript": "^4.8.3"
},

@@ -44,0 +44,0 @@ "files": [

@@ -60,7 +60,1 @@ # Devbook SDK

```
## Performance
Every 8 hours runs an automated CRON on GitHub that measures time to acquire a session. You can inspect the performance summaries in the GH Actions' details - in the workflow "Measure performance".
You can also trigger this workflow manually.
> The GitHub Actions CRON is not very reliable so don't rely it on running every 8 hours.

@@ -7,3 +7,3 @@ import {

export const codeSnippetMethod = 'codeSnippet'
export const codeSnippetService = 'codeSnippet'

@@ -10,0 +10,0 @@ export enum CodeSnippetExecState {

@@ -1,2 +0,2 @@

export const filesystemMethod = 'filesystem'
export const filesystemService = 'filesystem'

@@ -3,0 +3,0 @@ export interface FileInfo {

@@ -9,3 +9,3 @@ import SessionConnection, {

CodeSnippetStdoutHandler,
codeSnippetMethod,
codeSnippetService,
CodeSnippetExecState,

@@ -16,14 +16,19 @@ ScanOpenedPortsHandler,

TerminalManager,
terminalMethod,
terminalService,
} from './terminal'
import {
FilesystemManager,
filesystemMethod,
FileInfo,
filesystemService,
} from './filesystem'
import {
ProcessManager,
processMethod,
processService,
} from './process'
import { id } from '../utils/id'
import {
createDeferredPromise,
evaluateSettledPromises,
formatSettledErrors,
} from '../utils/promise'

@@ -54,19 +59,20 @@ export interface CodeSnippetOpts {

async open() {
await super.open()
await Promise.all([
await this.handleSubscriptions(
this.codeSnippetOpts?.onStateChange
? this.subscribe(codeSnippetMethod, this.codeSnippetOpts.onStateChange, 'state')
? this.subscribe(codeSnippetService, this.codeSnippetOpts.onStateChange, 'state')
: undefined,
this.codeSnippetOpts?.onStderr
? this.subscribe(codeSnippetMethod, this.codeSnippetOpts.onStderr, 'stderr')
? this.subscribe(codeSnippetService, this.codeSnippetOpts.onStderr, 'stderr')
: undefined,
this.codeSnippetOpts?.onStdout
? this.subscribe(codeSnippetMethod, this.codeSnippetOpts.onStdout, 'stdout')
? this.subscribe(codeSnippetService, this.codeSnippetOpts.onStdout, 'stdout')
: undefined,
this.codeSnippetOpts?.onScanPorts
? this.subscribe(codeSnippetMethod, this.codeSnippetOpts.onScanPorts, 'scanOpenedPorts')
? this.subscribe(codeSnippetService, this.codeSnippetOpts.onScanPorts, 'scanOpenedPorts')
: undefined,
])
)

@@ -76,3 +82,3 @@ // Init CodeSnippet handler

run: async (code, envVars = {}) => {
const state = await this.call(`${codeSnippetMethod}_run`, [code, envVars]) as CodeSnippetExecState
const state = await this.call(codeSnippetService, 'run', [code, envVars]) as CodeSnippetExecState
this.codeSnippetOpts?.onStateChange?.(state)

@@ -82,3 +88,3 @@ return state

stop: async () => {
const state = await this.call(`${codeSnippetMethod}_stop`) as CodeSnippetExecState
const state = await this.call(codeSnippetService, 'stop') as CodeSnippetExecState
this.codeSnippetOpts?.onStateChange?.(state)

@@ -92,12 +98,12 @@ return state

listAllFiles: async (path) => {
return await this.call(`${filesystemMethod}_listAllFiles`, [path]) as FileInfo[]
return await this.call(filesystemService, 'listAllFiles', [path]) as FileInfo[]
},
removeFile: async (path) => {
await this.call(`${filesystemMethod}_removeFile`, [path])
await this.call(filesystemService, 'removeFile', [path])
},
writeFile: async (path, content) => {
await this.call(`${filesystemMethod}_writeFile`, [path, content])
await this.call(filesystemService, 'writeFile', [path, content])
},
readFile: async (path) => {
return await this.call(`${filesystemMethod}_readFile`, [path]) as string
return await this.call(filesystemService, 'readFile', [path]) as string
},

@@ -109,32 +115,50 @@ }

killProcess: async (pid) => {
await this.call(`${terminalMethod}_killProcess`, [pid])
await this.call(terminalService, 'killProcess', [pid])
},
createSession: async ({ onData, onChildProcessesChange, size, activeTerminalID }) => {
const terminalID = await this.call(`${terminalMethod}_start`, [activeTerminalID ? activeTerminalID : '', size.cols, size.rows])
if (typeof terminalID !== 'string') {
throw new Error('Cannot initialize terminal')
createSession: async ({
onData,
onChildProcessesChange,
size,
terminalID = id(12),
}) => {
const [
onDataSubID,
onChildProcessesChangeSubID,
] = await this.handleSubscriptions(
this.subscribe(terminalService, onData, 'onData', terminalID),
onChildProcessesChange ? this.subscribe(terminalService, onChildProcessesChange, 'onChildProcessesChange', terminalID) : undefined,
)
try {
await this.call(terminalService, 'start', [terminalID, size.cols, size.rows])
} catch (err) {
const results = await Promise.allSettled([
this.unsubscribe(onDataSubID),
onChildProcessesChangeSubID ? this.unsubscribe(onChildProcessesChangeSubID) : undefined,
])
const errMsg = formatSettledErrors(results)
if (errMsg) {
this.logger.error(errMsg)
}
throw err
}
const [
onDataSubscriptionID,
onChildProcessesChangeSubscriptionID,
] = await Promise.all([
this.subscribe(terminalMethod, onData, 'onData', terminalID),
onChildProcessesChange ? this.subscribe(terminalMethod, onChildProcessesChange, 'onChildProcessesChange', terminalID) : undefined,
])
return {
terminalID,
destroy: async () => {
await Promise.all([
this.unsubscribe(onDataSubscriptionID),
onChildProcessesChangeSubscriptionID ? this.unsubscribe(onChildProcessesChangeSubscriptionID) : undefined,
await this.call(`${terminalMethod}_destroy`, [terminalID])
const results = await Promise.allSettled([
this.unsubscribe(onDataSubID),
onChildProcessesChangeSubID ? this.unsubscribe(onChildProcessesChangeSubID) : undefined,
await this.call(terminalService, 'destroy', [terminalID])
])
evaluateSettledPromises(results)
},
sendData: async (data) => {
await this.call(`${terminalMethod}_data`, [terminalID, data])
await this.call(terminalService, 'data', [terminalID, data])
},
resize: async ({ cols, rows }) => {
await this.call(`${terminalMethod}_resize`, [terminalID, cols, rows])
await this.call(terminalService, 'resize', [terminalID, cols, rows])
},

@@ -154,33 +178,61 @@ }

rootdir = '/',
// TODO: If the process or one of the subscriptions fails to register we are currently not unsubscribing from the others
// We are generating process ID in the SDK because we need to subscribe to the process stdout/stderr before starting it.
processID = id(12),
}) => {
const {
promise: processExited,
resolve: triggerExit,
} = createDeferredPromise()
const [
onExitSubscriptionID,
onStdoutSubscriptionID,
onStderrSubscriptionID,
] = await Promise.all([
onExit ? this.subscribe(processMethod, onExit, 'onExit', processID) : undefined,
onStdout ? this.subscribe(processMethod, onStdout, 'onStdout', processID) : undefined,
onStderr ? this.subscribe(processMethod, onStderr, 'onStderr', processID) : undefined,
])
onExitSubID,
onStdoutSubID,
onStderrSubID,
] = await this.handleSubscriptions(
this.subscribe(processService, triggerExit, 'onExit', processID),
onStdout ? this.subscribe(processService, onStdout, 'onStdout', processID) : undefined,
onStderr ? this.subscribe(processService, onStderr, 'onStderr', processID) : undefined,
)
await this.call(`${processMethod}_start`, [processID, cmd, envVars, rootdir])
const {
promise: unsubscribing,
resolve: handleFinishUnsubscribing,
} = createDeferredPromise()
processExited.then(async () => {
const results = await Promise.allSettled([
this.unsubscribe(onExitSubID),
onStdoutSubID ? this.unsubscribe(onStdoutSubID) : undefined,
onStderrSubID ? this.unsubscribe(onStderrSubID) : undefined,
])
const errMsg = formatSettledErrors(results)
if (errMsg) {
this.logger.error(errMsg)
}
onExit?.()
handleFinishUnsubscribing()
})
try {
await this.call(processService, 'start', [processID, cmd, envVars, rootdir])
} catch (err) {
triggerExit()
await unsubscribing
throw err
}
return {
processID,
kill: async () => {
if (onExitSubscriptionID) await this.unsubscribe(onExitSubscriptionID)
await Promise.all([
onStdoutSubscriptionID ? this.unsubscribe(onStdoutSubscriptionID) : undefined,
onStderrSubscriptionID ? this.unsubscribe(onStderrSubscriptionID) : undefined,
this.call(`${processMethod}_kill`, [processID]),
])
onExit?.()
try {
await this.call(processService, 'kill', [processID])
} finally {
triggerExit()
await unsubscribing
}
},
sendStdin: async (data) => {
await this.call(`${processMethod}_stdin`, [processID, data])
await this.call(processService, 'stdin', [processID, data])
},

@@ -187,0 +239,0 @@ }

@@ -7,3 +7,3 @@ import { EnvVars } from './envVars'

export const processMethod = 'process'
export const processService = 'process'

@@ -10,0 +10,0 @@ export interface Process {

@@ -18,2 +18,10 @@ import {

import Logger from '../utils/logger'
import { processService } from './process'
import { codeSnippetService } from './codeSnippet'
import { filesystemService } from './filesystem'
import { terminalService } from './terminal'
import {
assertFulfilled,
formatSettledErrors,
} from '../utils/promise'

@@ -23,6 +31,11 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any

type Service = typeof processService
| typeof codeSnippetService
| typeof filesystemService
| typeof terminalService
interface Subscriber {
subscriptionID: string
service: Service
subID: string
handler: SubscriptionHandler
method: string
}

@@ -63,32 +76,49 @@

// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected async call(method: string, params?: any[]) {
return this.rpc.call(method, params)
protected async call(service: Service, method: string, params?: any[]) {
this.logger.log(`${service}_${method}`, params)
return this.rpc.call(`${service}_${method}`, params)
}
protected async unsubscribe(subscriptionID: string) {
const subscription = this.subscribers.find(s => s.subscriptionID === subscriptionID)
protected async handleSubscriptions<T extends (ReturnType<SessionConnection['subscribe']> | undefined)[]>(...subs: T): Promise<{ [P in keyof T]: Awaited<T[P]> }> {
const results = await Promise.allSettled(subs)
if (results.every(r => r.status === 'fulfilled')) {
return results.map(r => r.status === 'fulfilled' ? r.value : undefined) as { [P in keyof T]: Awaited<T[P]> }
}
await Promise.all(
results
.filter(assertFulfilled)
.map(r => r.value ? this.unsubscribe(r.value) : undefined)
)
throw new Error(formatSettledErrors(results))
}
protected async unsubscribe(subID: string) {
const subscription = this.subscribers.find(s => s.subID === subID)
if (!subscription) return
await this.call(`${subscription.method}_unsubscribe`, [subscription?.subscriptionID])
await this.call(subscription.service, 'unsubscribe', [subscription.subID])
this.subscribers = this.subscribers.filter(s => s !== subscription)
this.logger.log(`Unsubscribed from "${subscription.method}"`)
this.logger.log(`Unsubscribed from "${subscription.service}"`)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected async subscribe(method: string, handler: SubscriptionHandler, ...params: any) {
const subscriptionID = await this.call(`${method}_subscribe`, params)
protected async subscribe(service: Service, handler: SubscriptionHandler, method: string, ...params: any[]) {
const subID = await this.call(service, 'subscribe', [method, ...params])
if (typeof subscriptionID !== 'string') {
throw new Error(`Cannot subscribe to ${method} with params ${params}. Expected response to be a subscription ID, instead got ${JSON.stringify(subscriptionID)}`)
if (typeof subID !== 'string') {
throw new Error(`Cannot subscribe to ${service}_${method}${params.length > 0 ? ' with params [' + params.join(', ') + ']' : ''}. Expected response should have been a subscription ID, instead we got ${JSON.stringify(subID)}`)
}
this.subscribers.push({
subscriptionID,
subID,
handler,
method,
service,
})
this.logger.log(`Subscribed to "${method}_${params}" with id "${subscriptionID}"`)
this.logger.log(`Subscribed to "${service}_${method}"${params.length > 0 ? ' with params [' + params.join(', ') + '] and' : ''} with id "${subID}"`)
return subscriptionID
return subID
}

@@ -140,3 +170,3 @@

const results = await Promise.allSettled(
this.subscribers.map(s => this.unsubscribe(s.subscriptionID)),
this.subscribers.map(s => this.unsubscribe(s.subID)),
)

@@ -237,2 +267,5 @@ results.forEach(r => {

try {
// When the WS connection closes the subscribers in devbookd are removed.
// We want to delete the subscriber handlers here so there are no orphans.
this.subscribers = []
await this.rpc.connect(sessionURL)

@@ -266,3 +299,3 @@ this.opts.onReconnect?.()

this.subscribers
.filter(s => s.subscriptionID === data.params?.subscription)
.filter(s => s.subID === data.params?.subscription)
.forEach(s => s.handler(data.params?.result))

@@ -269,0 +302,0 @@ }

@@ -1,2 +0,2 @@

export const terminalMethod = 'terminal'
export const terminalService = 'terminal'

@@ -21,4 +21,4 @@ export interface TerminalSession {

size: { cols: number, rows: number },
activeTerminalID?: string,
terminalID?: string,
}) => Promise<TerminalSession>
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc