@stackone/cli 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -8
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/cliCore-Bba3TFak.cjs +7 -0
- package/dist/cliCore-CGA-wigN.js +7 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/cliCore-BOwdDcP4.cjs +0 -7
- package/dist/cliCore-CYhcPSJT.js +0 -7
package/README.md
CHANGED
|
@@ -29,13 +29,14 @@ Initialize and configure the StackOne CLI by creating configuration profiles. Th
|
|
|
29
29
|
stackone init
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
**Options:**
|
|
33
|
+
|
|
34
|
+
- `-e, --env <environment>` - Specify the environment for the configuration profile (`production`, `staging` or custom value). Defaults to `production` if not provided. When using a custom environment, you will be prompted to enter the API URL.
|
|
35
|
+
|
|
32
36
|
The command will interactively prompt you for:
|
|
33
37
|
|
|
34
38
|
1. **Profile label** - A unique name for this configuration profile
|
|
35
|
-
2. **
|
|
36
|
-
- `production`
|
|
37
|
-
- `staging`
|
|
38
|
-
- `local`
|
|
39
|
+
2. **API Url** - Only when the environment is specified and is not production or staging
|
|
39
40
|
3. **API Key** - Your StackOne API key
|
|
40
41
|
|
|
41
42
|
**Features:**
|
|
@@ -47,7 +48,7 @@ The command will interactively prompt you for:
|
|
|
47
48
|
|
|
48
49
|
### `push`
|
|
49
50
|
|
|
50
|
-
Push connector(s) file(s) to the StackOne API registry. This command
|
|
51
|
+
Push connector(s) file(s) to the StackOne API registry. This command can use either a configuration profile created with the `init` command or provide credentials directly via command-line options.
|
|
51
52
|
|
|
52
53
|
```bash
|
|
53
54
|
stackone push --profile <profile-label> path/to/connector.s1.yaml
|
|
@@ -59,18 +60,36 @@ or
|
|
|
59
60
|
stackone push --profile <profile-label> path/to/connectors/
|
|
60
61
|
```
|
|
61
62
|
|
|
63
|
+
or using direct credentials:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
stackone push --api-key <your-api-key> path/to/connector.s1.yaml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
or with custom API URL:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
stackone push --api-key <your-api-key> --api-url <api-url> path/to/connector.s1.yaml
|
|
73
|
+
```
|
|
74
|
+
|
|
62
75
|
**Arguments:**
|
|
63
76
|
|
|
64
77
|
- `<path>` - Path to the connector file or folder with connectors to upload
|
|
65
78
|
|
|
66
79
|
**Options:**
|
|
67
80
|
|
|
68
|
-
- `-p, --profile <label>` - Configuration profile to use
|
|
81
|
+
- `-p, --profile <label>` - Configuration profile to use
|
|
82
|
+
- `--api-key <api-key>` - API key to use for authentication (alternative to using a profile)
|
|
83
|
+
- `--api-url <api-url>` - API URL to use (defaults to `https://api.stackone.com` if not specified)
|
|
84
|
+
|
|
85
|
+
**Note:** You must provide either `--profile` or `--api-key`. If using `--api-key`, the `--api-url` option is optional and will default to the production API URL.
|
|
69
86
|
|
|
70
87
|
**Features:**
|
|
71
88
|
|
|
72
|
-
- **
|
|
89
|
+
- **Flexible authentication**: Use either a saved profile or provide credentials directly
|
|
90
|
+
- **Profile validation**: Ensures the specified profile exists before uploading (when using `--profile`)
|
|
73
91
|
- **File validation**: Checks that the file exists and is a valid connector before attempting upload
|
|
92
|
+
- **Batch upload**: Supports uploading multiple connectors from a directory
|
|
74
93
|
|
|
75
94
|
### `validate`
|
|
76
95
|
|
|
@@ -106,7 +125,7 @@ Show the current version of the CLI:
|
|
|
106
125
|
|
|
107
126
|
```bash
|
|
108
127
|
stackone --version
|
|
109
|
-
stackone -
|
|
128
|
+
stackone -v
|
|
110
129
|
```
|
|
111
130
|
|
|
112
131
|
### Local Development
|
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-Bba3TFak.cjs`),t=new e.CLI;t.run();
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{CLI as e}from"./cliCore-
|
|
2
|
+
import{CLI as e}from"./cliCore-CGA-wigN.js";const t=new e;t.run();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const e=require(`./chunk-CUT6urMc.cjs`),t=e.__toESM(require(`chalk`)),n=e.__toESM(require(`commander`)),r=e.__toESM(require(`inquirer`)),i=e.__toESM(require(`fs`)),a=e.__toESM(require(`os`)),o=e.__toESM(require(`path`)),s=e.__toESM(require(`@stackone/connect-sdk`)),c=e.__toESM(require(`ora`)),l=e.__toESM(require(`url`)),u=(0,o.join)((0,a.homedir)(),`.stackone`),d={profiles:{}},f=()=>{if(!(0,i.existsSync)(u))return d;try{let e=(0,i.readFileSync)(u,`utf-8`);return JSON.parse(e)}catch{return d}},p=e=>{let t=f();return t.profiles[e]},m=e=>{let t=f();return!!t.profiles[e]},h=(e,t)=>{let n=f();n.profiles[e]=t;let r=(0,o.join)((0,a.homedir)());(0,i.existsSync)(r)||(0,i.mkdirSync)(r,{recursive:!0}),(0,i.writeFileSync)(u,JSON.stringify(n,null,2),`utf-8`)},g=()=>{let e=f();return Object.keys(e.profiles)};var _=class{static info(e){console.info(t.default.blue(`ℹ`),e)}static warn(e){console.info(t.default.yellow(`⚠`),e)}static error(e){console.info(t.default.red(`✗`),e)}static success(e){console.info(t.default.green(`✓`),e)}};const v=`https://api.stackone.com`,y=`https://api.stackone-dev.com`,b=`http://localhost:4000`;var x=class{async execute({environment:e}={}){let n=e?.toLowerCase()??`production`;try{let{label:e}=await r.default.prompt([{type:`input`,name:`label`,message:`Profile label:`,validate:e=>!e||e.trim().length===0?`The profile label is required`:e.includes(` `)?`The profile label cannot contain spaces`:!0}]);if(m(e)){let{overwrite:t}=await r.default.prompt([{type:`confirm`,name:`overwrite`,message:`Configuration profile with name "${e}" already exists. Do you want to overwrite it?`,default:!1}]);t||(_.info(`Configuration profile initialization cancelled`),process.exit(0))}let i;if(n===`production`)i=v;else if(n===`staging`)i=y;else{let{customUrl:e}=await r.default.prompt([{type:`input`,name:`customUrl`,message:`API URL:`,default:b,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{return new URL(e),!0}catch{return`Please enter a valid URL`}}}]);i=e}let{apiKey:a}=await r.default.prompt([{type:`password`,name:`apiKey`,message:`API Key:`,validate:e=>!e||e.trim().length===0?`API Key is required`:!0}]),o={label:e,environment:n,apiUrl:i,apiKey:a};h(e,o),console.info(t.default.green(`\n✓ Configuration profile "${e}" saved successfully`)),process.exit(0)}catch(e){e.isTtyError?_.error(`Prompt couldn't be rendered in the current environment`):_.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}};const S=`https://api.stackone.com`;var C=class{async execute({profile:e,fileOrDir:t,apiUrl:n,apiKey:r}={}){if(!e&&!r&&(_.error(`Please provide a profile or API key to use for pushing the connector.`),_.info(`You can provide these using the --profile and --api-key options.`),_.info(`Run "stackone init" to create a new configuration profile.`),process.exit(1)),e&&r&&(_.error(`Please provide either a profile or an API key, not both.`),process.exit(1)),e&&n&&_.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),e&&!m(e)){_.error(`Configuration profile "${e}" not found.`),_.info(`Run "stackone init" to create a new configuration profile.`);let t=g();_.info(`Available profiles: ${t.join(`, `)||`none`}`),process.exit(1)}let a=e?p(e):{apiUrl:n??S,apiKey:r};a||(_.error(`Failed to load configuration profile "${e}".`),process.exit(1)),a.apiKey||(_.error(`API key is missing. Please provide a valid API key in the profile or via the --api-key option.`),process.exit(1)),t||(_.error(`File or directory path is required.`),process.exit(1));try{(0,i.statSync)(t)}catch{_.error(`File or directory not found: ${t}`),process.exit(1)}let o=(0,i.statSync)(t),s=a.apiUrl??S;if(o.isDirectory()){let e=T(t),n=0;e.length===0?(_.error(`No .s1.yaml connector files found in the directory: ${t}.`),process.exit(1)):_.info(`Found ${e.length} connector(s) file(s). Processing...`);for(let t of e){console.info(`
|
|
2
|
+
`);let e=await this.uploadFile(t,s,a.apiKey);e&&n++}console.info(`
|
|
3
|
+
`),_.info(`Upload completed: ${n} of ${e.length} file(s) uploaded successfully.`),process.exit(n>0?0:1)}else t.endsWith(`.s1.yaml`)||(_.error(`Only .s1.yaml files are supported for upload.`),process.exit(1));let c=await this.uploadFile(t,s,a.apiKey);process.exit(c?0:1)}async uploadFile(e,n,r){try{console.info(t.default.blue(`📤 Uploading ${(0,o.basename)(e)}...`));let i=w(e);if(!i)return!1;let a=(0,o.basename)(e),s=new FormData,c=new Blob([i],{type:`application/x-yaml`});s.append(`file`,c,a);let l=Buffer.from(r).toString(`base64`),u=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${l}`},body:s});if(!u.ok){let e=await u.text();return _.error(`Upload failed: ${u.status} - ${u.statusText}`),e&&console.error(t.default.red(e)),!1}let d=await u.json();return console.info(t.default.green(`✓ Successfully uploaded ${a} with connector "${d.provider}@${d.version}"`)),!0}catch(e){return _.error(`Failed to upload file: ${e}`),!1}}};const w=e=>{let n=(0,s.loadConnector)(e),r=(0,s.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let t=e.split(`/`).pop()||e;return _.success(`Connector ${t} is valid!`),n}else i.length>0?(_.error(`Connector ${e} is not valid. Please fix the following errors:\n`),i.forEach(e=>{console.info(t.default.red(`- L${e.line}: ${e.message}`))})):_.error(`Connector ${e} is not valid. Please check the file for errors.`)},T=e=>{let t=[],n=(0,i.readdirSync)(e,{withFileTypes:!0});for(let r of n){let n=(0,o.join)(e,r.name);r.isDirectory()?t.push(...T(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t};var E=class{async execute(e){let{watchMode:n,fileOrDir:r}=e,a=(0,c.default)(`Watching for changes...`),o=()=>{console.clear(),console.info(t.default.yellow(`Watch mode enabled. Press "q" to quit.
|
|
4
|
+
`))};if(r){try{(0,i.statSync)(r)}catch{_.error(`File or directory not found: ${r}`),process.exit(1)}if(n){let{watch:e}=await Promise.resolve().then(()=>require(`./esm-BrK-ICga.cjs`)),n=await import(`readline`),i=n.createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{console.info(t.default.grey(`
|
|
5
|
+
|
|
6
|
+
Exiting watch mode...`)),c.close(),a.stop(),i.close(),process.exit(0)};o(),console.info(t.default.blue(`Running connector(s) validations...`)),await D(r),a.start();let c=e(r||`.`,{ignored:/(^|[/\\])\../,persistent:!0});c.on(`change`,async e=>{o(),a.stop(),console.info(t.default.blue(`File change detected. Running connector(s) validations...`)),await D(r),a.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else await D(r),process.exit(0)}}};const D=async e=>{let t=(0,i.statSync)(e);if(t.isDirectory()){let t=(0,i.readdirSync)(e),n=t.filter(e=>e.endsWith(`.s1.yaml`));if(n.length===0){_.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let r=0,a=0;for(let t of n){let n=`${e}/${t}`,o=(0,i.statSync)(n);if(o.isFile()){let e=await O(n);e?r++:a++}}_.info(`Validation completed: ${r} valid, ${a} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await O(e):_.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},O=async e=>{let n=(0,s.loadConnector)(e),r=(0,s.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let t=e.split(`/`).pop()||e;return _.success(`Connector ${t} is valid!\n`),!0}else if(i.length>0)return _.error(`Connector ${e} is not valid. Please fix the following errors:\n`),i.forEach(e=>{console.info(t.default.red(`- L${e.line}: ${e.message}`))}),console.info(`
|
|
7
|
+
`),!1;else return _.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},k=()=>{try{let e=(0,l.fileURLToPath)(require(`url`).pathToFileURL(__filename).href),t=(0,o.dirname)(e),n=(0,o.join)(t,`..`,`package.json`),r=JSON.parse((0,i.readFileSync)(n,`utf8`));return r.version}catch{return`unknown`}};var A=class{constructor(e=new n.Command,t=k()){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 x,r=new C,i=new E;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,n)=>{n(t.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 n.Argument(`<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(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new n.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(`version`).description(`Show version information`).action(()=>{console.info(`${t.default.greenBright(`StackOne`)} ${t.default.grey(`CLI`)} ${t.default.whiteBright(this.version)}`),process.exit(0)})}run(){this.program.parse(process.argv)}};Object.defineProperty(exports,`CLI`,{enumerable:!0,get:function(){return A}});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from"chalk";import{Argument as t,Command as n}from"commander";import r from"inquirer";import{existsSync as i,mkdirSync as a,readFileSync as o,readdirSync as s,statSync as c,writeFileSync as l}from"fs";import{homedir as u}from"os";import{basename as d,dirname as f,join as p}from"path";import{loadConnector as m,validateYamlConnector as h}from"@stackone/connect-sdk";import g from"ora";import{fileURLToPath as _}from"url";const v=p(u(),`.stackone`),y={profiles:{}},b=()=>{if(!i(v))return y;try{let e=o(v,`utf-8`);return JSON.parse(e)}catch{return y}},x=e=>{let t=b();return t.profiles[e]},S=e=>{let t=b();return!!t.profiles[e]},C=(e,t)=>{let n=b();n.profiles[e]=t;let r=p(u());i(r)||a(r,{recursive:!0}),l(v,JSON.stringify(n,null,2),`utf-8`)},w=()=>{let e=b();return Object.keys(e.profiles)};var T=class{static info(t){console.info(e.blue(`ℹ`),t)}static warn(t){console.info(e.yellow(`⚠`),t)}static error(t){console.info(e.red(`✗`),t)}static success(t){console.info(e.green(`✓`),t)}};const E=`https://api.stackone.com`,D=`https://api.stackone-dev.com`,O=`http://localhost:4000`;var k=class{async execute({environment:t}={}){let n=t?.toLowerCase()??`production`;try{let{label:t}=await r.prompt([{type:`input`,name:`label`,message:`Profile label:`,validate:e=>!e||e.trim().length===0?`The profile label is required`:e.includes(` `)?`The profile label cannot contain spaces`:!0}]);if(S(t)){let{overwrite:e}=await r.prompt([{type:`confirm`,name:`overwrite`,message:`Configuration profile with name "${t}" already exists. Do you want to overwrite it?`,default:!1}]);e||(T.info(`Configuration profile initialization cancelled`),process.exit(0))}let i;if(n===`production`)i=E;else if(n===`staging`)i=D;else{let{customUrl:e}=await r.prompt([{type:`input`,name:`customUrl`,message:`API URL:`,default:O,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{return new URL(e),!0}catch{return`Please enter a valid URL`}}}]);i=e}let{apiKey:a}=await r.prompt([{type:`password`,name:`apiKey`,message:`API Key:`,validate:e=>!e||e.trim().length===0?`API Key is required`:!0}]),o={label:t,environment:n,apiUrl:i,apiKey:a};C(t,o),console.info(e.green(`\n✓ Configuration profile "${t}" saved successfully`)),process.exit(0)}catch(e){e.isTtyError?T.error(`Prompt couldn't be rendered in the current environment`):T.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}};const A=`https://api.stackone.com`;var j=class{async execute({profile:e,fileOrDir:t,apiUrl:n,apiKey:r}={}){if(!e&&!r&&(T.error(`Please provide a profile or API key to use for pushing the connector.`),T.info(`You can provide these using the --profile and --api-key options.`),T.info(`Run "stackone init" to create a new configuration profile.`),process.exit(1)),e&&r&&(T.error(`Please provide either a profile or an API key, not both.`),process.exit(1)),e&&n&&T.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),e&&!S(e)){T.error(`Configuration profile "${e}" not found.`),T.info(`Run "stackone init" to create a new configuration profile.`);let t=w();T.info(`Available profiles: ${t.join(`, `)||`none`}`),process.exit(1)}let i=e?x(e):{apiUrl:n??A,apiKey:r};i||(T.error(`Failed to load configuration profile "${e}".`),process.exit(1)),i.apiKey||(T.error(`API key is missing. Please provide a valid API key in the profile or via the --api-key option.`),process.exit(1)),t||(T.error(`File or directory path is required.`),process.exit(1));try{c(t)}catch{T.error(`File or directory not found: ${t}`),process.exit(1)}let a=c(t),o=i.apiUrl??A;if(a.isDirectory()){let e=N(t),n=0;e.length===0?(T.error(`No .s1.yaml connector files found in the directory: ${t}.`),process.exit(1)):T.info(`Found ${e.length} connector(s) file(s). Processing...`);for(let t of e){console.info(`
|
|
2
|
+
`);let e=await this.uploadFile(t,o,i.apiKey);e&&n++}console.info(`
|
|
3
|
+
`),T.info(`Upload completed: ${n} of ${e.length} file(s) uploaded successfully.`),process.exit(n>0?0:1)}else t.endsWith(`.s1.yaml`)||(T.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(t,n,r){try{console.info(e.blue(`📤 Uploading ${d(t)}...`));let i=M(t);if(!i)return!1;let a=d(t),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 t=await l.text();return T.error(`Upload failed: ${l.status} - ${l.statusText}`),t&&console.error(e.red(t)),!1}let u=await l.json();return console.info(e.green(`✓ Successfully uploaded ${a} with connector "${u.provider}@${u.version}"`)),!0}catch(e){return T.error(`Failed to upload file: ${e}`),!1}}};const M=t=>{let n=m(t),r=h(n),i=r?.errors??[];if(r.success){let e=t.split(`/`).pop()||t;return T.success(`Connector ${e} is valid!`),n}else i.length>0?(T.error(`Connector ${t} is not valid. Please fix the following errors:\n`),i.forEach(t=>{console.info(e.red(`- L${t.line}: ${t.message}`))})):T.error(`Connector ${t} is not valid. Please check the file for errors.`)},N=e=>{let t=[],n=s(e,{withFileTypes:!0});for(let r of n){let n=p(e,r.name);r.isDirectory()?t.push(...N(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t};var P=class{async execute(t){let{watchMode:n,fileOrDir:r}=t,i=g(`Watching for changes...`),a=()=>{console.clear(),console.info(e.yellow(`Watch mode enabled. Press "q" to quit.
|
|
4
|
+
`))};if(r){try{c(r)}catch{T.error(`File or directory not found: ${r}`),process.exit(1)}if(n){let{watch:t}=await import(`./esm-D_hUWJ1V.js`),n=await import(`readline`),o=n.createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{console.info(e.grey(`
|
|
5
|
+
|
|
6
|
+
Exiting watch mode...`)),c.close(),i.stop(),o.close(),process.exit(0)};a(),console.info(e.blue(`Running connector(s) validations...`)),await F(r),i.start();let c=t(r||`.`,{ignored:/(^|[/\\])\../,persistent:!0});c.on(`change`,async t=>{a(),i.stop(),console.info(e.blue(`File change detected. Running connector(s) validations...`)),await F(r),i.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else await F(r),process.exit(0)}}};const F=async e=>{let t=c(e);if(t.isDirectory()){let t=s(e),n=t.filter(e=>e.endsWith(`.s1.yaml`));if(n.length===0){T.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let r=0,i=0;for(let t of n){let n=`${e}/${t}`,a=c(n);if(a.isFile()){let e=await I(n);e?r++:i++}}T.info(`Validation completed: ${r} valid, ${i} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await I(e):T.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},I=async t=>{let n=m(t),r=h(n),i=r?.errors??[];if(r.success){let e=t.split(`/`).pop()||t;return T.success(`Connector ${e} is valid!\n`),!0}else if(i.length>0)return T.error(`Connector ${t} is not valid. Please fix the following errors:\n`),i.forEach(t=>{console.info(e.red(`- L${t.line}: ${t.message}`))}),console.info(`
|
|
7
|
+
`),!1;else return T.error(`Connector ${t} is not valid. Please check the file for errors.`),!1},L=()=>{try{let e=_(import.meta.url),t=f(e),n=p(t,`..`,`package.json`),r=JSON.parse(o(n,`utf8`));return r.version}catch{return`unknown`}};var R=class{constructor(e=new n,t=L()){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 n=new k,r=new j,i=new P;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(t,n)=>{n(e.red(t))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(e=>{n.execute({environment:e.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 t(`<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(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new t(`<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(`version`).description(`Show version information`).action(()=>{console.info(`${e.greenBright(`StackOne`)} ${e.grey(`CLI`)} ${e.whiteBright(this.version)}`),process.exit(0)})}run(){this.program.parse(process.argv)}};export{R as CLI};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./cliCore-
|
|
1
|
+
const e=require(`./cliCore-Bba3TFak.cjs`);exports.CLI=e.CLI;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CLI as e}from"./cliCore-
|
|
1
|
+
import{CLI as e}from"./cliCore-CGA-wigN.js";export{e as CLI};
|
package/package.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
const e=require(`./chunk-CUT6urMc.cjs`),t=e.__toESM(require(`chalk`)),n=e.__toESM(require(`commander`)),r=e.__toESM(require(`inquirer`)),i=e.__toESM(require(`fs`)),a=e.__toESM(require(`os`)),o=e.__toESM(require(`path`)),s=e.__toESM(require(`@stackone/connect-sdk`)),c=e.__toESM(require(`ora`)),l=e.__toESM(require(`url`)),u=(0,o.join)((0,a.homedir)(),`.stackone`),d={profiles:{}},f=()=>{if(!(0,i.existsSync)(u))return d;try{let e=(0,i.readFileSync)(u,`utf-8`);return JSON.parse(e)}catch{return d}},p=e=>{let t=f();return t.profiles[e]},m=e=>{let t=f();return!!t.profiles[e]},h=(e,t)=>{let n=f();n.profiles[e]=t;let r=(0,o.join)((0,a.homedir)());(0,i.existsSync)(r)||(0,i.mkdirSync)(r,{recursive:!0}),(0,i.writeFileSync)(u,JSON.stringify(n,null,2),`utf-8`)},g=()=>{let e=f();return Object.keys(e.profiles)};var _=class{static info(e){console.info(t.default.blue(`ℹ`),e)}static warn(e){console.info(t.default.yellow(`⚠`),e)}static error(e){console.info(t.default.red(`✗`),e)}static success(e){console.info(t.default.green(`✓`),e)}};const v=`https://api.stackone.com`,y=`https://api.stackone-dev.com`,b=`http://localhost:4000`;var x=class{async execute(){try{let{label:e}=await r.default.prompt([{type:`input`,name:`label`,message:`Profile label:`,validate:e=>!e||e.trim().length===0?`The profile label is required`:e.includes(` `)?`The profile label cannot contain spaces`:!0}]);if(m(e)){let{overwrite:t}=await r.default.prompt([{type:`confirm`,name:`overwrite`,message:`Configuration profile with name "${e}" already exists. Do you want to overwrite it?`,default:!1}]);t||(_.info(`Configuration profile initialization cancelled`),process.exit(0))}let{environment:n}=await r.default.prompt([{type:`list`,name:`environment`,message:`Environment:`,choices:[`production`,`staging`,`local`]}]),i;if(n===`production`)i=v;else if(n===`staging`)i=y;else{let{customUrl:e}=await r.default.prompt([{type:`input`,name:`customUrl`,message:`API URL:`,default:b,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{return new URL(e),!0}catch{return`Please enter a valid URL`}}}]);i=e}let{apiKey:a}=await r.default.prompt([{type:`password`,name:`apiKey`,message:`API Key:`,validate:e=>!e||e.trim().length===0?`API Key is required`:!0}]),o={label:e,environment:n,apiUrl:i,apiKey:a};h(e,o),console.info(t.default.green(`\n✓ Configuration profile "${e}" saved successfully`)),process.exit(0)}catch(e){e.isTtyError?_.error(`Prompt couldn't be rendered in the current environment`):_.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}},S=class{async execute(e){let{profile:t,fileOrDir:n}=e;if(t||(_.error(`Profile is required. Use --profile <label> to specify a configuration.`),_.info(`Run "stackone init" to create a new configuration profile.`),process.exit(1)),!m(t)){_.error(`Configuration profile "${t}" not found.`),_.info(`Run "stackone init" to create a new configuration profile.`);let e=g();_.info(`Available profiles: ${e.join(`, `)||`none`}`),process.exit(1)}let r=p(t);r||(_.error(`Failed to load configuration profile "${t}".`),process.exit(1)),n||(_.error(`File or directory path is required.`),process.exit(1));try{(0,i.statSync)(n)}catch{_.error(`File or directory not found: ${n}`),process.exit(1)}let a=(0,i.statSync)(n);if(a.isDirectory()){let e=w(n),t=0;e.length===0?(_.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):_.info(`Found ${e.length} connector(s) file(s). Processing...`);for(let n of e){console.info(`
|
|
2
|
-
`);let e=await this.uploadFile(n,r.apiUrl,r.apiKey);e&&t++}console.info(`
|
|
3
|
-
`),_.info(`Upload completed: ${t} of ${e.length} file(s) uploaded successfully.`),process.exit(t>0?0:1)}else n.endsWith(`.s1.yaml`)||(_.error(`Only .s1.yaml files are supported for upload.`),process.exit(1));let o=await this.uploadFile(n,r.apiUrl,r.apiKey);process.exit(o?0:1)}async uploadFile(e,n,r){try{console.info(t.default.blue(`📤 Uploading ${(0,o.basename)(e)}...`));let i=C(e);if(!i)return!1;let a=(0,o.basename)(e),s=new FormData,c=new Blob([i],{type:`application/x-yaml`});s.append(`file`,c,a);let l=Buffer.from(r).toString(`base64`),u=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${l}`},body:s});if(!u.ok){let e=await u.text();return _.error(`Upload failed: ${u.status} - ${u.statusText}`),e&&console.error(t.default.red(e)),!1}let d=await u.json();return console.info(t.default.green(`✓ Successfully uploaded ${a} with connector "${d.provider}@${d.version}"`)),!0}catch(e){return _.error(`Failed to upload file: ${e}`),!1}}};const C=e=>{let n=(0,s.loadConnector)(e),r=(0,s.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let t=e.split(`/`).pop()||e;return _.success(`Connector ${t} is valid!`),n}else i.length>0?(_.error(`Connector ${e} is not valid. Please fix the following errors:\n`),i.forEach(e=>{console.info(t.default.red(`- L${e.line}: ${e.message}`))})):_.error(`Connector ${e} is not valid. Please check the file for errors.`)},w=e=>{let t=[],n=(0,i.readdirSync)(e,{withFileTypes:!0});for(let r of n){let n=(0,o.join)(e,r.name);r.isDirectory()?t.push(...w(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t};var T=class{async execute(e){let{watchMode:n,fileOrDir:r}=e,a=(0,c.default)(`Watching for changes...`),o=()=>{console.clear(),console.info(t.default.yellow(`Watch mode enabled. Press "q" to quit.
|
|
4
|
-
`))};if(r){try{(0,i.statSync)(r)}catch{_.error(`File or directory not found: ${r}`),process.exit(1)}if(n){let{watch:e}=await Promise.resolve().then(()=>require(`./esm-BrK-ICga.cjs`)),n=await import(`readline`),i=n.createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{console.info(t.default.grey(`
|
|
5
|
-
|
|
6
|
-
Exiting watch mode...`)),c.close(),a.stop(),i.close(),process.exit(0)};o(),console.info(t.default.blue(`Running connector(s) validations...`)),await E(r),a.start();let c=e(r||`.`,{ignored:/(^|[/\\])\../,persistent:!0});c.on(`change`,async e=>{o(),a.stop(),console.info(t.default.blue(`File change detected. Running connector(s) validations...`)),await E(r),a.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else await E(r),process.exit(0)}}};const E=async e=>{let t=(0,i.statSync)(e);if(t.isDirectory()){let t=(0,i.readdirSync)(e),n=t.filter(e=>e.endsWith(`.s1.yaml`));if(n.length===0){_.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let r=0,a=0;for(let t of n){let n=`${e}/${t}`,o=(0,i.statSync)(n);if(o.isFile()){let e=await D(n);e?r++:a++}}_.info(`Validation completed: ${r} valid, ${a} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await D(e):_.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},D=async e=>{let n=(0,s.loadConnector)(e),r=(0,s.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let t=e.split(`/`).pop()||e;return _.success(`Connector ${t} is valid!\n`),!0}else if(i.length>0)return _.error(`Connector ${e} is not valid. Please fix the following errors:\n`),i.forEach(e=>{console.info(t.default.red(`- L${e.line}: ${e.message}`))}),console.info(`
|
|
7
|
-
`),!1;else return _.error(`Connector ${e} is not valid. Please check the file for errors.`),!1},O=()=>{try{let e=(0,l.fileURLToPath)(require(`url`).pathToFileURL(__filename).href),t=(0,o.dirname)(e),n=(0,o.join)(t,`..`,`package.json`),r=JSON.parse((0,i.readFileSync)(n,`utf8`));return r.version}catch{return`unknown`}};var k=class{constructor(e=new n.Command,t=O()){this.program=e,this.version=t,this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version)}registerCommands(){let e=new x,r=new S,i=new T;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,n)=>{n(t.default.red(e))}}),this.program.command(`init`).description(`Initialize & create a StackOne CLI configuration profile`).action(()=>{e.execute()}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).addArgument(new n.Argument(`<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})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new n.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(`version`).description(`Show version information`).action(()=>{console.info(`${t.default.greenBright(`StackOne`)} ${t.default.grey(`CLI`)} ${t.default.whiteBright(this.version)}`),process.exit(0)})}run(){this.program.parse(process.argv)}};Object.defineProperty(exports,`CLI`,{enumerable:!0,get:function(){return k}});
|
package/dist/cliCore-CYhcPSJT.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import e from"chalk";import{Argument as t,Command as n}from"commander";import r from"inquirer";import{existsSync as i,mkdirSync as a,readFileSync as o,readdirSync as s,statSync as c,writeFileSync as l}from"fs";import{homedir as u}from"os";import{basename as d,dirname as f,join as p}from"path";import{loadConnector as m,validateYamlConnector as h}from"@stackone/connect-sdk";import g from"ora";import{fileURLToPath as _}from"url";const v=p(u(),`.stackone`),y={profiles:{}},b=()=>{if(!i(v))return y;try{let e=o(v,`utf-8`);return JSON.parse(e)}catch{return y}},x=e=>{let t=b();return t.profiles[e]},S=e=>{let t=b();return!!t.profiles[e]},C=(e,t)=>{let n=b();n.profiles[e]=t;let r=p(u());i(r)||a(r,{recursive:!0}),l(v,JSON.stringify(n,null,2),`utf-8`)},w=()=>{let e=b();return Object.keys(e.profiles)};var T=class{static info(t){console.info(e.blue(`ℹ`),t)}static warn(t){console.info(e.yellow(`⚠`),t)}static error(t){console.info(e.red(`✗`),t)}static success(t){console.info(e.green(`✓`),t)}};const E=`https://api.stackone.com`,D=`https://api.stackone-dev.com`,O=`http://localhost:4000`;var k=class{async execute(){try{let{label:t}=await r.prompt([{type:`input`,name:`label`,message:`Profile label:`,validate:e=>!e||e.trim().length===0?`The profile label is required`:e.includes(` `)?`The profile label cannot contain spaces`:!0}]);if(S(t)){let{overwrite:e}=await r.prompt([{type:`confirm`,name:`overwrite`,message:`Configuration profile with name "${t}" already exists. Do you want to overwrite it?`,default:!1}]);e||(T.info(`Configuration profile initialization cancelled`),process.exit(0))}let{environment:n}=await r.prompt([{type:`list`,name:`environment`,message:`Environment:`,choices:[`production`,`staging`,`local`]}]),i;if(n===`production`)i=E;else if(n===`staging`)i=D;else{let{customUrl:e}=await r.prompt([{type:`input`,name:`customUrl`,message:`API URL:`,default:O,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{return new URL(e),!0}catch{return`Please enter a valid URL`}}}]);i=e}let{apiKey:a}=await r.prompt([{type:`password`,name:`apiKey`,message:`API Key:`,validate:e=>!e||e.trim().length===0?`API Key is required`:!0}]),o={label:t,environment:n,apiUrl:i,apiKey:a};C(t,o),console.info(e.green(`\n✓ Configuration profile "${t}" saved successfully`)),process.exit(0)}catch(e){e.isTtyError?T.error(`Prompt couldn't be rendered in the current environment`):T.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}},A=class{async execute(e){let{profile:t,fileOrDir:n}=e;if(t||(T.error(`Profile is required. Use --profile <label> to specify a configuration.`),T.info(`Run "stackone init" to create a new configuration profile.`),process.exit(1)),!S(t)){T.error(`Configuration profile "${t}" not found.`),T.info(`Run "stackone init" to create a new configuration profile.`);let e=w();T.info(`Available profiles: ${e.join(`, `)||`none`}`),process.exit(1)}let r=x(t);r||(T.error(`Failed to load configuration profile "${t}".`),process.exit(1)),n||(T.error(`File or directory path is required.`),process.exit(1));try{c(n)}catch{T.error(`File or directory not found: ${n}`),process.exit(1)}let i=c(n);if(i.isDirectory()){let e=M(n),t=0;e.length===0?(T.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):T.info(`Found ${e.length} connector(s) file(s). Processing...`);for(let n of e){console.info(`
|
|
2
|
-
`);let e=await this.uploadFile(n,r.apiUrl,r.apiKey);e&&t++}console.info(`
|
|
3
|
-
`),T.info(`Upload completed: ${t} of ${e.length} file(s) uploaded successfully.`),process.exit(t>0?0:1)}else n.endsWith(`.s1.yaml`)||(T.error(`Only .s1.yaml files are supported for upload.`),process.exit(1));let a=await this.uploadFile(n,r.apiUrl,r.apiKey);process.exit(a?0:1)}async uploadFile(t,n,r){try{console.info(e.blue(`📤 Uploading ${d(t)}...`));let i=j(t);if(!i)return!1;let a=d(t),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 t=await l.text();return T.error(`Upload failed: ${l.status} - ${l.statusText}`),t&&console.error(e.red(t)),!1}let u=await l.json();return console.info(e.green(`✓ Successfully uploaded ${a} with connector "${u.provider}@${u.version}"`)),!0}catch(e){return T.error(`Failed to upload file: ${e}`),!1}}};const j=t=>{let n=m(t),r=h(n),i=r?.errors??[];if(r.success){let e=t.split(`/`).pop()||t;return T.success(`Connector ${e} is valid!`),n}else i.length>0?(T.error(`Connector ${t} is not valid. Please fix the following errors:\n`),i.forEach(t=>{console.info(e.red(`- L${t.line}: ${t.message}`))})):T.error(`Connector ${t} is not valid. Please check the file for errors.`)},M=e=>{let t=[],n=s(e,{withFileTypes:!0});for(let r of n){let n=p(e,r.name);r.isDirectory()?t.push(...M(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t};var N=class{async execute(t){let{watchMode:n,fileOrDir:r}=t,i=g(`Watching for changes...`),a=()=>{console.clear(),console.info(e.yellow(`Watch mode enabled. Press "q" to quit.
|
|
4
|
-
`))};if(r){try{c(r)}catch{T.error(`File or directory not found: ${r}`),process.exit(1)}if(n){let{watch:t}=await import(`./esm-D_hUWJ1V.js`),n=await import(`readline`),o=n.createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{console.info(e.grey(`
|
|
5
|
-
|
|
6
|
-
Exiting watch mode...`)),c.close(),i.stop(),o.close(),process.exit(0)};a(),console.info(e.blue(`Running connector(s) validations...`)),await P(r),i.start();let c=t(r||`.`,{ignored:/(^|[/\\])\../,persistent:!0});c.on(`change`,async t=>{a(),i.stop(),console.info(e.blue(`File change detected. Running connector(s) validations...`)),await P(r),i.start()}),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else await P(r),process.exit(0)}}};const P=async e=>{let t=c(e);if(t.isDirectory()){let t=s(e),n=t.filter(e=>e.endsWith(`.s1.yaml`));if(n.length===0){T.error(`No StackOne connectors found in directory: ${e}. Connector files need to have the extension .s1.yaml.\n`);return}let r=0,i=0;for(let t of n){let n=`${e}/${t}`,a=c(n);if(a.isFile()){let e=await F(n);e?r++:i++}}T.info(`Validation completed: ${r} valid, ${i} invalid connectors.\n`)}else t.isFile()&&e.endsWith(`s1.yaml`)?await F(e):T.error(`No StackOne connector found: ${e}. Connector files need to have the extension .s1.yaml.\n`)},F=async t=>{let n=m(t),r=h(n),i=r?.errors??[];if(r.success){let e=t.split(`/`).pop()||t;return T.success(`Connector ${e} is valid!\n`),!0}else if(i.length>0)return T.error(`Connector ${t} is not valid. Please fix the following errors:\n`),i.forEach(t=>{console.info(e.red(`- L${t.line}: ${t.message}`))}),console.info(`
|
|
7
|
-
`),!1;else return T.error(`Connector ${t} is not valid. Please check the file for errors.`),!1},I=()=>{try{let e=_(import.meta.url),t=f(e),n=p(t,`..`,`package.json`),r=JSON.parse(o(n,`utf8`));return r.version}catch{return`unknown`}};var L=class{constructor(e=new n,t=I()){this.program=e,this.version=t,this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version)}registerCommands(){let n=new k,r=new A,i=new N;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(t,n)=>{n(e.red(t))}}),this.program.command(`init`).description(`Initialize & create a StackOne CLI configuration profile`).action(()=>{n.execute()}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).addArgument(new t(`<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})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new t(`<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(`version`).description(`Show version information`).action(()=>{console.info(`${e.greenBright(`StackOne`)} ${e.grey(`CLI`)} ${e.whiteBright(this.version)}`),process.exit(0)})}run(){this.program.parse(process.argv)}};export{L as CLI};
|