@stackone/cli 1.13.9 → 1.13.10
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/cli.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const e=require(`./cliCore-
|
|
2
|
+
const e=require(`./cliCore-CE4evHvG.cjs`);new e.t().run();
|
package/dist/cli.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{t as e}from"./cliCore-
|
|
2
|
+
import{t as e}from"./cliCore-CxJljjN8.mjs";new e().run();export{};
|
|
@@ -48,8 +48,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
48
48
|
`),await this.uploadFile(t,o,i.apiKey)&&n++;console.info(`
|
|
49
49
|
`),x.info(`Upload completed: ${n} of ${e.length} file(s) uploaded successfully.`),process.exit(n>0?0:1)}else t.endsWith(`.s1.yaml`)||(x.error(`Only .s1.yaml files are supported for upload.`),process.exit(1));let s=await this.uploadFile(t,o,i.apiKey);process.exit(s?0:1)}async uploadFile(e,t,n){try{console.info(l.default.blue(`📤 Uploading ${(0,_.basename)(e)}...`));let r=Ig(e);if(!r)return!1;let i=(0,_.basename)(e),a=new FormData,o=new Blob([r],{type:`application/x-yaml`});a.append(`file`,o,i);let s=Buffer.from(n).toString(`base64`),c=await fetch(`${t}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${s}`},body:a});if(!c.ok){let e=await c.text();return x.error(`Upload failed: ${c.status} - ${c.statusText}`),e&&console.error(l.default.red(e)),!1}let u=await c.json();return console.info(l.default.green(`✓ Successfully uploaded ${i} with connector "${u.provider}@${u.version}"`)),!0}catch(e){return x.error(`Failed to upload file: ${e}`),!1}}};const Ig=e=>{let t=(0,b.loadConnector)(e),n=(0,b.validateYamlConnector)(t),r=n?.errors??[];if(n.success){let n=e.split(`/`).pop()||e;return x.success(`Connector ${n} is valid!`),t}else r.length>0?(x.error(`Connector ${e} is not valid. Please fix the following errors:\n`),r.forEach(e=>{console.info(l.default.red(`- L${e.line}: ${e.message}`))})):x.error(`Connector ${e} is not valid. Please check the file for errors.`)},Lg=e=>{let t=[],n=(0,g.readdirSync)(e,{withFileTypes:!0});for(let r of n){let n=(0,_.join)(e,r.name);r.isDirectory()?t.push(...Lg(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},Rg=$.object({provider_key:$.string().optional(),provider_version:$.string().optional(),auth_config_key:$.string(),environment:$.string().default(`production`),organization_id:$.string().default(`cli-organization-id`),account_id:$.string().default(`cli-account-secure-id`),project_id:$.string().default(`cli-project-secure-id`),credentials:$.record($.string(),$.any()).default({})}),zg=$.record($.string(),$.any()),Bg=$.object({path:$.record($.string(),$.any()).default({}),queryParams:$.record($.string(),$.any()).default({}),header:$.record($.string(),$.any()).default({}),body:$.record($.string(),$.any()).default({})}),Vg=`https://api.stackone.com`;var Hg=class{async execute({connector:e,action:t,actionId:n,account:r,accountId:i,params:a,credentials:o,profile:s,outputFile:c,debug:u,apiUrl:d,apiKey:f}={}){if(!s&&!f&&i&&(S.error(`Profile or API key is required when providing an account ID`),S.log(`Please provide a profile using the ${C(`--profile`)} option or an API key using the ${C(`--api-key`)} option.`),S.log(`To create a profile, run ${C(`stackone init`)}.`),process.exit(1)),s&&f&&(S.error(`Please provide either a profile or an API key, not both`),process.exit(1)),s&&d&&S.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),s&&!We(s)){S.error(`Configuration profile ${C(s)} not found`),S.log(`Run ${C(`stackone init`)} to create a new configuration profile.\n`);let e=Ke();e.length>0&&(S.info(`Available configuration profiles:`),e.forEach(e=>{S.log(` - ${l.default.blue(e)}`)})),process.exit(1)}let p=s?Ue(s):{apiUrl:d??Vg,apiKey:f};P(r)&&P(i)&&(S.error(`A valid account or account ID is required to run an action`),process.exit(1));let m;N(e)?this.#a(e)?(!s&&!f&&(S.error(`Profile or API key is required when using a connector identifier (provider_key@version)`),S.log(`Please provide a profile using the ${C(`--profile`)} option or an API key using the ${C(`--api-key`)} option.`),S.log(`Run ${C(`stackone init`)} to create a new configuration profile.`),process.exit(1)),m=await this.#o(e,p?.apiUrl??Vg,p?.apiKey)):m=this.#e(e):N(i)&&(m=await this.#s(i,p?.apiUrl??Vg,p?.apiKey));let h=N(t)?this.#r(t,e):m;P(h)&&(S.error(`A valid connector is required to run an action.`),process.exit(1));let ee=N(h?.actions)?Object.keys(h?.actions).length:0,_=N(h?.actions)?Object.keys(h.actions)[ee-1]:void 0,te=N(_)?h?.actions?.[_]?.id:void 0,v=(N(n)&&!n?.startsWith(`${h.key}_`)?`${h.key}_${n}`:n)??te;P(v)&&(S.error(`A valid action ID is required to run an action`),process.exit(1));let ne=N(i)?await this.#c(i,p?.apiUrl??Vg,p?.apiKey):{},re=N(r)?this.#i(r,h.key??`unknown`,h.version??`unknown`):void 0,y=N(o)?this.#l(o):{},ie={...ne,...re,credentials:{...ne.credentials??{},...y}};P(ie)&&(S.error(`A valid account data is required to run an action.`),process.exit(1));let ae=h.actions?.[v];P(ae)&&(S.error(`Action ID ${C(v)} not found in the connector ${C(h.key)}@${C(h.version)}.`),process.exit(1));let b=N(a)?this.#u(a,v):{path:{},queryParams:{},header:{},body:{}},oe=Date.now(),se=await this.#d({connector:h,actionId:v,account:ie,queryParams:{...b.queryParams,...u?{debug:`true`}:{}},pathParams:b.path,body:b.body,headers:b.header}),ce=Date.now()-oe;if(N(c))try{g.default.writeFileSync(c,JSON.stringify(se.output,null,2),`utf-8`),S.info(`Output written to file: ${c}`)}catch(e){S.error(`Failed to write output to file ${c}: ${e.message}`),process.exit(1)}else S.log(`\n${l.default.blue.inverse(` ACTION OUTPUT `)}`),pe(se.output);S.log(``),S.info(`Action ${C(v)} from connector ${C(h?.key)}@${C(h?.version)} finished in ${l.default.yellowBright((ce/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=(0,b.loadConnector)(e)}catch{}return t?this.#n(t):void 0};#t=e=>{try{return(0,b.loadConnector)(e)}catch(t){S.error(`Failed to load connector file from ${C(e)}: ${t.message}`),process.exit(1)}};#n=e=>{let t=(0,b.validateYamlConnector)(e),n=t?.errors??[];if(t.success)return t.connector||(S.error(`Failed to load connector.`),process.exit(1)),t.connector;n.length>0?(S.error(`Connector is not valid`),me(n,!0),process.exit(1)):(S.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(e,t)=>{let n=e;try{n=g.default.readFileSync(e,`utf-8`)}catch{}P(t)&&(S.error(`A valid connector is required to load an action.`),process.exit(1));let r=`${this.#t(t)} - ${n.split(`
|
|
50
50
|
`).map((e,t)=>t===0?e:` ${e}`).join(`
|
|
51
|
-
`)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=g.default.readFileSync(e,`utf-8`)}catch{}try{let e=Rg.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}S.error(`Failed to parse account information`),me(t,!1),t.length===0&&S.log(e.message),process.exit(1)}};#a=e=>e.includes(`@`)&&e.split(`@`).length===2&&!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`);#o=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching connector ${C(e)} from registry...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/registry/connectors/${e}`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch connector ${C(e)} from registry`),process.exit(1));let o=await a.text(),s=this.#n(o);return S.success(`Fetched connector ${C(s.key)}@${C(s.version)} from registry`),s}catch(n){r.stop(),S.error(`Failed to fetch connector ${C(e)} from registry: ${n.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#s=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching connector for account ${C(e)} from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch connector`),process.exit(1));let o=await a.text(),s=this.#n(o);return S.success(`Fetched connector ${C(s.key)}@${C(s.version)} for account ${C(e)}`),s}catch(e){r.stop(),S.error(`Failed to fetch connector: ${e.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#c=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching account ${C(e)} information from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch account ${C(e)} information`),process.exit(1));let o=await a.json();return S.success(`Fetched account ${C(e)} information from project ${C(o.project_id)}`),{providerKey:o.provider_key,providerVersion:o.provider_version,authConfigKey:o.auth_config_key,environment:o.environment,organizationId:o.organization_id,secureId:o.account_id,projectSecureId:o.project_id,credentials:o.credentials}}catch(n){r.stop(),S.error(`Failed to fetch account ${C(e)} information: ${n.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#l=e=>{let t=e;try{t=g.default.readFileSync(e,`utf-8`)}catch{}try{return zg.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}S.error(`Failed to parse credentials`),me(t,!1),t.length===0&&S.log(e.message),process.exit(1)}};#u=(e,t)=>{let n=e;try{n=g.default.readFileSync(e,`utf-8`)}catch{}try{return Bg.parse(JSON.parse(n))}catch(e){let n=[];try{n=JSON.parse(e.message)}catch{}S.error(`Invalid parameters for action ${C(t)}.`),me(n,!1),n.length===0&&S.log(e.message),process.exit(1)}};async#d({connector:e,actionId:t,account:n,pathParams:r={},queryParams:i={},body:a={},headers:o={}}){try{let s=await(0,b.runAction)({mode:`action_id`,actionId:t,account:n,connector:e,pathParams:r,queryParams:i,body:a,headers:o,getHttpClient:async()=>new oe.HttpClient});if(s.response?.successful){let e={...this.#f(i,s.steps),...Qi(s.outputs)?s.outputs:{data:s.outputs}};return{statusCode:s.response?.statusCode,output:e}}else{let n=s.response?.message??`An error occurred while processing the request`;S.error(`Action ID ${C(t)} from connector ${C(e.key)}@${C(e.version)} failed with status ${s.response?.statusCode}: ${n}`);let r={...this.#f(i,s.steps)};Object.keys(r).length>0&&(S.log(`${l.default.yellow.inverse(` EXECUTION DETAILS `)}`),pe(r)),process.exit(1)}}catch(e){this.#p(e)}}#f(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#p(e){let t=e;switch(P(t.errorType)&&(S.error(`An unknown error occurred`),S.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:S.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;S.error(`Invalid action inputs`),me(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:S.error(`Invalid cursor: ${t.message}`);break;default:S.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Ug=()=>{try{let e=(0,_.join)((0,_.dirname)((0,le.fileURLToPath)(require(`url`).pathToFileURL(__filename).href)),`..`,`package.json`);return JSON.parse((0,g.readFileSync)(e,`utf8`)).version}catch{return`unknown`}};var
|
|
51
|
+
`)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=g.default.readFileSync(e,`utf-8`)}catch{}try{let e=Rg.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}S.error(`Failed to parse account information`),me(t,!1),t.length===0&&S.log(e.message),process.exit(1)}};#a=e=>e.includes(`@`)&&e.split(`@`).length===2&&!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`);#o=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching connector ${C(e)} from registry...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/registry/connectors/${e}`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch connector ${C(e)} from registry`),process.exit(1));let o=await a.text(),s=this.#n(o);return S.success(`Fetched connector ${C(s.key)}@${C(s.version)} from registry`),s}catch(n){r.stop(),S.error(`Failed to fetch connector ${C(e)} from registry: ${n.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#s=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching connector for account ${C(e)} from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch connector`),process.exit(1));let o=await a.text(),s=this.#n(o);return S.success(`Fetched connector ${C(s.key)}@${C(s.version)} for account ${C(e)}`),s}catch(e){r.stop(),S.error(`Failed to fetch connector: ${e.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#c=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(S.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let r=(0,h.default)();try{r.text=`Fetching account ${C(e)} information from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await he(a,`Failed to fetch account ${C(e)} information`),process.exit(1));let o=await a.json();return S.success(`Fetched account ${C(e)} information from project ${C(o.project_id)}`),{providerKey:o.provider_key,providerVersion:o.provider_version,authConfigKey:o.auth_config_key,environment:o.environment,organizationId:o.organization_id,secureId:o.account_id,projectSecureId:o.project_id,credentials:o.credentials}}catch(n){r.stop(),S.error(`Failed to fetch account ${C(e)} information: ${n.message}`),S.log(`Please ensure that the API at ${ge(t)} is reachable and the API key is valid.`),process.exit(1)}};#l=e=>{let t=e;try{t=g.default.readFileSync(e,`utf-8`)}catch{}try{return zg.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}S.error(`Failed to parse credentials`),me(t,!1),t.length===0&&S.log(e.message),process.exit(1)}};#u=(e,t)=>{let n=e;try{n=g.default.readFileSync(e,`utf-8`)}catch{}try{return Bg.parse(JSON.parse(n))}catch(e){let n=[];try{n=JSON.parse(e.message)}catch{}S.error(`Invalid parameters for action ${C(t)}.`),me(n,!1),n.length===0&&S.log(e.message),process.exit(1)}};async#d({connector:e,actionId:t,account:n,pathParams:r={},queryParams:i={},body:a={},headers:o={}}){try{let s=await(0,b.runAction)({mode:`action_id`,actionId:t,account:n,connector:e,pathParams:r,queryParams:i,body:a,headers:o,getHttpClient:async()=>new oe.HttpClient});if(s.response?.successful){let e={...this.#f(i,s.steps),...Qi(s.outputs)?s.outputs:{data:s.outputs}};return{statusCode:s.response?.statusCode,output:e}}else{let n=s.response?.message??`An error occurred while processing the request`;S.error(`Action ID ${C(t)} from connector ${C(e.key)}@${C(e.version)} failed with status ${s.response?.statusCode}: ${n}`);let r={...this.#f(i,s.steps)};Object.keys(r).length>0&&(S.log(`${l.default.yellow.inverse(` EXECUTION DETAILS `)}`),pe(r)),process.exit(1)}}catch(e){this.#p(e)}}#f(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#p(e){let t=e;switch(P(t.errorType)&&(S.error(`An unknown error occurred`),S.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:S.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;S.error(`Invalid action inputs`),me(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:S.error(`Invalid cursor: ${t.message}`);break;default:S.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Ug=()=>{try{let e=(0,_.join)((0,_.dirname)((0,le.fileURLToPath)(require(`url`).pathToFileURL(__filename).href)),`..`,`package.json`);return JSON.parse((0,g.readFileSync)(e,`utf8`)).version}catch{return`unknown`}},Wg=(0,m.promisify)(d.exec);var Gg=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=(0,h.default)(),this.currentVersion=Ug()}async execute(e={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let t=await this.getLatestVersion();this.spinner.stop(),t||(S.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(t,this.currentVersion)?(S.box(`New version available: ${l.default.yellow(this.currentVersion)} → ${l.default.green(t)}`),await this.performUpdate(t)):e.force?(S.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(t)):S.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(e){this.spinner.stop(),S.error(`Error while trying to update StackOne CLI: ${e?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await Wg(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return ce.default.gt(e,t)}isUsingVolta(){if(typeof process.env.VOLTA_HOME!=`string`||process.env.VOLTA_HOME.length===0)return!1;let e=(0,p.join)(process.env.VOLTA_HOME,`bin`),t=(0,p.join)(e,`stackone`),n=(0,p.join)(e,`stackone.exe`);return(0,se.existsSync)(t)||(0,se.existsSync)(n)}async performUpdate(e){let t=this.isUsingVolta();this.spinner.text=`Updating to latest version (${C(e)})...`,this.spinner.start();try{await Wg(t?`volta install ${this.packageName}@latest`:`npm install -g ${this.packageName}@latest`,{encoding:`utf-8`}),this.spinner.stop(),S.success(`StackOne CLI updated successfully to latest version (${C(e)})`)}catch{this.spinner.stop();let e=t?`volta install ${this.packageName}@latest`:`npm install -g ${this.packageName}@latest`;throw Error(`Failed to install update. Please try manually: ${e}`)}}},Kg=class{async execute(e){let{watchMode:t,fileOrDir:n}=e,r=(0,h.default)(`Watching for changes...`),i=()=>{console.clear(),console.info(l.default.yellow(`Watch mode enabled. Press "q" to quit.
|
|
52
52
|
`))};if(n){try{(0,g.statSync)(n)}catch{x.error(`File or directory not found: ${n}`),process.exit(1)}if(t){let{watch:e}=await import(`chokidar`),t=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let a=()=>{console.info(l.default.grey(`
|
|
53
53
|
|
|
54
|
-
Exiting watch mode...`)),o.close(),r.stop(),t.close(),process.exit(0)};i(),console.info(l.default.blue(`Running connector(s) validations...`)),await
|
|
55
|
-
`),!1;else return x.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},
|
|
54
|
+
Exiting watch mode...`)),o.close(),r.stop(),t.close(),process.exit(0)};i(),console.info(l.default.blue(`Running connector(s) validations...`)),await qg(n),r.start();let o=e(n||`.`,{ignored:/(^|[/\\])\../,persistent:!0});o.on(`change`,async e=>{i(),r.stop(),console.info(l.default.blue(`File change detected. Running connector(s) validations...`)),await qg(n),r.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&a()}),process.on(`SIGINT`,()=>{a()})}else await qg(n),process.exit(0)}}};const qg=async e=>{let t=(0,g.statSync)(e);if(t.isDirectory()){let t=(0,g.readdirSync)(e).filter(e=>e.endsWith(`.s1.yaml`));if(t.length===0){x.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let n=0,r=0;for(let i of t){let t=`${e}/${i}`;(0,g.statSync)(t).isFile()&&(await Jg(t)?n++:r++)}x.info(`Validation completed: ${n} valid, ${r} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await Jg(e):x.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},Jg=async e=>{let t=(0,b.validateYamlConnector)((0,b.loadConnector)(e)),n=t?.errors??[];if(t.success){let t=e.split(`/`).pop()||e;return x.success(`Connector ${t} is valid!\n`),!0}else if(n.length>0)return x.error(`Connector ${e} is not valid. Please fix the following errors:\n`),n.forEach(e=>{console.info(l.default.red(`- L${e.line}: ${e.message}`))}),console.info(`
|
|
55
|
+
`),!1;else return x.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},Yg=`@stackone/cli`,Xg=2880*60*1e3,Zg=(0,p.join)((0,ue.homedir)(),`.stackone`),Qg=(0,p.join)(Zg,`version-check.json`),$g=(e=!1)=>{let t=r_(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=e_();e&&t_(e)&&n_(e),i_({lastCheckTime:n})}},e_=()=>{try{return(0,d.execSync)(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},t_=e=>{try{let t=Ug();return ce.default.gt(e,t)}catch{return!1}},n_=e=>{let t=Ug(),n=`Update available: ${l.default.dim(t)} → ${l.default.green(e)}`,r=`\n\nRun ${l.default.cyan(`stackone update`)} to update`;S.box(n,r)},r_=()=>{try{if(!(0,se.existsSync)(Qg))return null;let e=(0,se.readFileSync)(Qg,`utf-8`);return JSON.parse(e)}catch{return null}},i_=e=>{try{(0,se.existsSync)(Zg)||(0,se.mkdirSync)(Zg,{recursive:!0}),(0,se.writeFileSync)(Qg,JSON.stringify(e,null,2),`utf-8`)}catch{}};var a_=class{constructor(e=new u.Command,t=Ug()){this.program=e,this.version=t,this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let e=new Ng,t=new Fg,n=new Je,r=new kg,i=new Kg,a=new Ie,o=new Be,s=new je,c=new Hg,d=new Gg;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,t)=>{t(l.default.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(t=>{e.execute({environment:t.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new u.Argument(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,n)=>{t.execute({profile:n.profile,fileOrDir:e,apiUrl:n.apiUrl,apiKey:n.apiKey})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new u.Argument(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{n.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--connector <connector>`,`Connector identifier in format provider_key@version`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).description(`Get a connector from the StackOne registry`).action(e=>{r.execute({profile:e.profile,connector:e.connector,accountId:e.accountId,format:e.format,outputFile:e.outputFile,apiUrl:e.apiUrl,apiKey:e.apiKey})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new u.Argument(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{i.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file to run (optional when using --account-id)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).description(`Run a connector action`).action(e=>{c.execute({connector:e.connector,action:e.action,actionId:e.actionId,account:e.account,accountId:e.accountId,params:e.params,credentials:e.credentials,profile:e.profile,outputFile:e.outputFile,debug:e.debug,apiUrl:e.apiUrl,apiKey:e.apiKey})});let f=this.program.command(`agent`).description(`StackOne agent commands`);f.command(`setup`).option(`-g, --global`,`Setup global configuration`).option(`-l, --local`,`Setup local project configuration`).description(`Setup StackOne agent (global or local)`).action(e=>{e.global?a.execute():o.execute()}),f.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{s.execute()}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{d.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{S.log(`${l.default.inverse.greenBright(`StackOne`)} ${l.default.grey(`CLI`)} ${l.default.whiteBright(this.version)}`),$g(!0),process.exit(0)})}run(){process.argv.includes(`version`)||$g(),this.program.parse(process.argv)}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return a_}});
|
|
@@ -48,8 +48,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
48
48
|
`),await this.uploadFile(t,o,i.apiKey)&&n++;console.info(`
|
|
49
49
|
`),y.info(`Upload completed: ${n} of ${e.length} file(s) uploaded successfully.`),process.exit(n>0?0:1)}else t.endsWith(`.s1.yaml`)||(y.error(`Only .s1.yaml files are supported for upload.`),process.exit(1));let s=await this.uploadFile(t,o,i.apiKey);process.exit(s?0:1)}async uploadFile(e,n,r){try{console.info(t.blue(`📤 Uploading ${ie(e)}...`));let i=Pp(e);if(!i)return!1;let a=ie(e),o=new FormData,s=new Blob([i],{type:`application/x-yaml`});o.append(`file`,s,a);let c=Buffer.from(r).toString(`base64`),l=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${c}`},body:o});if(!l.ok){let e=await l.text();return y.error(`Upload failed: ${l.status} - ${l.statusText}`),e&&console.error(t.red(e)),!1}let u=await l.json();return console.info(t.green(`✓ Successfully uploaded ${a} with connector "${u.provider}@${u.version}"`)),!0}catch(e){return y.error(`Failed to upload file: ${e}`),!1}}};const Pp=e=>{let n=he(e),r=_e(n),i=r?.errors??[];if(r.success){let t=e.split(`/`).pop()||e;return y.success(`Connector ${t} is valid!`),n}else i.length>0?(y.error(`Connector ${e} is not valid. Please fix the following errors:\n`),i.forEach(e=>{console.info(t.red(`- L${e.line}: ${e.message}`))})):y.error(`Connector ${e} is not valid. Please check the file for errors.`)},Fp=e=>{let t=[],n=g(e,{withFileTypes:!0});for(let r of n){let n=oe(e,r.name);r.isDirectory()?t.push(...Fp(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},Ip=$.object({provider_key:$.string().optional(),provider_version:$.string().optional(),auth_config_key:$.string(),environment:$.string().default(`production`),organization_id:$.string().default(`cli-organization-id`),account_id:$.string().default(`cli-account-secure-id`),project_id:$.string().default(`cli-project-secure-id`),credentials:$.record($.string(),$.any()).default({})}),Lp=$.record($.string(),$.any()),Rp=$.object({path:$.record($.string(),$.any()).default({}),queryParams:$.record($.string(),$.any()).default({}),header:$.record($.string(),$.any()).default({}),body:$.record($.string(),$.any()).default({})}),zp=`https://api.stackone.com`;var Bp=class{async execute({connector:e,action:n,actionId:r,account:i,accountId:a,params:o,credentials:s,profile:c,outputFile:l,debug:u,apiUrl:d,apiKey:p}={}){if(!c&&!p&&a&&(b.error(`Profile or API key is required when providing an account ID`),b.log(`Please provide a profile using the ${x(`--profile`)} option or an API key using the ${x(`--api-key`)} option.`),b.log(`To create a profile, run ${x(`stackone init`)}.`),process.exit(1)),c&&p&&(b.error(`Please provide either a profile or an API key, not both`),process.exit(1)),c&&d&&b.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),c&&!ft(c)){b.error(`Configuration profile ${x(c)} not found`),b.log(`Run ${x(`stackone init`)} to create a new configuration profile.\n`);let e=mt();e.length>0&&(b.info(`Available configuration profiles:`),e.forEach(e=>{b.log(` - ${t.blue(e)}`)})),process.exit(1)}let m=c?dt(c):{apiUrl:d??zp,apiKey:p};P(i)&&P(a)&&(b.error(`A valid account or account ID is required to run an action`),process.exit(1));let h;N(e)?this.#a(e)?(!c&&!p&&(b.error(`Profile or API key is required when using a connector identifier (provider_key@version)`),b.log(`Please provide a profile using the ${x(`--profile`)} option or an API key using the ${x(`--api-key`)} option.`),b.log(`Run ${x(`stackone init`)} to create a new configuration profile.`),process.exit(1)),h=await this.#o(e,m?.apiUrl??zp,m?.apiKey)):h=this.#e(e):N(a)&&(h=await this.#s(a,m?.apiUrl??zp,m?.apiKey));let g=N(n)?this.#r(n,e):h;P(g)&&(b.error(`A valid connector is required to run an action.`),process.exit(1));let ee=N(g?.actions)?Object.keys(g?.actions).length:0,te=N(g?.actions)?Object.keys(g.actions)[ee-1]:void 0,ne=N(te)?g?.actions?.[te]?.id:void 0,re=(N(r)&&!r?.startsWith(`${g.key}_`)?`${g.key}_${r}`:r)??ne;P(re)&&(b.error(`A valid action ID is required to run an action`),process.exit(1));let ie=N(a)?await this.#c(a,m?.apiUrl??zp,m?.apiKey):{},ae=N(i)?this.#i(i,g.key??`unknown`,g.version??`unknown`):void 0,oe=N(s)?this.#l(s):{},se={...ie,...ae,credentials:{...ie.credentials??{},...oe}};P(se)&&(b.error(`A valid account data is required to run an action.`),process.exit(1));let _=g.actions?.[re];P(_)&&(b.error(`Action ID ${x(re)} not found in the connector ${x(g.key)}@${x(g.version)}.`),process.exit(1));let ce=N(o)?this.#u(o,re):{path:{},queryParams:{},header:{},body:{}},le=Date.now(),ue=await this.#d({connector:g,actionId:re,account:se,queryParams:{...ce.queryParams,...u?{debug:`true`}:{}},pathParams:ce.path,body:ce.body,headers:ce.header}),de=Date.now()-le;if(N(l))try{f.writeFileSync(l,JSON.stringify(ue.output,null,2),`utf-8`),b.info(`Output written to file: ${l}`)}catch(e){b.error(`Failed to write output to file ${l}: ${e.message}`),process.exit(1)}else b.log(`\n${t.blue.inverse(` ACTION OUTPUT `)}`),Re(ue.output);b.log(``),b.info(`Action ${x(re)} from connector ${x(g?.key)}@${x(g?.version)} finished in ${t.yellowBright((de/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=he(e)}catch{}return t?this.#n(t):void 0};#t=e=>{try{return he(e)}catch(t){b.error(`Failed to load connector file from ${x(e)}: ${t.message}`),process.exit(1)}};#n=e=>{let t=_e(e),n=t?.errors??[];if(t.success)return t.connector||(b.error(`Failed to load connector.`),process.exit(1)),t.connector;n.length>0?(b.error(`Connector is not valid`),ze(n,!0),process.exit(1)):(b.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(e,t)=>{let n=e;try{n=f.readFileSync(e,`utf-8`)}catch{}P(t)&&(b.error(`A valid connector is required to load an action.`),process.exit(1));let r=`${this.#t(t)} - ${n.split(`
|
|
50
50
|
`).map((e,t)=>t===0?e:` ${e}`).join(`
|
|
51
|
-
`)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=f.readFileSync(e,`utf-8`)}catch{}try{let e=Ip.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}b.error(`Failed to parse account information`),ze(t,!1),t.length===0&&b.log(e.message),process.exit(1)}};#a=e=>e.includes(`@`)&&e.split(`@`).length===2&&!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`);#o=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let r=d();try{r.text=`Fetching connector ${x(e)} from registry...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/registry/connectors/${e}`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch connector ${x(e)} from registry`),process.exit(1));let o=await a.text(),s=this.#n(o);return b.success(`Fetched connector ${x(s.key)}@${x(s.version)} from registry`),s}catch(n){r.stop(),b.error(`Failed to fetch connector ${x(e)} from registry: ${n.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#s=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let r=d();try{r.text=`Fetching connector for account ${x(e)} from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch connector`),process.exit(1));let o=await a.text(),s=this.#n(o);return b.success(`Fetched connector ${x(s.key)}@${x(s.version)} for account ${x(e)}`),s}catch(e){r.stop(),b.error(`Failed to fetch connector: ${e.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#c=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let r=d();try{r.text=`Fetching account ${x(e)} information from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch account ${x(e)} information`),process.exit(1));let o=await a.json();return b.success(`Fetched account ${x(e)} information from project ${x(o.project_id)}`),{providerKey:o.provider_key,providerVersion:o.provider_version,authConfigKey:o.auth_config_key,environment:o.environment,organizationId:o.organization_id,secureId:o.account_id,projectSecureId:o.project_id,credentials:o.credentials}}catch(n){r.stop(),b.error(`Failed to fetch account ${x(e)} information: ${n.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#l=e=>{let t=e;try{t=f.readFileSync(e,`utf-8`)}catch{}try{return Lp.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}b.error(`Failed to parse credentials`),ze(t,!1),t.length===0&&b.log(e.message),process.exit(1)}};#u=(e,t)=>{let n=e;try{n=f.readFileSync(e,`utf-8`)}catch{}try{return Rp.parse(JSON.parse(n))}catch(e){let n=[];try{n=JSON.parse(e.message)}catch{}b.error(`Invalid parameters for action ${x(t)}.`),ze(n,!1),n.length===0&&b.log(e.message),process.exit(1)}};async#d({connector:e,actionId:n,account:r,pathParams:i={},queryParams:a={},body:o={},headers:s={}}){try{let c=await ge({mode:`action_id`,actionId:n,account:r,connector:e,pathParams:i,queryParams:a,body:o,headers:s,getHttpClient:async()=>new ve});if(c.response?.successful){let e={...this.#f(a,c.steps),...jn(c.outputs)?c.outputs:{data:c.outputs}};return{statusCode:c.response?.statusCode,output:e}}else{let r=c.response?.message??`An error occurred while processing the request`;b.error(`Action ID ${x(n)} from connector ${x(e.key)}@${x(e.version)} failed with status ${c.response?.statusCode}: ${r}`);let i={...this.#f(a,c.steps)};Object.keys(i).length>0&&(b.log(`${t.yellow.inverse(` EXECUTION DETAILS `)}`),Re(i)),process.exit(1)}}catch(e){this.#p(e)}}#f(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#p(e){let t=e;switch(P(t.errorType)&&(b.error(`An unknown error occurred`),b.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:b.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;b.error(`Invalid action inputs`),ze(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:b.error(`Invalid cursor: ${t.message}`);break;default:b.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Vp=()=>{try{let e=oe(ae(we(import.meta.url)),`..`,`package.json`);return JSON.parse(h(e,`utf8`)).version}catch{return`unknown`}};var
|
|
51
|
+
`)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=f.readFileSync(e,`utf-8`)}catch{}try{let e=Ip.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}b.error(`Failed to parse account information`),ze(t,!1),t.length===0&&b.log(e.message),process.exit(1)}};#a=e=>e.includes(`@`)&&e.split(`@`).length===2&&!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`);#o=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let r=d();try{r.text=`Fetching connector ${x(e)} from registry...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/registry/connectors/${e}`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch connector ${x(e)} from registry`),process.exit(1));let o=await a.text(),s=this.#n(o);return b.success(`Fetched connector ${x(s.key)}@${x(s.version)} from registry`),s}catch(n){r.stop(),b.error(`Failed to fetch connector ${x(e)} from registry: ${n.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#s=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let r=d();try{r.text=`Fetching connector for account ${x(e)} from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch connector`),process.exit(1));let o=await a.text(),s=this.#n(o);return b.success(`Fetched connector ${x(s.key)}@${x(s.version)} for account ${x(e)}`),s}catch(e){r.stop(),b.error(`Failed to fetch connector: ${e.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#c=async(e,t,n)=>{(P(e)||P(t)||P(n))&&(b.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let r=d();try{r.text=`Fetching account ${x(e)} information from API...`,r.start();let i=Buffer.from(n).toString(`base64`),a=await fetch(`${t}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${i}`}});r.stop(),a.ok||(await Be(a,`Failed to fetch account ${x(e)} information`),process.exit(1));let o=await a.json();return b.success(`Fetched account ${x(e)} information from project ${x(o.project_id)}`),{providerKey:o.provider_key,providerVersion:o.provider_version,authConfigKey:o.auth_config_key,environment:o.environment,organizationId:o.organization_id,secureId:o.account_id,projectSecureId:o.project_id,credentials:o.credentials}}catch(n){r.stop(),b.error(`Failed to fetch account ${x(e)} information: ${n.message}`),b.log(`Please ensure that the API at ${Ve(t)} is reachable and the API key is valid.`),process.exit(1)}};#l=e=>{let t=e;try{t=f.readFileSync(e,`utf-8`)}catch{}try{return Lp.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}b.error(`Failed to parse credentials`),ze(t,!1),t.length===0&&b.log(e.message),process.exit(1)}};#u=(e,t)=>{let n=e;try{n=f.readFileSync(e,`utf-8`)}catch{}try{return Rp.parse(JSON.parse(n))}catch(e){let n=[];try{n=JSON.parse(e.message)}catch{}b.error(`Invalid parameters for action ${x(t)}.`),ze(n,!1),n.length===0&&b.log(e.message),process.exit(1)}};async#d({connector:e,actionId:n,account:r,pathParams:i={},queryParams:a={},body:o={},headers:s={}}){try{let c=await ge({mode:`action_id`,actionId:n,account:r,connector:e,pathParams:i,queryParams:a,body:o,headers:s,getHttpClient:async()=>new ve});if(c.response?.successful){let e={...this.#f(a,c.steps),...jn(c.outputs)?c.outputs:{data:c.outputs}};return{statusCode:c.response?.statusCode,output:e}}else{let r=c.response?.message??`An error occurred while processing the request`;b.error(`Action ID ${x(n)} from connector ${x(e.key)}@${x(e.version)} failed with status ${c.response?.statusCode}: ${r}`);let i={...this.#f(a,c.steps)};Object.keys(i).length>0&&(b.log(`${t.yellow.inverse(` EXECUTION DETAILS `)}`),Re(i)),process.exit(1)}}catch(e){this.#p(e)}}#f(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#p(e){let t=e;switch(P(t.errorType)&&(b.error(`An unknown error occurred`),b.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:b.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;b.error(`Invalid action inputs`),ze(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:b.error(`Invalid cursor: ${t.message}`);break;default:b.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Vp=()=>{try{let e=oe(ae(we(import.meta.url)),`..`,`package.json`);return JSON.parse(h(e,`utf8`)).version}catch{return`unknown`}},Hp=u(i);var Up=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=d(),this.currentVersion=Vp()}async execute(e={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let n=await this.getLatestVersion();this.spinner.stop(),n||(b.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(n,this.currentVersion)?(b.box(`New version available: ${t.yellow(this.currentVersion)} → ${t.green(n)}`),await this.performUpdate(n)):e.force?(b.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(n)):b.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(e){this.spinner.stop(),b.error(`Error while trying to update StackOne CLI: ${e?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await Hp(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return Ce.gt(e,t)}isUsingVolta(){if(typeof process.env.VOLTA_HOME!=`string`||process.env.VOLTA_HOME.length===0)return!1;let e=l(process.env.VOLTA_HOME,`bin`),t=l(e,`stackone`),n=l(e,`stackone.exe`);return ye(t)||ye(n)}async performUpdate(e){let t=this.isUsingVolta();this.spinner.text=`Updating to latest version (${x(e)})...`,this.spinner.start();try{await Hp(t?`volta install ${this.packageName}@latest`:`npm install -g ${this.packageName}@latest`,{encoding:`utf-8`}),this.spinner.stop(),b.success(`StackOne CLI updated successfully to latest version (${x(e)})`)}catch{this.spinner.stop();let e=t?`volta install ${this.packageName}@latest`:`npm install -g ${this.packageName}@latest`;throw Error(`Failed to install update. Please try manually: ${e}`)}}},Wp=class{async execute(e){let{watchMode:n,fileOrDir:r}=e,i=d(`Watching for changes...`),a=()=>{console.clear(),console.info(t.yellow(`Watch mode enabled. Press "q" to quit.
|
|
52
52
|
`))};if(r){try{te(r)}catch{y.error(`File or directory not found: ${r}`),process.exit(1)}if(n){let{watch:e}=await import(`chokidar`),n=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let o=()=>{console.info(t.grey(`
|
|
53
53
|
|
|
54
|
-
Exiting watch mode...`)),s.close(),i.stop(),n.close(),process.exit(0)};a(),console.info(t.blue(`Running connector(s) validations...`)),await
|
|
55
|
-
`),!1;else return y.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},
|
|
54
|
+
Exiting watch mode...`)),s.close(),i.stop(),n.close(),process.exit(0)};a(),console.info(t.blue(`Running connector(s) validations...`)),await Gp(r),i.start();let s=e(r||`.`,{ignored:/(^|[/\\])\../,persistent:!0});s.on(`change`,async e=>{a(),i.stop(),console.info(t.blue(`File change detected. Running connector(s) validations...`)),await Gp(r),i.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&o()}),process.on(`SIGINT`,()=>{o()})}else await Gp(r),process.exit(0)}}};const Gp=async e=>{let t=te(e);if(t.isDirectory()){let t=g(e).filter(e=>e.endsWith(`.s1.yaml`));if(t.length===0){y.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let n=0,r=0;for(let i of t){let t=`${e}/${i}`;te(t).isFile()&&(await Kp(t)?n++:r++)}y.info(`Validation completed: ${n} valid, ${r} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await Kp(e):y.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},Kp=async e=>{let n=_e(he(e)),r=n?.errors??[];if(n.success){let t=e.split(`/`).pop()||e;return y.success(`Connector ${t} is valid!\n`),!0}else if(r.length>0)return y.error(`Connector ${e} is not valid. Please fix the following errors:\n`),r.forEach(e=>{console.info(t.red(`- L${e.line}: ${e.message}`))}),console.info(`
|
|
55
|
+
`),!1;else return y.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},qp=l(Te(),`.stackone`),Jp=l(qp,`version-check.json`),Yp=(e=!1)=>{let t=$p(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=Xp();e&&Zp(e)&&Qp(e),em({lastCheckTime:n})}},Xp=()=>{try{return a(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},Zp=e=>{try{let t=Vp();return Ce.gt(e,t)}catch{return!1}},Qp=e=>{let n=Vp(),r=`Update available: ${t.dim(n)} → ${t.green(e)}`,i=`\n\nRun ${t.cyan(`stackone update`)} to update`;b.box(r,i)},$p=()=>{try{if(!ye(Jp))return null;let e=xe(Jp,`utf-8`);return JSON.parse(e)}catch{return null}},em=e=>{try{ye(qp)||be(qp,{recursive:!0}),Se(Jp,JSON.stringify(e,null,2),`utf-8`)}catch{}};var tm=class{constructor(e=new r,t=Vp()){this.program=e,this.version=t,this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let e=new jp,r=new Np,i=new gt,a=new Ap,o=new Wp,s=new it,c=new ct,l=new et,u=new Bp,d=new Up;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,n)=>{n(t.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(t=>{e.execute({environment:t.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new n(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,t)=>{r.execute({profile:t.profile,fileOrDir:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new n(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{i.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--connector <connector>`,`Connector identifier in format provider_key@version`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).description(`Get a connector from the StackOne registry`).action(e=>{a.execute({profile:e.profile,connector:e.connector,accountId:e.accountId,format:e.format,outputFile:e.outputFile,apiUrl:e.apiUrl,apiKey:e.apiKey})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new n(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{o.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file to run (optional when using --account-id)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).description(`Run a connector action`).action(e=>{u.execute({connector:e.connector,action:e.action,actionId:e.actionId,account:e.account,accountId:e.accountId,params:e.params,credentials:e.credentials,profile:e.profile,outputFile:e.outputFile,debug:e.debug,apiUrl:e.apiUrl,apiKey:e.apiKey})});let f=this.program.command(`agent`).description(`StackOne agent commands`);f.command(`setup`).option(`-g, --global`,`Setup global configuration`).option(`-l, --local`,`Setup local project configuration`).description(`Setup StackOne agent (global or local)`).action(e=>{e.global?s.execute():c.execute()}),f.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{l.execute()}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{d.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{b.log(`${t.inverse.greenBright(`StackOne`)} ${t.grey(`CLI`)} ${t.whiteBright(this.version)}`),Yp(!0),process.exit(0)})}run(){process.argv.includes(`version`)||Yp(),this.program.parse(process.argv)}};export{tm as t};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./cliCore-
|
|
1
|
+
const e=require(`./cliCore-CE4evHvG.cjs`);exports.CLI=e.t;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./cliCore-
|
|
1
|
+
import{t as e}from"./cliCore-CxJljjN8.mjs";export{e as CLI};
|