dashnex 0.5.40 → 0.5.42
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 +1 -3
- package/dist/commands/app/deploy.js +1 -1
- package/dist/commands/app/index.js +1 -1
- package/dist/commands/app/push.js +1 -1
- package/dist/commands/check.js +1 -1
- package/dist/package.json.js +1 -1
- package/dist/services/auth.js +1 -1
- package/dist/src/commands/app/deploy.d.ts +1 -4
- package/dist/src/commands/app/push.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,9 +51,7 @@ dashnex <command> [options]
|
|
|
51
51
|
|
|
52
52
|
**app push**:
|
|
53
53
|
- `--deploy` / `--no-deploy` — Auto-deploy or skip deploy after push
|
|
54
|
+
- `--no-check` — Skip pre-push checks
|
|
54
55
|
|
|
55
56
|
**app delete**:
|
|
56
57
|
- `-y, --yes` — Skip confirmation prompt
|
|
57
|
-
|
|
58
|
-
**app deploy**:
|
|
59
|
-
- `--no-check` — Skip pre-deploy checks
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"chalk";import{debug as t,debugError as o}from"../../lib/debug.js";import{getDeployerBase as s,getBusinessApiBase as r}from"../../lib/api.js";import{ensureLoggedIn as n}from"../../services/auth.js";import{createSpinner as a}from"../../lib/spinner.js";import{isUserInterrupt as i,INTERRUPTED_MESSAGE as c}from"../../lib/errors.js";import{getApplicationUrl as l}from"../../lib/app-url.js";import{ensureAgreements as p}from"../../services/agreements.js";
|
|
1
|
+
import e from"chalk";import{debug as t,debugError as o}from"../../lib/debug.js";import{getDeployerBase as s,getBusinessApiBase as r}from"../../lib/api.js";import{ensureLoggedIn as n}from"../../services/auth.js";import{createSpinner as a}from"../../lib/spinner.js";import{isUserInterrupt as i,INTERRUPTED_MESSAGE as c}from"../../lib/errors.js";import{getApplicationUrl as l}from"../../lib/app-url.js";import{ensureAgreements as p}from"../../services/agreements.js";const d=3e5,m=99,f=e=>new Promise(t=>setTimeout(t,e)),u=async(s,r,n,a)=>{const i=await fetch(s,{method:"GET",headers:{Authorization:`Bearer ${r}`,Accept:"text/event-stream"}});if(t(`SSE connection opened: ${i.status}`),!i.ok){const t=i.status;let o="Failed to start deployment.";if(401===t||403===t)o="Please run 'dashnex login' to authenticate.";else try{const e=await i.text(),t=JSON.parse(e);"string"==typeof t.error?o=t.error:"string"==typeof t.message&&(o=t.message)}catch{}throw console.error(e.red(o)),new Error(`HTTP ${t}: ${o}`)}if(!i.body)throw new Error("Response body is null");t("SSE connection established successfully"),a?.();const c=i.body.getReader();try{for await(const e of async function*(e){const t=new TextDecoder("utf-8");let o="";for(;;){const{value:s,done:r}=await e.read();if(r)break;o+=t.decode(s,{stream:!0});const n=o.split("\n");o=n.pop()||"";let a="";for(const e of n)e.startsWith("data: ")?a=e.slice(6):""===e&&a&&(yield{data:a},a="")}if(o.startsWith("data: ")){const e=o.slice(6);e&&(yield{data:e})}}(c))try{if(!e.data){t("Received empty SSE event");continue}const o=JSON.parse(e.data);t(`SSE message received: ${JSON.stringify(o)}`),n(o)}catch(l){o(l),t(`Failed to parse SSE event data: ${e.data}`)}}finally{c.releaseLock()}};class y{async execute(){t("Deploy flow started");const r=await n();if(!r)return;if(!(await p(r.token,{ciMode:!0})))return;const l=`${s()}/business/v1/applications/deploy`;t(`GET ${l} (SSE)`);let y=0,h="",g=!1,w=0,S=!1;const $=a();let b=0,v=0,x=null;const E=(e,t)=>{const o=Math.round(e);$.text(`[${o}%] ${t}`)},D=()=>{k();const e=y,t=Date.now(),o=d*((m-e)/m);x=setInterval(()=>{const s=Date.now()-t;let r;if(v>t){const e=Date.now()-v,t=m-b,o=t*3030.3030303030305;r=Math.min(b+e/o*t,m)}else r=Math.min(e+s/o*(m-e),m);r>y&&(y=r,E(y,h))},200)},k=()=>{x&&(clearInterval(x),x=null)};let T=!1;const j=t=>{if(S=!0,"string"==typeof t.error)return k(),$.stop(),console.error(e.red(t.error)),g=!0,void(T=!0);if("string"==typeof t.message&&(h=t.message),"number"==typeof t.progress&&(b=t.progress,v=Date.now(),t.progress>y&&(y=t.progress)),"string"==typeof t.message||"number"==typeof t.progress)if(y>=100){k(),$.stop();const t=h||"Application is deployed";process.stdout.write(`${e.green(t)}\n`),g=!0}else E(y,h)};for(;w<=5;)try{return S?E(y,h):$.start("Connecting..."),D(),await u(l,r.token,j,()=>{S||($.text(`[${Math.round(y)}%] Deployment in progress...`),h="Deployment in progress...")}),k(),$.stop(),t("SSE connection closed"),T&&process.exit(1),void(g&&await this.showDeployedUrl(r.token))}catch(M){if(k(),o(M),t(`SSE connection error: ${M}`),g)return $.stop(),void(T&&process.exit(1));if(i(M))return $.stop(),void console.log(e.yellow(c));M instanceof Error&&M.message.startsWith("HTTP")&&($.stop(),console.error(e.red("Could not complete deployment. Check your connection and try again.")),process.exit(1)),w++,w>5&&($.stop(),console.error(e.red("Deployment failed. Maximum reconnection attempts exceeded.")),process.exit(1));const s=Math.min(1e3*Math.pow(2,w-1),3e4);t(`Connection error. Reconnecting in ${s/1e3}s... (attempt ${w}/5)`),await f(s)}}async showDeployedUrl(s){try{const o=`${r()}/business/v1/applications`;t(`GET ${o} (for deployed URL)`);const n=await fetch(o,{headers:{Authorization:`Bearer ${s}`}});if(!n.ok)return;const a=await n.json().catch(()=>({})),i=l({subdomain:a.subdomain,appFullCustomDomain:a.appFullCustomDomain});i&&console.log(`Application is deployed to ${e.cyan(i)}`)}catch(n){o(n)}}}export{y as DeployCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CreateCommand as e}from"./create.js";import{PullCommand as o}from"./pull.js";import{PushCommand as p}from"./push.js";import{DeleteCommand as a}from"./delete.js";import{DeployCommand as i}from"./deploy.js";import{StatusCommand as t}from"./status.js";const s={name:"app",description:"Manage DashNex applications",handler:{execute:async()=>{}},options:[],subcommands:[{name:"create",description:"Create a new DashNex application",handler:new e,options:[{flags:"-t, --template <template>",description:"Template (name@branch-or-tag)",defaultValue:"webapp-base@live"},{flags:"--subdomain <subdomain>",description:"Subdomain (CI mode, skip prompts)"}]},{name:"pull",description:"Pull existing application to specified folder",handler:new o,options:[{flags:"-y, --yes",description:"Skip prompts and child commands (CI mode)"}]},{name:"push",description:"Push local application to DashNex",handler:new p,options:[{flags:"--deploy",description:"Auto-deploy after push (skip prompt)"},{flags:"--no-deploy",description:"Skip deploy prompt"}]},{name:"delete",description:"Delete application from DashNex",handler:new a,options:[{flags:"-y, --yes",description:"Skip confirmation prompt"}]},{name:"deploy",description:"Deploy application to DashNex",handler:new i,options:[
|
|
1
|
+
import{CreateCommand as e}from"./create.js";import{PullCommand as o}from"./pull.js";import{PushCommand as p}from"./push.js";import{DeleteCommand as a}from"./delete.js";import{DeployCommand as i}from"./deploy.js";import{StatusCommand as t}from"./status.js";const s={name:"app",description:"Manage DashNex applications",handler:{execute:async()=>{}},options:[],subcommands:[{name:"create",description:"Create a new DashNex application",handler:new e,options:[{flags:"-t, --template <template>",description:"Template (name@branch-or-tag)",defaultValue:"webapp-base@live"},{flags:"--subdomain <subdomain>",description:"Subdomain (CI mode, skip prompts)"}]},{name:"pull",description:"Pull existing application to specified folder",handler:new o,options:[{flags:"-y, --yes",description:"Skip prompts and child commands (CI mode)"}]},{name:"push",description:"Push local application to DashNex",handler:new p,options:[{flags:"--deploy",description:"Auto-deploy after push (skip prompt)"},{flags:"--no-deploy",description:"Skip deploy prompt"},{flags:"--no-check",description:"Skip pre-push checks"}]},{name:"delete",description:"Delete application from DashNex",handler:new a,options:[{flags:"-y, --yes",description:"Skip confirmation prompt"}]},{name:"deploy",description:"Deploy application to DashNex",handler:new i,options:[]},{name:"status",description:"Show current application status",handler:new t,options:[]}]};export{s as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"chalk";import o from"fs-extra";import t from"path";import i from"os";import s from"adm-zip";import r from"ignore";import
|
|
1
|
+
import e from"chalk";import o from"fs-extra";import t from"path";import i from"os";import s from"adm-zip";import r from"ignore";import n from"inquirer";import{debug as a,debugError as c}from"../../lib/debug.js";import{getBusinessApiBase as p}from"../../lib/api.js";import{ensureLoggedIn as l}from"../../services/auth.js";import{createSpinner as d}from"../../lib/spinner.js";import{isUserInterrupt as m,INTERRUPTED_MESSAGE as f}from"../../lib/errors.js";import{DeployCommand as h}from"./deploy.js";import{CheckCommand as u}from"../check.js";const g=[".dashnex",".git",".next",".wrangler"],w=async(e,i)=>{const s=[],r=await o.readdir(e,{withFileTypes:!0});for(const o of r){const r=t.relative(process.cwd(),t.join(e,o.name)).split(t.sep).join("/");if(g.some(e=>r===e||r.startsWith(`${e}/`)))continue;if(i.ignores(r))continue;const n=t.join(e,o.name);if(o.isDirectory()){const e=await w(n,i);s.push(...e)}else o.isFile()&&s.push(n)}return s};class y{async execute(y={}){a("Push flow started");if(!1===y.check)a("Skipping pre-push checks (--no-check)");else{a("Running pre-push checks");const o=new u;await o.run()||(console.error(e.red("Push aborted: checks failed.")),process.exit(1))}const j=await l();if(!j)return;const x=process.cwd(),k=t.join(x,".gitignore"),v=r();if(v.add(g),await o.pathExists(k)){const e=await o.readFile(k,"utf8");v.add(e)}a("Building file list");const $=await w(x,v);a(`Including ${$.length} files`);const b=new s;for(const e of $){const o=t.relative(x,e).split(t.sep).join("/"),i="."===t.dirname(o)?"":t.dirname(o),s=t.basename(o);b.addLocalFile(e,i,s)}const F=t.join(i.tmpdir(),`dashnex-push-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`),P=d();try{P.start("Packaging application..."),b.writeZip(F),a(`Zip written to ${F}`);const t=`${p()}/business/v1/cli/push`;a(`POST ${t}`);const i=await o.readFile(F),s=new Blob([i],{type:"application/zip"}),r=new FormData;r.append("file",s,"archive.zip");const c=new Headers;c.set("Authorization",`Bearer ${j.token}`),P.text("Uploading...");const l=await fetch(t,{method:"POST",headers:c,body:r});if(P.stop(),a(`Response: ${l.status}`),!l.ok){const o=l.headers.get("content-type")??"";let t="Failed to push application.";if(401===l.status||403===l.status)t="Please run 'dashnex login' to authenticate.";else if(o.includes("application/json")){const e=(e=>"string"==typeof e.error?e.error:"string"==typeof e.message?e.message:void 0)(await l.json().catch(()=>({})));e&&(t=e)}console.error(e.red(t)),process.exit(1)}let d;if(console.log(e.green("Application pushed successfully.")),void 0!==y.deploy)d=y.deploy,a(`Deploy decided via flag: ${d}`);else{d=(await n.prompt([{type:"confirm",name:"deploy",message:"Deploy the application?",default:!0}])).deploy,a(`User chose to deploy: ${d}`)}if(d){a("Running deploy flow");const e=new h;await e.execute()}}catch(z){if(P.stop(),c(z),z instanceof Error&&z.message.startsWith("EXIT:"))throw z;if(m(z))return void console.log(e.yellow(f));console.error(e.red("Could not reach DashNex API. Check your connection and try again.")),process.exit(1)}finally{await o.remove(F).catch(()=>{}),a("Temp zip removed")}}}export{y as PushCommand};
|
package/dist/commands/check.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as e}from"child_process";import o from"chalk";import{debug as n,debugError as r}from"../lib/debug.js";const s=(o,s)=>new Promise((
|
|
1
|
+
import{spawn as e}from"child_process";import o from"chalk";import{debug as n,debugError as r}from"../lib/debug.js";const s=(o,s)=>{const c=`${o} ${s.join(" ")}`;return new Promise((s,t)=>{n(`Running: ${c}`);const a=e(c,{stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("error",e=>{r(e),t(e)}),a.on("close",e=>{n(`${o} exited with code ${e}`),s(null===e?1:e)})})},c=o=>new Promise(n=>{const r=e(`${o} --version`,{stdio:"ignore",shell:!0});r.on("error",()=>n(!1)),r.on("close",e=>n(0===e))}),t=[{name:"TypeScript",command:"npx",args:["tsc","--noEmit"],notFoundMessage:"TypeScript is not available. Please install it with: npm install -D typescript"}];class a{async execute(){n("Check flow started"),n(`Running ${t.length} check(s)`);for(const a of t){n(`Running check: ${a.name}`);await c(a.command)||(console.error(o.red(a.notFoundMessage)),process.exit(1));try{0!==await s(a.command,a.args)&&(console.error(o.red("Check failed.")),process.exit(1))}catch(e){r(e),console.error(o.red(a.notFoundMessage)),process.exit(1)}}console.log(o.green("All checks passed."))}async run(){n("Running checks (called from deploy)");for(const a of t){n(`Running check: ${a.name}`);if(!(await c(a.command)))return console.error(o.red(a.notFoundMessage)),!1;try{if(0!==await s(a.command,a.args))return!1}catch(e){return r(e),console.error(o.red(a.notFoundMessage)),!1}}return console.log(o.green("All checks passed.")),!0}}export{a as CheckCommand};
|
package/dist/package.json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e="@dashnex/cli",a="0.5.
|
|
1
|
+
const e="@dashnex/cli",a="0.5.42",n="Command-line interface for DashNex framework",o={name:e,version:a,description:n};export{o as default,n as description,e as name,a as version};
|
package/dist/services/auth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"chalk";import
|
|
1
|
+
import e from"chalk";import n from"fs-extra";import r from"path";import{debug as s,debugError as t,debugJson as o}from"../lib/debug.js";import{getApiBase as a,apiFetch as i}from"../lib/api.js";const u=()=>{console.error(e.red("Please run 'dashnex login' to authenticate.")),console.error(e.dim("If you don't have a business account yet, create one at "+("qa"===(process.env.APPLICATION_ENV??"")?"https://business.qa.dashnex.com/":"https://business.dashnex.com/")))},h=async(e,r)=>{s(`POST ${a()}/auth/v1/token/refresh`);const{response:t,body:u}=await i(`${a()}/auth/v1/token/refresh`,{method:"POST",body:JSON.stringify({refreshToken:e})});if(s(`Response: ${t.status}`),o("Refresh response",u),!t.ok)return s("Token refresh failed"),null;const h=u;if(!h.token||!h.refreshToken)return s("Refresh response missing tokens"),null;const f=await n.readJson(r);return f.token=h.token,f.refreshToken=h.refreshToken,await n.writeJson(r,f,{spaces:2}),s("Updated .dashnex with new tokens"),l(h.token,h.refreshToken,r,{...f,token:h.token,refreshToken:h.refreshToken})},l=async(e,n,r,u)=>{if(((e,n=30)=>{try{const r=e.split(".");if(3!==r.length)return!1;const t=JSON.parse(Buffer.from(r[1],"base64url").toString());if("number"!=typeof t.exp)return!1;const o=Math.floor(Date.now()/1e3),a=t.exp-n<=o;return a&&s(`Token expired or expiring soon (exp: ${t.exp}, now: ${o})`),a}catch{return!1}})(e)){if(!n)return s("Token expired, no refreshToken available"),null;s("Token expired, refreshing proactively");try{return await h(n,r)}catch(l){return t(l),null}}s(`GET ${a()}/users/v1/`);try{const{response:t,body:l}=await i(`${a()}/users/v1/`,{headers:{Authorization:`Bearer ${e}`}});if(s(`Response: ${t.status}`),o("Users response",l),t.ok){const n=l;if("string"==typeof n.name&&u.businessId)return s(`Token valid, Already logged in as ${n.name}`),{token:e,businessId:u.businessId,userName:n.name}}return n?(s("Users API rejected token, refreshing"),await h(n,r)):(s("Token invalid, no refreshToken available"),null)}catch(l){return t(l),null}},f=async(e={})=>{const{exitOnFailure:t=!0,dashnexPath:o}=e,a=o??await(async e=>{let s=r.resolve(e);for(;;){const e=r.join(s,".dashnex");if(await n.pathExists(e))return e;const t=r.dirname(s);if(t===s)return null;s=t}})(process.cwd());if(!a||!(await n.pathExists(a)))return s(".dashnex not found"),t&&(u(),process.exit(1)),null;let i;s(`Found .dashnex at ${a}`);try{i=await n.readJson(a)}catch{return s(".dashnex parse failed"),t&&(u(),process.exit(1)),null}const{token:h,refreshToken:f,businessId:c}=i;if(!h)return s(".dashnex missing token"),t&&(u(),process.exit(1)),null;const d=await l(h,f,a,i);return d||(t&&(u(),process.exit(1)),null)};export{f as ensureLoggedIn};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { CliCommand } from '@dashnex/types';
|
|
2
|
-
export interface DeployCommandOptions {
|
|
3
|
-
check?: boolean;
|
|
4
|
-
}
|
|
5
2
|
export declare class DeployCommand implements CliCommand {
|
|
6
|
-
execute(
|
|
3
|
+
execute(): Promise<void>;
|
|
7
4
|
private showDeployedUrl;
|
|
8
5
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "dashnex",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.42",
|
|
5
5
|
"description": "Command-line interface for DashNex framework",
|
|
6
6
|
"homepage": "https://dashnex.io",
|
|
7
7
|
"type": "module",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@types/fs-extra": "^11.0.4",
|
|
40
40
|
"@types/inquirer": "^9.0.9",
|
|
41
41
|
"@types/node": "^25.3.0",
|
|
42
|
-
"eslint": "^9.39.
|
|
42
|
+
"eslint": "^9.39.3",
|
|
43
43
|
"rollup-plugin-preserve-directives": "^0.4.0",
|
|
44
44
|
"terser": "^5.46.0",
|
|
45
45
|
"typescript": "^5.9.3",
|