@membranehq/cli 0.10.2 → 0.10.3
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/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -137,7 +137,7 @@ ${t.comment}`:t.comment}this.doc.range[2]=t.offset;break}default:this.errors.pus
|
|
|
137
137
|
`)+1;for(;t!==0;)this.onNewLine(this.offset+t),t=this.source.indexOf(`
|
|
138
138
|
`,t)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(e){const t=e.items[e.items.length-1];switch(this.type){case"newline":if(this.onKeyLine=!1,t.value){const n="end"in t.value?t.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type==="comment"?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case"space":case"comment":if(t.value)e.items.push({start:[this.sourceToken]});else if(t.sep)t.sep.push(this.sourceToken);else{if(this.atIndentedComment(t.start,e.indent)){const i=e.items[e.items.length-2]?.value?.end;if(Array.isArray(i)){Array.prototype.push.apply(i,t.start),i.push(this.sourceToken),e.items.pop();return}}t.start.push(this.sourceToken)}return}if(this.indent>=e.indent){const n=!this.onKeyLine&&this.indent===e.indent,i=n&&(t.sep||t.explicitKey)&&this.type!=="seq-item-ind";let r=[];if(i&&t.sep&&!t.value){const o=[];for(let a=0;a<t.sep.length;++a){const l=t.sep[a];switch(l.type){case"newline":o.push(a);break;case"space":break;case"comment":l.indent>e.indent&&(o.length=0);break;default:o.length=0}}o.length>=2&&(r=t.sep.splice(o[1]))}switch(this.type){case"anchor":case"tag":i||t.value?(r.push(this.sourceToken),e.items.push({start:r}),this.onKeyLine=!0):t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case"explicit-key-ind":!t.sep&&!t.explicitKey?(t.start.push(this.sourceToken),t.explicitKey=!0):i||t.value?(r.push(this.sourceToken),e.items.push({start:r,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(t.explicitKey)if(t.sep)if(t.value)e.items.push({start:[],key:null,sep:[this.sourceToken]});else if(ve(t.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:r,key:null,sep:[this.sourceToken]}]});else if(Oi(t.key)&&!ve(t.sep,"newline")){const o=Ve(t.start),a=t.key,l=t.sep;l.push(this.sourceToken),delete t.key,delete t.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:o,key:a,sep:l}]})}else r.length>0?t.sep=t.sep.concat(r,this.sourceToken):t.sep.push(this.sourceToken);else if(ve(t.start,"newline"))Object.assign(t,{key:null,sep:[this.sourceToken]});else{const o=Ve(t.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:o,key:null,sep:[this.sourceToken]}]})}else t.sep?t.value||i?e.items.push({start:r,key:null,sep:[this.sourceToken]}):ve(t.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):t.sep.push(this.sourceToken):Object.assign(t,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{const o=this.flowScalar(this.type);i||t.value?(e.items.push({start:r,key:o,sep:[]}),this.onKeyLine=!0):t.sep?this.stack.push(o):(Object.assign(t,{key:o,sep:[]}),this.onKeyLine=!0);return}default:{const o=this.startBlockValue(e);if(o){if(o.type==="block-seq"){if(!t.explicitKey&&t.sep&&!ve(t.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else n&&e.items.push({start:r});this.stack.push(o);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(e){const t=e.items[e.items.length-1];switch(this.type){case"newline":if(t.value){const n="end"in t.value?t.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type==="comment"?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else t.start.push(this.sourceToken);return;case"space":case"comment":if(t.value)e.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(t.start,e.indent)){const i=e.items[e.items.length-2]?.value?.end;if(Array.isArray(i)){Array.prototype.push.apply(i,t.start),i.push(this.sourceToken),e.items.pop();return}}t.start.push(this.sourceToken)}return;case"anchor":case"tag":if(t.value||this.indent<=e.indent)break;t.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==e.indent)break;t.value||ve(t.start,"seq-item-ind")?e.items.push({start:[this.sourceToken]}):t.start.push(this.sourceToken);return}if(this.indent>e.indent){const n=this.startBlockValue(e);if(n){this.stack.push(n);return}}yield*this.pop(),yield*this.step()}*flowCollection(e){const t=e.items[e.items.length-1];if(this.type==="flow-error-end"){let n;do yield*this.pop(),n=this.peek(1);while(n&&n.type==="flow-collection")}else if(e.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!t||t.sep?e.items.push({start:[this.sourceToken]}):t.start.push(this.sourceToken);return;case"map-value-ind":!t||t.value?e.items.push({start:[],key:null,sep:[this.sourceToken]}):t.sep?t.sep.push(this.sourceToken):Object.assign(t,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!t||t.value?e.items.push({start:[this.sourceToken]}):t.sep?t.sep.push(this.sourceToken):t.start.push(this.sourceToken);return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{const i=this.flowScalar(this.type);!t||t.value?e.items.push({start:[],key:i,sep:[]}):t.sep?this.stack.push(i):Object.assign(t,{key:i,sep:[]});return}case"flow-map-end":case"flow-seq-end":e.end.push(this.sourceToken);return}const n=this.startBlockValue(e);n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{const n=this.peek(2);if(n.type==="block-map"&&(this.type==="map-value-ind"&&n.indent===e.indent||this.type==="newline"&&!n.items[n.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type==="map-value-ind"&&n.type!=="flow-collection"){const i=Qt(n),r=Ve(i);$i(e);const o=e.end.splice(1,e.end.length);o.push(this.sourceToken);const a={type:"block-map",offset:e.offset,indent:e.indent,items:[{start:r,key:e,sep:o}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=a}else yield*this.lineEnd(e)}}flowScalar(e){if(this.onNewLine){let t=this.source.indexOf(`
|
|
139
139
|
`)+1;for(;t!==0;)this.onNewLine(this.offset+t),t=this.source.indexOf(`
|
|
140
|
-
`,t)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;const t=Qt(e),n=Ve(t);return n.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;const t=Qt(e),n=Ve(t);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!=="comment"||this.indent<=t?!1:e.every(n=>n.type==="newline"||n.type==="space")}*documentEnd(e){this.type!=="doc-mode"&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;case"space":case"comment":default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}}function Li(s){const e=s.prettyErrors!==!1;return{lineCounter:s.lineCounter||e&&new Ni||null,prettyErrors:e}}c(Li,"parseOptions");function Sa(s,e={}){const{lineCounter:t,prettyErrors:n}=Li(e),i=new zn(t?.addNewLine),r=new Gn(e),o=Array.from(r.compose(i.parse(s)));if(n&&t)for(const a of o)a.errors.forEach(Wt(s,t)),a.warnings.forEach(Wt(s,t));return o.length>0?o:Object.assign([],{empty:!0},r.streamInfo())}c(Sa,"parseAllDocuments");function Di(s,e={}){const{lineCounter:t,prettyErrors:n}=Li(e),i=new zn(t?.addNewLine),r=new Gn(e);let o=null;for(const a of r.compose(i.parse(s),!0,s.length))if(!o)o=a;else if(o.options.logLevel!=="silent"){o.errors.push(new $e(a.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return n&&t&&(o.errors.forEach(Wt(s,t)),o.warnings.forEach(Wt(s,t))),o}c(Di,"parseDocument");function Ca(s,e,t){let n;typeof e=="function"?n=e:t===void 0&&e&&typeof e=="object"&&(t=e);const i=Di(s,t);if(!i)return null;if(i.warnings.forEach(r=>qs(i.options.logLevel,r)),i.errors.length>0){if(i.options.logLevel!=="silent")throw i.errors[0];i.errors=[]}return i.toJS(Object.assign({reviver:n},t))}c(Ca,"parse");function ka(s,e,t){let n=null;if(typeof e=="function"||Array.isArray(e)?n=e:t===void 0&&e&&(t=e),typeof t=="string"&&(t=t.length),typeof t=="number"){const i=Math.round(t);t=i<1?void 0:i>8?{indent:8}:{indent:i}}if(s===void 0){const{keepUndefined:i}=t??e??{};if(!i)return}return Te(s)&&!n?s.toString(t):new Qe(s,n,t).toString(t)}c(ka,"stringify");var va=Object.freeze({__proto__:null,Alias:Nt,CST:ya,Composer:Gn,Document:Qe,Lexer:Ti,LineCounter:Ni,Pair:Q,Parser:zn,Scalar:L,Schema:Zt,YAMLError:jn,YAMLMap:ne,YAMLParseError:$e,YAMLSeq:ke,YAMLWarning:hi,isAlias:Ce,isCollection:U,isDocument:Te,isMap:Re,isNode:q,isPair:F,isScalar:R,isSeq:_e,parse:Ca,parseAllDocuments:Sa,parseDocument:Di,stringify:ka,visit:Ne,visitAsync:Tt});const z={Added:"added",Changed:"changed",Deleted:"deleted",Stopped:"stopped"},Ea={ignored:uo,persistent:!0,ignoreInitial:!0,followSymlinks:!1,depth:20,awaitWriteFinish:{stabilityThreshold:500,pollInterval:100},ignorePermissionErrors:!0,atomic:!0,usePolling:!1,alwaysStat:!1,interval:1e3,binaryInterval:300};class Ia extends gs{static{c(this,"FileWatcher")}constructor(e){super(),this.options=e,this.membraneDir=It(this.options.cwd)}isWatching=!1;watcher;membraneDir;contentCache={};async start(){this.isWatching||(P.existsSync(this.membraneDir)||P.mkdirSync(this.membraneDir,{recursive:!0}),this.initializeContentCache(),this.watcher=mr.watch(this.membraneDir,Ea),this.watcher.on("add",e=>this.handleFileSystemEvent(z.Added,e)).on("change",e=>this.handleFileSystemEvent(z.Changed,e)).on("unlink",e=>this.handleFileSystemEvent(z.Deleted,e)).on("ready",()=>this.isWatching=!0))}async stop(){!this.isWatching||!this.watcher||(await this.watcher.close(),this.isWatching=!1,this.watcher=void 0,this.clearCache(),this.emit(z.Stopped))}getCwd(){return this.options.cwd}handleFileSystemEvent(e,t){const n=x.relative(this.membraneDir,t);if(e===z.Deleted){this.removeFromCache(n);const a={filePath:t,relativePath:n,data:void 0};T.info(`[local] ${e}: ${a.relativePath}`),this.emit(e,a);return}const i=this.readFileContent(t);if(!this.hasContentChanged(n,i,e))return;const o=this.processFileEvent(t,i);this.updateCache(n,i),o&&(T.info(`[local] ${e}: ${o.relativePath}`),this.emit(e,o))}readFileContent(e){return P.readFileSync(e,"utf8")}processFileEvent(e,t){const n=x.relative(this.membraneDir,e);let i;try{i=t?va.parse(t):void 0}catch{i=void 0}return{filePath:e,relativePath:n,data:i}}hasContentChanged(e,t,n){if(n==="added")return!0;if(!t)return this.contentCache[e]!==void 0;const i=this.getContentHash(t);return this.contentCache[e]!==i}getContentHash(e){return cr.createHash("sha256").update(e).digest("hex")}updateCache(e,t){if(!t){delete this.contentCache[e];return}this.contentCache[e]=this.getContentHash(t)}removeFromCache(e){delete this.contentCache[e]}clearCache(){Object.keys(this.contentCache).forEach(e=>{delete this.contentCache[e]})}initializeContentCache(){P.existsSync(this.membraneDir)&&this.scanDirectoryForCache(this.membraneDir)}scanDirectoryForCache(e){const t=P.readdirSync(e,{withFileTypes:!0});for(const n of t){const i=x.join(e,n.name);if(n.isDirectory())this.scanDirectoryForCache(i);else if(n.isFile())try{const r=P.readFileSync(i,"utf8"),o=x.relative(this.membraneDir,i);this.updateCache(o,r)}catch{}}}}class pt{static{c(this,"ElementSyncService")}constructor(e,t){this.localManager=e,this.remoteManager=t,this.notifier=ue}fileWatcher=void 0;notifier;changes=[];clear(){this.changes=[]}hasConflicts(){return this.changes.some(e=>e.isConflict)}hasChanges(){return this.changes.length>0}async startWatching(){this.fileWatcher=new Ia({cwd:process.cwd()}),this.fileWatcher.on(z.Added,e=>this.handleLocalEvent(e,z.Added)),this.fileWatcher.on(z.Changed,e=>this.handleLocalEvent(e,z.Changed)),this.fileWatcher.on(z.Deleted,e=>this.handleLocalEvent(e,z.Deleted)),await this.fileWatcher.start(),T.success("[local] Tracking changes..")}async stopWatching(){await this.fileWatcher?.stop(),this.fileWatcher=void 0}async handleLocalEvent(e,t){try{if(oo(e.filePath))switch(t){case z.Added:case z.Changed:await ao(e.filePath);break;case z.Deleted:await co(e.filePath);break}else{let n=V.fromPathAndData(e.filePath,e.data);if(!n){const r=V.idFromPath(e.filePath);if(!r||(n=this.remoteManager.cache.get(r),!n))return}const i=this.getManager(fe.OUTGOING);switch(T.info(`[resolver][${this.getDirectionLabel(fe.OUTGOING)}] ${t}: ${n.id}`),t){case z.Added:case z.Changed:await i.putElement(n);break;case z.Deleted:await i.deleteElement(n);break}}}catch(n){T.error(`[sync] Error handling local event: ${n}`)}}detectIncomingChanges(){this.clearChanges();const e=pt.getChanges(fe.INCOMING,this.remoteManager.cache,this.localManager.cache);return this.updateChanges(e),e}detectOutgoingChanges(){this.clearChanges();const e=pt.getChanges(fe.OUTGOING,this.localManager.cache,this.remoteManager.cache);return this.updateChanges(e),e}getChange(e){const t=this.localManager.cache.get(e.id),n=this.remoteManager.cache.get(e.id);return!t&&n?{type:X.CREATE,element:n,direction:fe.INCOMING,isConflict:!1}:t&&!n?{type:X.DELETE,element:t,direction:fe.OUTGOING,isConflict:!0}:t&&n&&!t.isEqual(n)?{type:X.UPDATE,element:t,direction:fe.OUTGOING,isConflict:!0}:null}async resolveChanges(){this.hasChanges()&&(T.info("[resolver] Resolving changes.."),await Promise.all(this.changes.map(e=>this.resolveChange(e))),T.success(`[resolver] Resolved ${this.changes.length} changes`))}async resolveChange(e){const t=this.getManager(e.direction);switch(e.type){case X.DELETE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Deleting ${e.element.id}`),t.deleteElement(e.element);case X.CREATE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Creating ${e.element.id}`),t.putElement(e.element);case X.UPDATE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Updating ${e.element.id}`),t.putElement(e.element)}}getManager(e){return e===fe.INCOMING?this.localManager:this.remoteManager}static getChanges(e,t,n){const i=t.getAllIds(),r=n.getAllIds(),o=new Set([...i,...r]),a=[];for(const l of o){const u=t.get(l),p=n.get(l),d=pt.detectChangeForElement(u,p,e);d&&a.push(d)}return a}updateChanges(e){this.changes=e;for(const t of e)T.info(`[resolver][${this.getDirectionLabel(t.direction)}] ${this.getTypeLabel(t.type)} ${t.element.id}`);if(this.hasConflicts()){const t=e.filter(n=>n.isConflict);T.warning("[resolver] Conflicts detected"),this.notifier.setConflicts(t)}}clearChanges(){this.changes=[]}getDirectionLabel(e){switch(e){case fe.INCOMING:return"local\u2190remote";case fe.OUTGOING:return"local\u2192remote"}}getTypeLabel(e){switch(e){case X.CREATE:return"ADD";case X.UPDATE:return"UPD";case X.DELETE:return"DEL"}}static detectChangeForElement(e,t,n){return e&&!t?{type:X.CREATE,element:e,direction:n,isConflict:!1}:!e&&t?{type:X.DELETE,element:t,direction:n,isConflict:!0}:e&&t&&!e.isEqual(t)?{type:X.UPDATE,element:e,direction:n,isConflict:!0}:null}}class Pi{static{c(this,"WorkspaceService")}notifier;local;remote;syncService;constructor(){this.notifier=ue,this.local=new Is(new ho),this.remote=new Is(new po),this.syncService=new pt(this.local,this.remote)}async reset(){this.local.cache.clear(),this.remote.cache.clear(),this.updateStats(),this.syncService.clear()}async push(e={}){await this.notifier.setState(D.PUSHING);try{await this.refreshElements()}catch(n){return T.error(`Failed to refresh elements: ${te(n)?.message??"Unknown error"}`),e?.onComplete?.()}if(this.syncService.detectOutgoingChanges(),this.syncService.hasConflicts()&&!e.force)return await this.notifier.setState(D.CONFLICTS);const t=await eo();this.remote.setConnectorsMapping(t),await this.syncLocalAndRemoteWorkspaces({watch:e.watch})}async notifyRemote(){await this.notifier.connectToRemote()}async pull(e={}){await this.notifier.setState(D.PULLING);try{await this.refreshElements()}catch(t){return T.error(`Failed to refresh elements: ${te(t)?.message??"Unknown error"}`),e?.onComplete?.()}if(this.syncService.detectIncomingChanges(),this.syncService.hasConflicts()&&!e.force)return this.notifier.setState(D.CONFLICTS);await Zr({integrations:this.remote.cache.getElementsByType(K.Integration).map(t=>t.data),allConnectors:e.allConnectors}),await this.syncLocalAndRemoteWorkspaces({watch:e.watch})}async syncLocalAndRemoteWorkspaces(e={}){await this.notifier.setState(D.RESOLVING),this.syncService.hasChanges()&&await this.syncService.resolveChanges(),this.updateStats(),await this.notifier.setState(D.SYNCED),e.watch&&(await this.notifier.setState(D.WATCHING),await this.syncService.startWatching()),e.onComplete?.()}async refreshElements(){return Promise.all([this.remote.refresh(),this.local.refresh()])}updateStats(){const e={};for(const t of this.local.cache.getAll())e[t.type]=(e[t.type]||0)+1;this.notifier.setStats(e)}}new Pi;const dt={Agent:"agent",Cli:"cli"};class xi{static{c(this,"MembraneCLIService")}constructor(e,t,n=()=>process.exit(0)){this.mode=e,this.cwd=t,this.onShutdown=n,this.notifications=ue,this.workspaceService=new Pi,this.mcpStatusService=new Yr,this.setupProcessCleanup()}initialized=!1;notifications;workspaceService;mcpStatusService;isShuttingDown=!1;currentConfig=null;get config(){return this.currentConfig}async pullWorkspace(e={}){try{return this.workspaceService.pull(e)}catch(t){throw T.error(`Failed to pull workspace: ${t}`),t}}async pushWorkspace(e={}){try{return this.workspaceService.push(e)}catch(t){throw T.error(`Failed to push workspace: ${t}`),t}}async syncWorkspaces(e={}){try{return this.workspaceService.syncLocalAndRemoteWorkspaces(e)}catch(t){throw T.error(`Failed to sync workspaces: ${t}`),t}}async init({force:e=!1}={}){if(!(this.initialized&&!e)){await this.notifications.setState(D.NOT_INITIALIZED);try{await this.loadConfig(),Ze.isCacheDefined(this.currentConfig)?(await this.initServices(),this.initialized=!0,await this.notifications.setState(D.INITIALIZED)):(this.initialized=!1,await this.notifications.setState(D.SETTING_UP))}catch(t){T.error(`Failed to initialize services: ${t}`),await this.notifications.setState(D.ERROR),this.onShutdown()}}}async loadConfig(){this.currentConfig=Ze.loadConfig(this.cwd),this.notifications.setConfig(this.currentConfig)}async updateConfig(e){const t={...this.currentConfig,...e};if(!(JSON.stringify(t)!==JSON.stringify(this.currentConfig)))return;await this.stopServices();const i=Ze.updateConfig(t);this.currentConfig=i,await this.init({force:!0})}async shutdown(){!this.initialized||this.isShuttingDown||(this.isShuttingDown=!0,this.mode===dt.Agent&&(await this.notifications.cleanup(),await this.mcpStatusService.stop()),this.initialized=!1,this.onShutdown())}async initServices(){this.mode===dt.Agent&&(await this.notifications.connectToRemote(),await this.mcpStatusService.start()),await this.workspaceService.reset()}async stopServices(){this.mode===dt.Agent&&(await this.notifications.cleanup(),await this.mcpStatusService.stop())}setupProcessCleanup(){["SIGINT","SIGTERM","uncaughtException","unhandledRejection"].forEach(t=>process.on(t,()=>this.shutdown())),process.on("beforeExit",t=>{t===0&&this.shutdown()})}}const Mi=Hi(process.argv.slice(2)),Ri=Mi.cwd?Wi(Mi.cwd):process.cwd(),Ta=new xi(dt.Agent,Ri),Na=c(()=>m(wt,{cwd:Ri,membraneCLIService:Ta,children:m(Vr,{})}),"App");function Aa(){mt(m(Na,{}))}c(Aa,"runAgent");function Oa(s,e){s.command("init").description("Run interactive setup for Membrane project").option("--key <key>","Workspace key for non-interactive setup").option("--secret <secret>","Workspace secret for non-interactive setup").addHelpText("after",["","Examples:"," membrane init # Run interactive setup"," membrane init --key KEY --secret SEC # Non-interactive setup with key and secret",""].join(`
|
|
140
|
+
`,t)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;const t=Qt(e),n=Ve(t);return n.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;const t=Qt(e),n=Ve(t);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!=="comment"||this.indent<=t?!1:e.every(n=>n.type==="newline"||n.type==="space")}*documentEnd(e){this.type!=="doc-mode"&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;case"space":case"comment":default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}}function Li(s){const e=s.prettyErrors!==!1;return{lineCounter:s.lineCounter||e&&new Ni||null,prettyErrors:e}}c(Li,"parseOptions");function Sa(s,e={}){const{lineCounter:t,prettyErrors:n}=Li(e),i=new zn(t?.addNewLine),r=new Gn(e),o=Array.from(r.compose(i.parse(s)));if(n&&t)for(const a of o)a.errors.forEach(Wt(s,t)),a.warnings.forEach(Wt(s,t));return o.length>0?o:Object.assign([],{empty:!0},r.streamInfo())}c(Sa,"parseAllDocuments");function Di(s,e={}){const{lineCounter:t,prettyErrors:n}=Li(e),i=new zn(t?.addNewLine),r=new Gn(e);let o=null;for(const a of r.compose(i.parse(s),!0,s.length))if(!o)o=a;else if(o.options.logLevel!=="silent"){o.errors.push(new $e(a.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return n&&t&&(o.errors.forEach(Wt(s,t)),o.warnings.forEach(Wt(s,t))),o}c(Di,"parseDocument");function Ca(s,e,t){let n;typeof e=="function"?n=e:t===void 0&&e&&typeof e=="object"&&(t=e);const i=Di(s,t);if(!i)return null;if(i.warnings.forEach(r=>qs(i.options.logLevel,r)),i.errors.length>0){if(i.options.logLevel!=="silent")throw i.errors[0];i.errors=[]}return i.toJS(Object.assign({reviver:n},t))}c(Ca,"parse");function ka(s,e,t){let n=null;if(typeof e=="function"||Array.isArray(e)?n=e:t===void 0&&e&&(t=e),typeof t=="string"&&(t=t.length),typeof t=="number"){const i=Math.round(t);t=i<1?void 0:i>8?{indent:8}:{indent:i}}if(s===void 0){const{keepUndefined:i}=t??e??{};if(!i)return}return Te(s)&&!n?s.toString(t):new Qe(s,n,t).toString(t)}c(ka,"stringify");var va=Object.freeze({__proto__:null,Alias:Nt,CST:ya,Composer:Gn,Document:Qe,Lexer:Ti,LineCounter:Ni,Pair:Q,Parser:zn,Scalar:L,Schema:Zt,YAMLError:jn,YAMLMap:ne,YAMLParseError:$e,YAMLSeq:ke,YAMLWarning:hi,isAlias:Ce,isCollection:U,isDocument:Te,isMap:Re,isNode:q,isPair:F,isScalar:R,isSeq:_e,parse:Ca,parseAllDocuments:Sa,parseDocument:Di,stringify:ka,visit:Ne,visitAsync:Tt});const z={Added:"added",Changed:"changed",Deleted:"deleted",Stopped:"stopped"},Ea={ignored:uo,persistent:!0,ignoreInitial:!0,followSymlinks:!1,depth:20,awaitWriteFinish:{stabilityThreshold:500,pollInterval:100},ignorePermissionErrors:!0,atomic:!0,usePolling:!1,alwaysStat:!1,interval:1e3,binaryInterval:300};class Ia extends gs{static{c(this,"FileWatcher")}constructor(e){super(),this.options=e,this.membraneDir=It(this.options.cwd)}isWatching=!1;watcher;membraneDir;contentCache={};async start(){this.isWatching||(P.existsSync(this.membraneDir)||P.mkdirSync(this.membraneDir,{recursive:!0}),this.initializeContentCache(),this.watcher=mr.watch(this.membraneDir,Ea),this.watcher.on("add",e=>this.handleFileSystemEvent(z.Added,e)).on("change",e=>this.handleFileSystemEvent(z.Changed,e)).on("unlink",e=>this.handleFileSystemEvent(z.Deleted,e)).on("ready",()=>this.isWatching=!0))}async stop(){!this.isWatching||!this.watcher||(await this.watcher.close(),this.isWatching=!1,this.watcher=void 0,this.clearCache(),this.emit(z.Stopped))}getCwd(){return this.options.cwd}handleFileSystemEvent(e,t){const n=x.relative(this.membraneDir,t);if(e===z.Deleted){this.removeFromCache(n);const a={filePath:t,relativePath:n,data:void 0};T.info(`[local] ${e}: ${a.relativePath}`),this.emit(e,a);return}const i=this.readFileContent(t);if(!this.hasContentChanged(n,i,e))return;const o=this.processFileEvent(t,i);this.updateCache(n,i),o&&(T.info(`[local] ${e}: ${o.relativePath}`),this.emit(e,o))}readFileContent(e){return P.readFileSync(e,"utf8")}processFileEvent(e,t){const n=x.relative(this.membraneDir,e);let i;try{i=t?va.parse(t):void 0}catch{i=void 0}return{filePath:e,relativePath:n,data:i}}hasContentChanged(e,t,n){if(n==="added")return!0;if(!t)return this.contentCache[e]!==void 0;const i=this.getContentHash(t);return this.contentCache[e]!==i}getContentHash(e){return cr.createHash("sha256").update(e).digest("hex")}updateCache(e,t){if(!t){delete this.contentCache[e];return}this.contentCache[e]=this.getContentHash(t)}removeFromCache(e){delete this.contentCache[e]}clearCache(){Object.keys(this.contentCache).forEach(e=>{delete this.contentCache[e]})}initializeContentCache(){P.existsSync(this.membraneDir)&&this.scanDirectoryForCache(this.membraneDir)}scanDirectoryForCache(e){const t=P.readdirSync(e,{withFileTypes:!0});for(const n of t){const i=x.join(e,n.name);if(n.isDirectory())this.scanDirectoryForCache(i);else if(n.isFile())try{const r=P.readFileSync(i,"utf8"),o=x.relative(this.membraneDir,i);this.updateCache(o,r)}catch{}}}}class pt{static{c(this,"ElementSyncService")}constructor(e,t){this.localManager=e,this.remoteManager=t,this.notifier=ue}fileWatcher=void 0;notifier;changes=[];clear(){this.changes=[]}hasConflicts(){return this.changes.some(e=>e.isConflict)}hasChanges(){return this.changes.length>0}async startWatching(){this.fileWatcher=new Ia({cwd:process.cwd()}),this.fileWatcher.on(z.Added,e=>this.handleLocalEvent(e,z.Added)),this.fileWatcher.on(z.Changed,e=>this.handleLocalEvent(e,z.Changed)),this.fileWatcher.on(z.Deleted,e=>this.handleLocalEvent(e,z.Deleted)),await this.fileWatcher.start(),T.success("[local] Tracking changes..")}async stopWatching(){await this.fileWatcher?.stop(),this.fileWatcher=void 0}async handleLocalEvent(e,t){try{if(oo(e.filePath))switch(t){case z.Added:case z.Changed:await ao(e.filePath);break;case z.Deleted:await co(e.filePath);break}else{let n=V.fromPathAndData(e.filePath,e.data);if(!n){const r=V.idFromPath(e.filePath);if(!r||(n=this.remoteManager.cache.get(r),!n))return}const i=this.getManager(fe.OUTGOING);switch(T.info(`[resolver][${this.getDirectionLabel(fe.OUTGOING)}] ${t}: ${n.id}`),t){case z.Added:case z.Changed:await i.putElement(n);break;case z.Deleted:await i.deleteElement(n);break}}}catch(n){T.error(`[sync] Error handling local event: ${n}`)}}detectIncomingChanges(){this.clearChanges();const e=pt.getChanges(fe.INCOMING,this.remoteManager.cache,this.localManager.cache);return this.updateChanges(e),e}detectOutgoingChanges(){this.clearChanges();const e=pt.getChanges(fe.OUTGOING,this.localManager.cache,this.remoteManager.cache);return this.updateChanges(e),e}getChange(e){const t=this.localManager.cache.get(e.id),n=this.remoteManager.cache.get(e.id);return!t&&n?{type:X.CREATE,element:n,direction:fe.INCOMING,isConflict:!1}:t&&!n?{type:X.DELETE,element:t,direction:fe.OUTGOING,isConflict:!0}:t&&n&&!t.isEqual(n)?{type:X.UPDATE,element:t,direction:fe.OUTGOING,isConflict:!0}:null}async resolveChanges(){this.hasChanges()&&(T.info("[resolver] Resolving changes.."),await Promise.all(this.changes.map(e=>this.resolveChange(e))),T.success(`[resolver] Resolved ${this.changes.length} changes`))}async resolveChange(e){const t=this.getManager(e.direction);switch(e.type){case X.DELETE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Deleting ${e.element.id}`),t.deleteElement(e.element);case X.CREATE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Creating ${e.element.id}`),t.putElement(e.element);case X.UPDATE:return T.info(`[resolver][${this.getDirectionLabel(e.direction)}] Updating ${e.element.id}`),t.putElement(e.element)}}getManager(e){return e===fe.INCOMING?this.localManager:this.remoteManager}static getChanges(e,t,n){const i=t.getAllIds(),r=n.getAllIds(),o=new Set([...i,...r]),a=[];for(const l of o){const u=t.get(l),p=n.get(l),d=pt.detectChangeForElement(u,p,e);d&&a.push(d)}return a}updateChanges(e){this.changes=e;for(const t of e)T.info(`[resolver][${this.getDirectionLabel(t.direction)}] ${this.getTypeLabel(t.type)} ${t.element.id}`);if(this.hasConflicts()){const t=e.filter(n=>n.isConflict);T.warning("[resolver] Conflicts detected"),this.notifier.setConflicts(t)}}clearChanges(){this.changes=[]}getDirectionLabel(e){switch(e){case fe.INCOMING:return"local\u2190remote";case fe.OUTGOING:return"local\u2192remote"}}getTypeLabel(e){switch(e){case X.CREATE:return"ADD";case X.UPDATE:return"UPD";case X.DELETE:return"DEL"}}static detectChangeForElement(e,t,n){return e&&!t?{type:X.CREATE,element:e,direction:n,isConflict:!1}:!e&&t?{type:X.DELETE,element:t,direction:n,isConflict:!0}:e&&t&&!e.isEqual(t)?{type:X.UPDATE,element:e,direction:n,isConflict:!0}:null}}class Pi{static{c(this,"WorkspaceService")}notifier;local;remote;syncService;constructor(){this.notifier=ue,this.local=new Is(new ho),this.remote=new Is(new po),this.syncService=new pt(this.local,this.remote)}async reset(){this.local.cache.clear(),this.remote.cache.clear(),this.updateStats(),this.syncService.clear()}async push(e={}){await this.notifier.setState(D.PUSHING);try{await this.refreshElements()}catch(n){return T.error(`Failed to refresh elements: ${te(n)?.message??"Unknown error"}`),e?.onComplete?.()}if(this.syncService.detectOutgoingChanges(),this.syncService.hasConflicts()&&!e.force)return await this.notifier.setState(D.CONFLICTS);const t=await eo();this.remote.setConnectorsMapping(t),await this.syncLocalAndRemoteWorkspaces(e)}async notifyRemote(){await this.notifier.connectToRemote()}async pull(e={}){await this.notifier.setState(D.PULLING);try{await this.refreshElements()}catch(t){return T.error(`Failed to refresh elements: ${te(t)?.message??"Unknown error"}`),e?.onComplete?.()}if(this.syncService.detectIncomingChanges(),this.syncService.hasConflicts()&&!e.force)return this.notifier.setState(D.CONFLICTS);await Zr({integrations:this.remote.cache.getElementsByType(K.Integration).map(t=>t.data),allConnectors:e.allConnectors}),await this.syncLocalAndRemoteWorkspaces(e)}async syncLocalAndRemoteWorkspaces(e={}){await this.notifier.setState(D.RESOLVING),this.syncService.hasChanges()&&await this.syncService.resolveChanges(),this.updateStats(),await this.notifier.setState(D.SYNCED),e.watch&&(await this.notifier.setState(D.WATCHING),await this.syncService.startWatching()),e.onComplete?.()}async refreshElements(){return Promise.all([this.remote.refresh(),this.local.refresh()])}updateStats(){const e={};for(const t of this.local.cache.getAll())e[t.type]=(e[t.type]||0)+1;this.notifier.setStats(e)}}new Pi;const dt={Agent:"agent",Cli:"cli"};class xi{static{c(this,"MembraneCLIService")}constructor(e,t,n=()=>process.exit(0)){this.mode=e,this.cwd=t,this.onShutdown=n,this.notifications=ue,this.workspaceService=new Pi,this.mcpStatusService=new Yr,this.setupProcessCleanup()}initialized=!1;notifications;workspaceService;mcpStatusService;isShuttingDown=!1;currentConfig=null;get config(){return this.currentConfig}async pullWorkspace(e={}){try{return this.workspaceService.pull(e)}catch(t){throw T.error(`Failed to pull workspace: ${t}`),t}}async pushWorkspace(e={}){try{return this.workspaceService.push(e)}catch(t){throw T.error(`Failed to push workspace: ${t}`),t}}async syncWorkspaces(e={}){try{return this.workspaceService.syncLocalAndRemoteWorkspaces(e)}catch(t){throw T.error(`Failed to sync workspaces: ${t}`),t}}async init({force:e=!1}={}){if(!(this.initialized&&!e)){await this.notifications.setState(D.NOT_INITIALIZED);try{await this.loadConfig(),Ze.isCacheDefined(this.currentConfig)?(await this.initServices(),this.initialized=!0,await this.notifications.setState(D.INITIALIZED)):(this.initialized=!1,await this.notifications.setState(D.SETTING_UP))}catch(t){T.error(`Failed to initialize services: ${t}`),await this.notifications.setState(D.ERROR),this.onShutdown()}}}async loadConfig(){this.currentConfig=Ze.loadConfig(this.cwd),this.notifications.setConfig(this.currentConfig)}async updateConfig(e){const t={...this.currentConfig,...e};if(!(JSON.stringify(t)!==JSON.stringify(this.currentConfig)))return;await this.stopServices();const i=Ze.updateConfig(t);this.currentConfig=i,await this.init({force:!0})}async shutdown(){!this.initialized||this.isShuttingDown||(this.isShuttingDown=!0,this.mode===dt.Agent&&(await this.notifications.cleanup(),await this.mcpStatusService.stop()),this.initialized=!1,this.onShutdown())}async initServices(){this.mode===dt.Agent&&(await this.notifications.connectToRemote(),await this.mcpStatusService.start()),await this.workspaceService.reset()}async stopServices(){this.mode===dt.Agent&&(await this.notifications.cleanup(),await this.mcpStatusService.stop())}setupProcessCleanup(){["SIGINT","SIGTERM","uncaughtException","unhandledRejection"].forEach(t=>process.on(t,()=>this.shutdown())),process.on("beforeExit",t=>{t===0&&this.shutdown()})}}const Mi=Hi(process.argv.slice(2)),Ri=Mi.cwd?Wi(Mi.cwd):process.cwd(),Ta=new xi(dt.Agent,Ri),Na=c(()=>m(wt,{cwd:Ri,membraneCLIService:Ta,children:m(Vr,{})}),"App");function Aa(){mt(m(Na,{}))}c(Aa,"runAgent");function Oa(s,e){s.command("init").description("Run interactive setup for Membrane project").option("--key <key>","Workspace key for non-interactive setup").option("--secret <secret>","Workspace secret for non-interactive setup").addHelpText("after",["","Examples:"," membrane init # Run interactive setup"," membrane init --key KEY --secret SEC # Non-interactive setup with key and secret",""].join(`
|
|
141
141
|
`)).action(t=>{t.key&&t.secret?Ze.saveToFile({workspaceKey:t.key,workspaceSecret:t.secret})?(console.error("\u2705 Configuration saved to membrane.config.yml"),process.exit(0)):(console.error("Error writing configuration file"),process.exit(1)):t.key||t.secret?(console.error("Error: Both --key and --secret must be provided for non-interactive mode"),process.exit(1)):mt(xe.createElement(wt,{membraneCLIService:e,children:xe.createElement(Cs,{onComplete:c(()=>process.exit(0),"onComplete")})}))})}c(Oa,"setupInitCommand");async function _i(s,e){const t={iss:s,exp:Math.floor(Date.now()/1e3)+600,isAdmin:!0};return rn.sign(t,e)}c(_i,"generateAdminAccessToken");async function $a(s,e){return(await on.get(`${s}/docs-json`,{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}})).data}c($a,"fetchOpenApiSchema");function Ki(s,e=!0){if(!s)return e?W.string():W.string().optional();let t;switch(s.type){case"integer":t=W.coerce.number().int();break;case"number":t=W.coerce.number();break;case"boolean":t=W.coerce.boolean();break;case"string":default:t=W.string();break}return s.format==="uuid"?t=W.string().uuid():s.format==="email"?t=W.string().email():s.format==="date"?t=W.string().regex(/^\d{4}-\d{2}-\d{2}$/):s.format==="date-time"&&(t=W.string().datetime()),s.enum&&(t=W.enum(s.enum)),(s.type==="integer"||s.type==="number")&&(s.minimum!==void 0&&(t=t.min(s.minimum)),s.maximum!==void 0&&(t=t.max(s.maximum))),s.type==="string"&&(s.minLength!==void 0&&(t=t.min(s.minLength)),s.maxLength!==void 0&&(t=t.max(s.maxLength))),e?t:t.optional()}c(Ki,"convertOpenApiSchemaToZod");function Fi(s){const e=s.match(/\{([^}]+)\}/g);return e?e.map(t=>t.slice(1,-1)):[]}c(Fi,"extractPathParameters");function La(s,e,t,n,i,r){const o=s.operationId||`${t}_${e.replace(/[^a-zA-Z0-9]/g,"_")}`,a=s.description||s.summary||`${t.toUpperCase()} ${e}`,l={},u={},p={};if(s.parameters){for(const h of s.parameters)if(h.in==="path")u[h.name]=Ki(h.schema,!0).describe(h.description||`Path parameter: ${h.name}`);else if(h.in==="query"){const g=h.required===!0;p[h.name]=Ki(h.schema,g).describe(h.description||`Query parameter: ${h.name}`)}}Object.keys(u).length>0&&(l.params=W.object(u).describe("Path parameters")),Object.keys(p).length>0&&(l.query=W.object(p).describe("Query parameters")),s.requestBody&&s.requestBody.content&&s.requestBody.content["application/json"]&&(l.body=W.any().describe("Request body"));const d=Object.keys(l).length>0?W.object(l):W.object({});return{name:o,description:a,parameters:d,async execute(h){try{const g=Fi(e);if(g.length>0){if(!h.params)throw new Error(`Missing required path parameters: ${g.join(", ")}`);const I=g.filter(O=>!(O in h.params));if(I.length>0)throw new Error(`Missing required path parameters: ${I.join(", ")}`)}let w=`${n}${e}`;if(h.params)for(const[I,O]of Object.entries(h.params)){const $=`{${I}}`;w.includes($)&&(w=w.replace($,String(O)))}const f=Fi(w);if(f.length>0)throw new Error(`Unresolved path parameters: ${f.join(", ")}`);const y=new URLSearchParams;if(h.query)for(const[I,O]of Object.entries(h.query))O!=null&&y.append(I,String(O));y.toString()&&(w+=`?${y.toString()}`);const C=await _i(i,r),v={method:t.toUpperCase(),headers:{Authorization:`Bearer ${C}`,"Content-Type":"application/json"}};h.body&&t.toLowerCase()!=="get"&&(v.data=h.body);const A=await on.request({url:w,...v});return{content:[{type:"text",text:JSON.stringify(A.data,null,2)}]}}catch(g){return on.isAxiosError(g)?{content:[{type:"text",text:`Error: ${g.response?.data?`HTTP ${g.response.status}: ${g.response.statusText} - ${JSON.stringify(g.response.data)}`:`HTTP ${g.response?.status||"unknown"}: ${g.message}`}`}],isError:!0}:g instanceof Error?{content:[{type:"text",text:`Error: API call failed: ${g.message}`}],isError:!0}:{content:[{type:"text",text:"Error: API call failed with unknown error"}],isError:!0}}}}}c(La,"createApiTool");function Da(s,e,t,n){const i=[];if(!s.paths)return i;for(const[r,o]of Object.entries(s.paths))if(typeof o=="object"&&o!==null){for(const[a,l]of Object.entries(o))if(["get","post","put","delete","patch"].includes(a)&&l&&typeof l=="object"){const u=La(l,r,a,e,t,n);i.push(u)}}return i}c(Da,"convertOpenApiToTools");function Pa(s){s.command("mcp").description("Launch MCP server with OpenAPI endpoints as tools (API URI is read from environment variables or membrane.config.yml)").addHelpText("after",["","Examples:"," membrane mcp # Launch MCP server using API URI from env vars or membrane.config.yml",""].join(`
|
|
142
142
|
`)).action(async()=>{try{process.env.FASTMCP_SUPPRESS_WARNINGS="true";const e=St();e||(console.error("No configuration found. Please set MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first."),process.exit(1)),(!e.workspaceKey||!e.workspaceSecret)&&(console.error("Missing workspace credentials"),process.exit(1));const t=e.apiUri||cn,n=await _i(e.workspaceKey,e.workspaceSecret),i=await $a(t,n),r=Da(i,t,e.workspaceKey,e.workspaceSecret),o=new wr({name:"Membrane API",instructions:`This MCP server lets you interact with Membrane to configure, run, and troubleshoot integrations.
|
|
143
143
|
Use it for anything related to Membrane or integrations.
|