@dashnex/cli 0.5.2 → 0.5.4
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.d.ts +2 -0
- package/dist/cli.js +1 -161
- package/dist/client.d.ts +3 -0
- package/dist/client.js +1 -12
- package/dist/commands/create.d.ts +7 -0
- package/dist/commands/create.js +1 -134
- package/dist/commands/delete.d.ts +4 -0
- package/dist/commands/delete.js +1 -51
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +1 -68
- package/dist/commands/login.d.ts +8 -0
- package/dist/commands/login.js +1 -262
- package/dist/commands/logout.d.ts +4 -0
- package/dist/commands/logout.js +1 -16
- package/dist/commands/pull.d.ts +4 -0
- package/dist/commands/pull.js +1 -102
- package/dist/commands/push.d.ts +4 -0
- package/dist/commands/push.js +1 -108
- package/dist/commands/version.d.ts +5 -0
- package/dist/commands/version.js +1 -10
- package/dist/commands/whoami.d.ts +4 -0
- package/dist/commands/whoami.js +1 -52
- package/dist/dashnex.json.js +1 -5
- package/dist/lib/api.d.ts +7 -0
- package/dist/lib/api.js +1 -23
- package/dist/lib/debug.d.ts +3 -0
- package/dist/lib/debug.js +1 -45
- package/dist/package.json.js +1 -15
- package/dist/server.d.ts +3 -0
- package/dist/server.js +1 -12
- package/dist/services/auth.d.ts +10 -0
- package/dist/services/auth.js +1 -116
- package/package.json +3 -3
- package/dist/cli.js.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/delete.js.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/pull.js.map +0 -1
- package/dist/commands/push.js.map +0 -1
- package/dist/commands/version.js.map +0 -1
- package/dist/commands/whoami.js.map +0 -1
- package/dist/dashnex.json.js.map +0 -1
- package/dist/lib/api.js.map +0 -1
- package/dist/lib/debug.js.map +0 -1
- package/dist/package.json.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services/auth.js.map +0 -1
package/dist/lib/debug.js
CHANGED
|
@@ -1,45 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
const isSensitiveKey = (key) => {
|
|
3
|
-
const k = key.toLowerCase();
|
|
4
|
-
return k.includes("token") || k.includes("password") || k === "auth_code";
|
|
5
|
-
};
|
|
6
|
-
const sanitizeForLog = (obj) => {
|
|
7
|
-
if (obj === null || typeof obj !== "object") return obj;
|
|
8
|
-
if (Array.isArray(obj)) {
|
|
9
|
-
return obj.map(sanitizeForLog);
|
|
10
|
-
}
|
|
11
|
-
const result = {};
|
|
12
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
13
|
-
if (isSensitiveKey(key)) {
|
|
14
|
-
result[key] = "[REDACTED]";
|
|
15
|
-
} else {
|
|
16
|
-
result[key] = sanitizeForLog(value);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
|
-
const debug = (msg) => {
|
|
22
|
-
if (process.env.DEBUG) {
|
|
23
|
-
console.log(chalk.dim(msg));
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const debugJson = (label, body) => {
|
|
27
|
-
if (process.env.DEBUG) {
|
|
28
|
-
const sanitized = sanitizeForLog(body);
|
|
29
|
-
console.log(chalk.dim(`${label}: ${JSON.stringify(sanitized, null, 2)}`));
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const debugError = (error) => {
|
|
33
|
-
if (process.env.DEBUG && error instanceof Error) {
|
|
34
|
-
console.log(chalk.dim(`Error: ${error.message}`));
|
|
35
|
-
if (error.stack) {
|
|
36
|
-
console.log(chalk.dim(`Stack: ${error.stack}`));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
export {
|
|
41
|
-
debug,
|
|
42
|
-
debugError,
|
|
43
|
-
debugJson
|
|
44
|
-
};
|
|
45
|
-
//# sourceMappingURL=debug.js.map
|
|
1
|
+
import o from"chalk";const e=o=>{const e=o.toLowerCase();return e.includes("token")||e.includes("password")||"auth_code"===e},r=o=>{if(null===o||"object"!=typeof o)return o;if(Array.isArray(o))return o.map(r);const s={};for(const[n,t]of Object.entries(o))e(n)?s[n]="[REDACTED]":s[n]=r(t);return s},s=e=>{process.env.DEBUG&&console.log(o.dim(e))},n=(e,s)=>{if(process.env.DEBUG){const n=r(s);console.log(o.dim(`${e}: ${JSON.stringify(n,null,2)}`))}},t=e=>{process.env.DEBUG&&e instanceof Error&&(console.log(o.dim(`Error: ${e.message}`)),e.stack&&console.log(o.dim(`Stack: ${e.stack}`)))};export{s as debug,t as debugError,n as debugJson};
|
package/dist/package.json.js
CHANGED
|
@@ -1,15 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
const version = "0.5.2";
|
|
3
|
-
const description = "Command-line interface for DashNex framework";
|
|
4
|
-
const packageJson = {
|
|
5
|
-
name,
|
|
6
|
-
version,
|
|
7
|
-
description
|
|
8
|
-
};
|
|
9
|
-
export {
|
|
10
|
-
packageJson as default,
|
|
11
|
-
description,
|
|
12
|
-
name,
|
|
13
|
-
version
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=package.json.js.map
|
|
1
|
+
const e="@dashnex/cli",a="0.5.4",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/server.d.ts
ADDED
package/dist/server.js
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import dashnexConfig from "./dashnex.json.js";
|
|
3
|
-
const server = {
|
|
4
|
-
name: packageJson.name,
|
|
5
|
-
version: packageJson.version,
|
|
6
|
-
description: packageJson.description,
|
|
7
|
-
...dashnexConfig
|
|
8
|
-
};
|
|
9
|
-
export {
|
|
10
|
-
server as default
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=server.js.map
|
|
1
|
+
import o from"./package.json.js";import s from"./dashnex.json.js";const e={name:o.name,version:o.version,description:o.description,...s};export{e as default};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface EnsureLoggedInResult {
|
|
2
|
+
token: string;
|
|
3
|
+
businessId: string;
|
|
4
|
+
userName?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface EnsureLoggedInOptions {
|
|
7
|
+
exitOnFailure?: boolean;
|
|
8
|
+
dashnexPath?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const ensureLoggedIn: (options?: EnsureLoggedInOptions) => Promise<EnsureLoggedInResult | null>;
|
package/dist/services/auth.js
CHANGED
|
@@ -1,116 +1 @@
|
|
|
1
|
-
import chalk from "
|
|
2
|
-
import fs from "fs-extra";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { debug, debugJson, debugError } from "../lib/debug.js";
|
|
5
|
-
import { getApiBase, apiFetch } from "../lib/api.js";
|
|
6
|
-
const findDashnexPath = async (startDir) => {
|
|
7
|
-
let dir = path.resolve(startDir);
|
|
8
|
-
while (true) {
|
|
9
|
-
const candidate = path.join(dir, ".dashnex");
|
|
10
|
-
if (await fs.pathExists(candidate)) return candidate;
|
|
11
|
-
const parent = path.dirname(dir);
|
|
12
|
-
if (parent === dir) return null;
|
|
13
|
-
dir = parent;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
const validateTokenAndRefreshIfNeeded = async (token, refreshToken, dashnexPath, config) => {
|
|
17
|
-
debug(`GET ${getApiBase()}/users/v1/`);
|
|
18
|
-
try {
|
|
19
|
-
const { response, body } = await apiFetch(`${getApiBase()}/users/v1/`, {
|
|
20
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
21
|
-
});
|
|
22
|
-
debug(`Response: ${response.status}`);
|
|
23
|
-
debugJson("Users response", body);
|
|
24
|
-
if (response.ok) {
|
|
25
|
-
const data = body;
|
|
26
|
-
if (typeof data.name === "string" && config.businessId) {
|
|
27
|
-
debug(`Token valid, Already logged in as ${data.name}`);
|
|
28
|
-
return {
|
|
29
|
-
token,
|
|
30
|
-
businessId: config.businessId,
|
|
31
|
-
userName: data.name
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (!refreshToken) {
|
|
36
|
-
debug("Token invalid, no refreshToken available");
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
debug(`POST ${getApiBase()}/auth/v1/token/refresh`);
|
|
40
|
-
const { response: refreshResponse, body: refreshBody } = await apiFetch(
|
|
41
|
-
`${getApiBase()}/auth/v1/token/refresh`,
|
|
42
|
-
{
|
|
43
|
-
method: "POST",
|
|
44
|
-
body: JSON.stringify({ refreshToken })
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
debug(`Response: ${refreshResponse.status}`);
|
|
48
|
-
debugJson("Refresh response", refreshBody);
|
|
49
|
-
if (!refreshResponse.ok) {
|
|
50
|
-
debug("Token refresh failed");
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
const refreshData = refreshBody;
|
|
54
|
-
if (!refreshData.token || !refreshData.refreshToken) {
|
|
55
|
-
debug("Refresh response missing tokens");
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const updatedConfig = await fs.readJson(dashnexPath);
|
|
59
|
-
updatedConfig.token = refreshData.token;
|
|
60
|
-
updatedConfig.refreshToken = refreshData.refreshToken;
|
|
61
|
-
await fs.writeJson(dashnexPath, updatedConfig, { spaces: 2 });
|
|
62
|
-
debug("Updated .dashnex with new tokens, retrying session check");
|
|
63
|
-
return validateTokenAndRefreshIfNeeded(
|
|
64
|
-
refreshData.token,
|
|
65
|
-
refreshData.refreshToken,
|
|
66
|
-
dashnexPath,
|
|
67
|
-
{ ...updatedConfig, token: refreshData.token, refreshToken: refreshData.refreshToken }
|
|
68
|
-
);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
debugError(error);
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
const ensureLoggedIn = async (options = {}) => {
|
|
75
|
-
const { exitOnFailure = true, dashnexPath: customPath } = options;
|
|
76
|
-
const dashnexPath = customPath ?? await findDashnexPath(process.cwd());
|
|
77
|
-
if (!dashnexPath || !await fs.pathExists(dashnexPath)) {
|
|
78
|
-
debug(".dashnex not found");
|
|
79
|
-
if (exitOnFailure) {
|
|
80
|
-
console.error(chalk.red("Please run 'npx dashnex login' to authenticate."));
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
let config;
|
|
86
|
-
try {
|
|
87
|
-
config = await fs.readJson(dashnexPath);
|
|
88
|
-
} catch {
|
|
89
|
-
debug(".dashnex parse failed");
|
|
90
|
-
if (exitOnFailure) {
|
|
91
|
-
console.error(chalk.red("Please run 'npx dashnex login' to authenticate."));
|
|
92
|
-
process.exit(1);
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
const { token, refreshToken, businessId } = config;
|
|
97
|
-
if (!token) {
|
|
98
|
-
debug(".dashnex missing token");
|
|
99
|
-
if (exitOnFailure) {
|
|
100
|
-
console.error(chalk.red("Please run 'npx dashnex login' to authenticate."));
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
const result = await validateTokenAndRefreshIfNeeded(token, refreshToken, dashnexPath, config);
|
|
106
|
-
if (result) return result;
|
|
107
|
-
if (exitOnFailure) {
|
|
108
|
-
console.error(chalk.red("Please run 'npx dashnex login' to authenticate."));
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
};
|
|
113
|
-
export {
|
|
114
|
-
ensureLoggedIn
|
|
115
|
-
};
|
|
116
|
-
//# sourceMappingURL=auth.js.map
|
|
1
|
+
import e from"chalk";import n from"fs-extra";import s from"path";import{debug as r,debugJson as t,debugError as o}from"../lib/debug.js";import{getApiBase as a,apiFetch as i}from"../lib/api.js";const l=async(e,s,u,h)=>{r(`GET ${a()}/users/v1/`);try{const{response:o,body:d}=await i(`${a()}/users/v1/`,{headers:{Authorization:`Bearer ${e}`}});if(r(`Response: ${o.status}`),t("Users response",d),o.ok){const n=d;if("string"==typeof n.name&&h.businessId)return r(`Token valid, Already logged in as ${n.name}`),{token:e,businessId:h.businessId,userName:n.name}}if(!s)return r("Token invalid, no refreshToken available"),null;r(`POST ${a()}/auth/v1/token/refresh`);const{response:c,body:f}=await i(`${a()}/auth/v1/token/refresh`,{method:"POST",body:JSON.stringify({refreshToken:s})});if(r(`Response: ${c.status}`),t("Refresh response",f),!c.ok)return r("Token refresh failed"),null;const p=f;if(!p.token||!p.refreshToken)return r("Refresh response missing tokens"),null;const k=await n.readJson(u);return k.token=p.token,k.refreshToken=p.refreshToken,await n.writeJson(u,k,{spaces:2}),r("Updated .dashnex with new tokens, retrying session check"),l(p.token,p.refreshToken,u,{...k,token:p.token,refreshToken:p.refreshToken})}catch(d){return o(d),null}},u=async(t={})=>{const{exitOnFailure:o=!0,dashnexPath:a}=t,i=a??await(async e=>{let r=s.resolve(e);for(;;){const e=s.join(r,".dashnex");if(await n.pathExists(e))return e;const t=s.dirname(r);if(t===r)return null;r=t}})(process.cwd());if(!i||!(await n.pathExists(i)))return r(".dashnex not found"),o&&(console.error(e.red("Please run 'npx dashnex login' to authenticate.")),process.exit(1)),null;let u;try{u=await n.readJson(i)}catch{return r(".dashnex parse failed"),o&&(console.error(e.red("Please run 'npx dashnex login' to authenticate.")),process.exit(1)),null}const{token:h,refreshToken:d,businessId:c}=u;if(!h)return r(".dashnex missing token"),o&&(console.error(e.red("Please run 'npx dashnex login' to authenticate.")),process.exit(1)),null;const f=await l(h,d,i,u);return f||(o&&(console.error(e.red("Please run 'npx dashnex login' to authenticate.")),process.exit(1)),null)};export{u as ensureLoggedIn};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@dashnex/cli",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.4",
|
|
5
5
|
"description": "Command-line interface for DashNex framework",
|
|
6
6
|
"homepage": "https://dashnex.io",
|
|
7
7
|
"type": "module",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"adm-zip": "^0.5.16",
|
|
29
29
|
"chalk": "^5.6.2",
|
|
30
30
|
"commander": "^14.0.3",
|
|
31
|
-
"dotenv": "^17.
|
|
31
|
+
"dotenv": "^17.3.0",
|
|
32
32
|
"fs-extra": "^11.3.3",
|
|
33
33
|
"ignore": "^7.0.5",
|
|
34
34
|
"inquirer": "^13.2.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@dashnex/types": "^0.5.
|
|
37
|
+
"@dashnex/types": "^0.5.11",
|
|
38
38
|
"@types/adm-zip": "^0.5.7",
|
|
39
39
|
"@types/fs-extra": "^11.0.4",
|
|
40
40
|
"@types/inquirer": "^9.0.9",
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { CliCommandConfig, CliOption } from \"@dashnex/types\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport dotenv from \"dotenv\";\nimport packageJson from '../package.json' with { type: \"json\" };\n\nconst program = new Command();\n\nconst { name, version, description } = packageJson;\n\nprogram\n .name(name)\n .description(description)\n .version(version);\n\nfunction getModuleRoot(module: string, appDir: string): string {\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (fs.existsSync(appPackageJsonPath)) {\n try {\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n if (appPackageJson.name === module) {\n return appDir;\n }\n } catch {\n // ignore\n }\n }\n return path.join(appDir, \"node_modules\", module);\n}\n\nasync function discoverModuleCommands(module: string, appDir: string): Promise<CliCommandConfig[]> {\n\n const discoveredCommands: CliCommandConfig[] = [];\n\n try {\n const moduleRoot = getModuleRoot(module, appDir);\n const modulePath = path.join(moduleRoot, \"dist\", \"commands\", \"index.js\");\n\n if (fs.existsSync(modulePath)) {\n // Import from the full path\n const module = await import(modulePath);\n \n // Handle both named and default exports\n let moduleCommands: CliCommandConfig[] = [];\n \n if (module.default) {\n // Default export\n moduleCommands = Array.isArray(module.default) ? module.default : [];\n } else if (module.commands) {\n // Named export\n moduleCommands = Array.isArray(module.commands) ? module.commands : [];\n }\n \n if (moduleCommands.length > 0) {\n discoveredCommands.push(...moduleCommands);\n }\n }\n } catch (error) {\n // Module doesn't have commands or failed to load - this is expected for some modules\n if (process.env.DEBUG) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(chalk.yellow(`Module ${module} has no commands or failed to load: ${errorMessage}`));\n }\n }\n\n return discoveredCommands;\n}\n\n// Do it here, instead of importing from the core module to avoid circular dependencies\nasync function discoverDashnexModules(appDir: string): Promise<string[]> {\n try {\n const dashnexModules: string[] = [];\n const seen = new Set<string>();\n\n const addIfNew = (name: string) => {\n if (!seen.has(name)) {\n seen.add(name);\n dashnexModules.push(name);\n }\n };\n\n // Check if current directory is a dashnex module (running from module repo directly)\n const appDashnexPath = path.join(appDir, \"dashnex.json\");\n if (fs.existsSync(appDashnexPath)) {\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (fs.existsSync(appPackageJsonPath)) {\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n if (appPackageJson.name) {\n addIfNew(appPackageJson.name);\n }\n }\n }\n\n // Read the app's package.json to see which dashnex modules are installed in node_modules\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (!fs.existsSync(appPackageJsonPath)) {\n return dashnexModules;\n }\n\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n const allDependencies = {\n ...appPackageJson.dependencies,\n ...appPackageJson.devDependencies,\n ...appPackageJson.optionalDependencies\n };\n\n for (const [module] of Object.entries(allDependencies)) {\n const moduleRoot = path.join(appDir, \"node_modules\", module);\n if (fs.existsSync(path.join(moduleRoot, \"dashnex.json\"))) {\n addIfNew(module);\n }\n }\n\n return dashnexModules;\n } catch (error) {\n if (process.env.DEBUG) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(\"⚠ Error reading app package.json:\", errorMessage);\n }\n return [];\n }\n}\n\nfunction registerCommand(\n parentCommand: Command, \n dashnexCommand: CliCommandConfig, \n parentOptions: any = {}\n): void {\n const cmd = parentCommand\n .command(dashnexCommand.name)\n .description(dashnexCommand.description);\n\n // Add options if defined\n if (dashnexCommand.options) {\n dashnexCommand.options.forEach((option: CliOption) => {\n if (option.defaultValue !== undefined) {\n // Handle different types of default values\n if (typeof option.defaultValue === 'number') {\n cmd.option(option.flags, option.description, String(option.defaultValue));\n } else {\n cmd.option(option.flags, option.description, option.defaultValue as string | boolean);\n }\n } else {\n cmd.option(option.flags, option.description);\n }\n });\n }\n\n // Add subcommands if defined \n if (dashnexCommand.subcommands) {\n dashnexCommand.subcommands.forEach(subcommand => {\n registerCommand(cmd, subcommand, { ...parentOptions, ...dashnexCommand.options });\n });\n }\n\n // Register the command handler\n cmd.action(async (options, actionCommand) => {\n try {\n // Merge parent options with current command options\n const mergedOptions = { ...parentOptions, ...options };\n await dashnexCommand.handler.execute(mergedOptions);\n } catch (error) {\n console.error(chalk.red(`❌ Command failed in ${dashnexCommand.name}:`), error);\n process.exit(1);\n }\n });\n}\n\n// Main execution\nasync function main() {\n // Load environment variables from .env file\n dotenv.config({ quiet: true });\n\n process.env.DASHNEX_CLI = \"1\";\n \n // Find the app directory (where the CLI was called from) to ensure proper module resolution\n let appDir = process.cwd();\n \n if (process.env.DEBUG) {\n console.log(`CLI started from directory: ${appDir}`);\n }\n\n const moduleNames = await discoverDashnexModules(appDir);\n \n if (process.env.DEBUG) {\n console.log(`Discovered modules: ${moduleNames.join(', ')}`);\n }\n\n // Load the CLI commands from the dashnex modules\n for (const moduleName of moduleNames) {\n const moduleCommands = await discoverModuleCommands(moduleName, appDir);\n\n for (const command of moduleCommands) {\n registerCommand(program, command);\n }\n }\n\n // Load the CLI commands from the application\n try {\n const { default: applicationCommands } = await import(path.join(appDir, \"dist\", \"commands\", \"index.js\"));\n\n if (applicationCommands && Array.isArray(applicationCommands)) {\n for (const command of applicationCommands) {\n registerCommand(program, command);\n }\n }\n } catch (error) {\n if (process.env.DEBUG) {\n console.error(chalk.yellow(\"⚠ Failed to discover application commands\"));\n }\n }\n\n // Parse command line arguments\n program.parse(process.argv);\n\n // Show help if no command provided\n if (!process.argv.slice(2).length) {\n program.outputHelp();\n }\n}\n\n// Run the CLI\nmain().catch((error) => {\n console.error(chalk.red(\"❌ CLI failed:\"), error);\n process.exit(1);\n});\n"],"names":["module","name","appPackageJsonPath","appPackageJson"],"mappings":"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"}
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../src/client.ts"],"sourcesContent":["import { ModuleConfig } from '@dashnex/types';\n\nimport packageJson from '../package.json' with { type: \"json\" };\nimport dashnexConfig from '../dashnex.json' with { type: \"json\" };\n\nexport default {\n name: packageJson.name,\n version: packageJson.version,\n description: packageJson.description,\n ...dashnexConfig,\n} as ModuleConfig;"],"names":[],"mappings":";;AAKA,MAAA,SAAe;AAAA,EACX,MAAM,YAAY;AAAA,EAClB,SAAS,YAAY;AAAA,EACrB,aAAa,YAAY;AAAA,EACzB,GAAG;AACP;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sources":["../../src/commands/create.ts"],"sourcesContent":["import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (Array.isArray(body.message) && body.message.length > 0) {\n return body.message.join(\" \");\n }\n if (typeof body.message === \"string\") return body.message;\n if (typeof body.error === \"string\") return body.error;\n return undefined;\n};\n\nconst SUCCESS_MESSAGE =\n \"Application is created successfully. Use 'npx dashnex pull' to pull it to your computer or 'npx dashnex deploy' to deploy it to the cloud.\";\n\nexport interface CreateCommandOptions {\n template?: string;\n}\n\nexport class CreateCommand implements CliCommand {\n async execute(options: CreateCommandOptions = {}): Promise<void> {\n debug(\"Create flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n debug(\"Auth valid, checking if business already has application\");\n\n const applicationsUrl = `${getBusinessApiBase()}/business/v1/applications`;\n debug(`GET ${applicationsUrl}`);\n\n try {\n const appsResponse = await fetch(applicationsUrl, {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n debug(`Applications response: ${appsResponse.status}`);\n\n if (appsResponse.status !== 404) {\n console.error(\n chalk.red(\n \"Business already has an application. Run 'npx dashnex pull' to pull the existing one.\"\n )\n );\n process.exit(1);\n }\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n\n debug(\"No existing application, proceeding to subdomain prompt\");\n\n let subdomain: string;\n const checkSubdomainUrl = (sub: string) =>\n `${getBusinessApiBase()}/business/v1/applications/check-subdomain?subdomain=${encodeURIComponent(sub)}`;\n\n while (true) {\n const { sub } = await inquirer.prompt<{ sub: string }>([\n {\n type: \"input\",\n name: \"sub\",\n message: \"Pick your subdomain:\",\n validate: (input: string) => (input.trim() ? true : \"Subdomain is required\"),\n },\n ]);\n\n subdomain = sub.trim();\n debug(`Checking subdomain: ${subdomain}`);\n\n try {\n const checkResponse = await fetch(checkSubdomainUrl(subdomain), {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n debug(`Check subdomain response: ${checkResponse.status}`);\n\n if (!checkResponse.ok) {\n const contentType = checkResponse.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to check subdomain availability.\";\n if (checkResponse.status === 401 || checkResponse.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n console.error(chalk.red(message));\n process.exit(1);\n }\n if (contentType.includes(\"application/json\")) {\n const body = (await checkResponse.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n continue;\n }\n\n const checkBody = (await checkResponse.json()) as { available?: boolean; subdomain?: string };\n if (checkBody.available) {\n debug(`Subdomain ${subdomain} is available`);\n break;\n }\n\n console.error(chalk.red(\"Subdomain is not available. Please choose a different one.\"));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n\n const createUrl = `${getBusinessApiBase()}/business/v1/cli/create`;\n debug(`POST ${createUrl}`);\n\n const createBody: Record<string, string> = { subdomain };\n if (options.template) {\n createBody.template = options.template;\n debug(`Template: ${options.template}`);\n }\n\n try {\n const createResponse = await fetch(createUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${session.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(createBody),\n });\n\n debug(`Create response: ${createResponse.status}`);\n\n if (!createResponse.ok) {\n const contentType = createResponse.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to create application.\";\n if (createResponse.status === 401 || createResponse.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await createResponse.json().catch(() => ({}))) as Record<string, unknown>;\n debug(`Create response body: ${JSON.stringify(body)}`);\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n debug(\"Application created successfully\");\n console.log(chalk.green(SUCCESS_MESSAGE));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delete.js","sources":["../../src/commands/delete.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\nexport class DeleteCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Delete flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n const url = `${getBusinessApiBase()}/business/v1/applications`;\n debug(`DELETE ${url}`);\n\n try {\n const response = await fetch(url, {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${session.token}` },\n });\n\n debug(`Response: ${response.status}`);\n\n if (!response.ok) {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to delete application.\";\n if (response.status === 401 || response.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const successMessage =\n typeof body.message === \"string\" ? body.message : \"Application deleted successfully.\";\n\n debug(\"Application deleted successfully\");\n console.log(chalk.green(successMessage));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n}\n"],"names":["body"],"mappings":";;;;AAMA,MAAM,sBAAsB,CAAC,SAAsD;AACjF,MAAI,OAAO,KAAK,UAAU,iBAAiB,KAAK;AAChD,MAAI,OAAO,KAAK,YAAY,iBAAiB,KAAK;AAClD,SAAO;AACT;AAEO,MAAM,cAAoC;AAAA,EAC/C,MAAM,UAAyB;AAC7B,UAAM,qBAAqB;AAE3B,UAAM,UAAU,MAAM,eAAA;AACtB,QAAI,CAAC,QAAS;AAEd,UAAM,MAAM,GAAG,mBAAA,CAAoB;AACnC,UAAM,UAAU,GAAG,EAAE;AAErB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS,EAAE,eAAe,UAAU,QAAQ,KAAK,GAAA;AAAA,MAAG,CACrD;AAED,YAAM,aAAa,SAAS,MAAM,EAAE;AAEpC,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,YAAI,UAAU;AACd,YAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,oBAAU;AAAA,QACZ,WAAW,YAAY,SAAS,kBAAkB,GAAG;AACnD,gBAAMA,QAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,gBAAM,aAAa,oBAAoBA,KAAI;AAC3C,cAAI,WAAY,WAAU;AAAA,QAC5B;AACA,gBAAQ,MAAM,MAAM,IAAI,OAAO,CAAC;AAChC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,YAAM,iBACJ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAEpD,YAAM,kCAAkC;AACxC,cAAQ,IAAI,MAAM,MAAM,cAAc,CAAC;AAAA,IACzC,SAAS,OAAO;AACd,iBAAW,KAAK;AAChB,UAAI,iBAAiB,SAAS,MAAM,QAAQ,WAAW,OAAO,EAAG,OAAM;AACvE,cAAQ,MAAM,MAAM,IAAI,mEAAmE,CAAC;AAC5F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/commands/index.ts"],"sourcesContent":["import { CliCommandConfig } from \"@dashnex/types\";\nimport VersionCommand from \"./version.js\";\nimport { LoginCommand } from \"./login.js\";\nimport { LogoutCommand } from \"./logout.js\";\nimport { CreateCommand } from \"./create.js\";\nimport { PullCommand } from \"./pull.js\";\nimport { PushCommand } from \"./push.js\";\nimport { DeleteCommand } from \"./delete.js\";\nimport { WhoamiCommand } from \"./whoami.js\";\n\nconst commands: CliCommandConfig[] = [\n {\n name: \"version\",\n description: \"Display the version of the CLI\",\n handler: new VersionCommand(),\n options: []\n },\n {\n name: \"login\",\n description: \"Log in to your DashNex account\",\n handler: new LoginCommand(),\n options: []\n },\n {\n name: \"logout\",\n description: \"Log out and remove local credentials\",\n handler: new LogoutCommand(),\n options: []\n },\n {\n name: \"create\",\n description: \"Create a new DashNex application\",\n handler: new CreateCommand(),\n options: [\n {\n flags: \"-t, --template <template>\",\n description: \"Template (name@branch-or-tag)\",\n defaultValue: \"webapp-base@live\",\n },\n ],\n },\n {\n name: \"pull\",\n description: \"Pull existing application to current folder\",\n handler: new PullCommand(),\n options: [],\n },\n {\n name: \"push\",\n description: \"Push local application to DashNex\",\n handler: new PushCommand(),\n options: [],\n },\n {\n name: \"delete\",\n description: \"Delete application from DashNex\",\n handler: new DeleteCommand(),\n options: [],\n },\n {\n name: \"whoami\",\n description: \"Show current logged-in business and user\",\n handler: new WhoamiCommand(),\n options: [],\n },\n];\n\nexport default commands;\n"],"names":[],"mappings":";;;;;;;;AAUA,MAAM,WAA+B;AAAA,EACnC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,eAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,aAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,QACb,cAAc;AAAA,MAAA;AAAA,IAChB;AAAA,EACF;AAAA,EAEF;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,YAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,YAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAEd;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sources":["../../src/commands/login.ts"],"sourcesContent":["import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugJson, debugError } from \"../lib/debug.js\";\nimport { getApiBase, apiFetch } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\ninterface LoginResponse {\n token?: string;\n refreshToken?: string;\n two_fa_required?: boolean;\n type?: string;\n}\n\ninterface Business {\n id: string;\n name: string;\n}\n\nconst handleApiError = (\n response: Response,\n body: Record<string, unknown>,\n defaultMessage: string\n): never => {\n const apiMessage = extractErrorMessage(body);\n let message = defaultMessage;\n if (response.status === 429) {\n message = \"Too many requests. Please wait a moment and try again.\";\n } else if (response.status >= 500) {\n message = \"DashNex API is temporarily unavailable. Please try again later.\";\n } else if (apiMessage) {\n message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n};\n\nexport class LoginCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Login flow started\");\n\n const cwd = process.cwd();\n const dashnexPath = path.join(cwd, \".dashnex\");\n\n const session = await ensureLoggedIn({ exitOnFailure: false, dashnexPath });\n if (session) {\n console.log(chalk.green(`Already logged in as ${session.userName ?? \"user\"}`));\n return;\n }\n\n try {\n const { username, password } = await inquirer.prompt<{ username: string; password: string }>([\n {\n type: \"input\",\n name: \"username\",\n message: \"Email:\",\n validate: (input: string) => (input.trim() ? true : \"Email is required\"),\n },\n {\n type: \"password\",\n name: \"password\",\n message: \"Password:\",\n mask: \"*\",\n validate: (input: string) => (input ? true : \"Password is required\"),\n },\n ]);\n\n const trimmedUsername = username.trim();\n debug(\"Email provided\");\n\n debug(`POST ${getApiBase()}/auth/v1/login`);\n const { response: loginResponse, body: loginBody } = await apiFetch(\n `${getApiBase()}/auth/v1/login`,\n {\n method: \"POST\",\n body: JSON.stringify({ username: trimmedUsername, password }),\n }\n );\n debug(`Response: ${loginResponse.status}`);\n debugJson(\"Login response\", loginBody);\n\n if (!loginResponse.ok) {\n debugError(new Error(`Login failed: ${loginResponse.status} ${JSON.stringify(loginBody)}`));\n if (loginResponse.status === 401) {\n console.error(chalk.red(\"Invalid username or password.\"));\n process.exit(1);\n }\n handleApiError(\n loginResponse,\n loginBody,\n \"Login failed. Please try again.\"\n );\n }\n\n const loginData = loginBody as LoginResponse;\n\n if (loginData.two_fa_required && loginData.token) {\n debug(`2FA required, type: ${loginData.type || \"unknown\"}`);\n const token = await this.handle2FA(loginData.token, loginData.type);\n if (!token) process.exit(1);\n await this.completeLogin(token, dashnexPath);\n } else if (loginData.token && loginData.refreshToken) {\n await this.completeLogin(\n { token: loginData.token, refreshToken: loginData.refreshToken },\n dashnexPath\n );\n } else {\n console.error(chalk.red(\"Invalid response from server. Please try again.\"));\n process.exit(1);\n }\n } catch (error) {\n debugError(error);\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n\n private async handle2FA(\n interimToken: string,\n type?: string\n ): Promise<{ token: string; refreshToken: string } | null> {\n if (type === \"sms\") {\n debug(`POST ${getApiBase()}/auth/v1/two-fa/sms`);\n try {\n const { response } = await apiFetch(`${getApiBase()}/auth/v1/two-fa/sms`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${interimToken}` },\n body: JSON.stringify({}),\n });\n debug(`Response: ${response.status}`);\n } catch (err) {\n debugError(err);\n console.error(chalk.red(\"Could not send SMS code. Check your connection and try again.\"));\n return null;\n }\n }\n\n const typeLabel = type === \"sms\" ? \"Check your phone for the code\" : \"Check your authenticator app for the code\";\n const maxAttempts = 3;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const { auth_code } = await inquirer.prompt<{ auth_code: string }>([\n {\n type: \"input\",\n name: \"auth_code\",\n message: `Enter code (${typeLabel}):`,\n validate: (input: string) => (input.trim() ? true : \"Code is required\"),\n },\n ]);\n\n debug(`POST ${getApiBase()}/auth/v1/2fa-check`);\n try {\n const { response, body } = await apiFetch(`${getApiBase()}/auth/v1/2fa-check`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${interimToken}` },\n body: JSON.stringify({ auth_code: auth_code.trim() }),\n });\n debug(`Response: ${response.status}`);\n debugJson(\"2FA check response\", body);\n\n if (response.ok) {\n const data = body as { token?: string; refreshToken?: string };\n if (data.token && data.refreshToken) {\n return { token: data.token, refreshToken: data.refreshToken };\n }\n }\n\n if (response.status >= 400 && response.status < 500) {\n console.error(chalk.red(\"Invalid code. Please try again.\"));\n if (attempt < maxAttempts) {\n const { retry } = await inquirer.prompt<{ retry: boolean }>([\n {\n type: \"confirm\",\n name: \"retry\",\n message: \"Try again?\",\n default: true,\n },\n ]);\n if (!retry) return null;\n }\n continue;\n }\n\n handleApiError(response, body, \"2FA verification failed. Please try again.\");\n } catch (err) {\n debugError(err);\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n return null;\n }\n }\n\n return null;\n }\n\n private async completeLogin(\n tokens: { token: string; refreshToken: string },\n dashnexPath: string\n ): Promise<void> {\n debug(`GET ${getApiBase()}/users/v1/business/my`);\n const { response: bizResponse, body: bizBody } = await apiFetch(\n `${getApiBase()}/users/v1/business/my`,\n {\n headers: { Authorization: `Bearer ${tokens.token}` },\n }\n );\n debug(`Response: ${bizResponse.status}`);\n debugJson(\"Businesses response\", bizBody);\n\n if (!bizResponse.ok) {\n debugError(new Error(`Business fetch failed: ${bizResponse.status}`));\n handleApiError(\n bizResponse,\n bizBody,\n \"Failed to fetch businesses. Please try again.\"\n );\n }\n\n const businesses = this.parseBusinesses(bizBody);\n debug(`Businesses: ${businesses.length}`);\n\n if (businesses.length === 0) {\n console.error(chalk.red(\"No businesses found for your account.\"));\n process.exit(1);\n }\n\n let selected: Business;\n if (businesses.length === 1) {\n selected = businesses[0];\n debug(`Selected business: ${selected.id} ${selected.name}`);\n } else {\n const { businessId } = await inquirer.prompt<{ businessId: string }>([\n {\n type: \"select\",\n name: \"businessId\",\n message: \"Select business:\",\n choices: businesses.map((b) => ({ name: b.name, value: b.id })),\n },\n ]);\n selected = businesses.find((b) => b.id === businessId) || businesses[0];\n debug(`Selected business: ${selected.id} ${selected.name}`);\n }\n\n debug(`GET ${getApiBase()}/business/v1/login?_switch_business=${selected.id}`);\n const { response: switchResponse, body: switchBody } = await apiFetch(\n `${getApiBase()}/business/v1/login?_switch_business=${selected.id}`,\n {\n headers: { Authorization: `Bearer ${tokens.token}` },\n }\n );\n debug(`Response: ${switchResponse.status}`);\n debugJson(\"Business login response\", switchBody);\n\n if (!switchResponse.ok) {\n debugError(new Error(`Business login failed: ${switchResponse.status}`));\n handleApiError(\n switchResponse,\n switchBody,\n \"Failed to switch to business. Please try again.\"\n );\n }\n\n const switchData = switchBody as { token?: string; refreshToken?: string };\n if (!switchData.token || !switchData.refreshToken) {\n console.error(chalk.red(\"Invalid response from server. Please try again.\"));\n process.exit(1);\n }\n\n const config = {\n token: switchData.token,\n refreshToken: switchData.refreshToken,\n businessId: selected.id,\n };\n\n await fs.writeJson(dashnexPath, config, { spaces: 2 });\n debug(\"Saved credentials to .dashnex\");\n\n this.ensureGitignore();\n\n console.log(chalk.green(`Logged in as ${selected.name}`));\n }\n\n private parseBusinesses(body: Record<string, unknown>): Business[] {\n const arr = Array.isArray(body)\n ? body\n : (body.items as unknown[]) ??\n (body.data as unknown[]) ??\n (body.businesses as unknown[]) ??\n [];\n if (!Array.isArray(arr)) return [];\n\n return arr\n .map((item) => {\n if (item && typeof item === \"object\") {\n const o = item as Record<string, unknown>;\n const id = String(o.id ?? o.business_id ?? \"\").trim();\n const name = String(o.name ?? o.companyName ?? o.business_name ?? \"Unknown\").trim();\n if (id) return { id, name };\n }\n return null;\n })\n .filter((b): b is Business => b !== null);\n }\n\n private async ensureGitignore(): Promise<void> {\n const gitignorePath = path.join(process.cwd(), \".gitignore\");\n if (!(await fs.pathExists(gitignorePath))) return;\n\n let content = await fs.readFile(gitignorePath, \"utf8\");\n if (content.includes(\".dashnex\")) return;\n\n content = content.trimEnd();\n if (!content.endsWith(\"\\n\")) content += \"\\n\";\n content += \"\\n.dashnex\\n\";\n await fs.writeFile(gitignorePath, content);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"logout.js","sources":["../../src/commands/logout.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\n\nexport class LogoutCommand implements CliCommand {\n async execute(): Promise<void> {\n const dashnexPath = path.join(process.cwd(), \".dashnex\");\n if (await fs.pathExists(dashnexPath)) {\n await fs.remove(dashnexPath);\n }\n console.log(chalk.green(\"Logged out.\"));\n }\n}\n"],"names":[],"mappings":";;;AAKO,MAAM,cAAoC;AAAA,EAC/C,MAAM,UAAyB;AAC7B,UAAM,cAAc,KAAK,KAAK,QAAQ,IAAA,GAAO,UAAU;AACvD,QAAI,MAAM,GAAG,WAAW,WAAW,GAAG;AACpC,YAAM,GAAG,OAAO,WAAW;AAAA,IAC7B;AACA,YAAQ,IAAI,MAAM,MAAM,aAAa,CAAC;AAAA,EACxC;AACF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sources":["../../src/commands/pull.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport os from \"os\";\nimport inquirer from \"inquirer\";\nimport AdmZip from \"adm-zip\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\nconst SUCCESS_MESSAGE_NEW =\n 'Application is successfully pulled. Run \"npm install\" or \"pnpm install\" to install dependencies and then \"npx dashnex dev\" to run it';\n\nconst getSuccessMessageNew = (targetDir: string, cwd: string): string => {\n if (path.resolve(targetDir) === path.resolve(cwd)) {\n return SUCCESS_MESSAGE_NEW;\n }\n const folder = path.relative(cwd, targetDir);\n return `Application is successfully pulled. Run 'cd ${folder}' then \"pnpm install\" or \"npm install\" to install dependencies and then \"npx dashnex dev\" to run it`;\n};\n\nexport class PullCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Pull flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n const cwd = process.cwd();\n const dashnexJsonPath = path.join(cwd, \"dashnex.json\");\n const hasApp = await fs.pathExists(dashnexJsonPath);\n debug(`Application check (dashnex.json): ${hasApp ? \"present\" : \"absent\"}`);\n\n let targetDir: string;\n if (hasApp) {\n targetDir = cwd;\n } else {\n debug(\"No application yet, prompting for folder\");\n const { folder } = await inquirer.prompt<{ folder: string }>([\n {\n type: \"input\",\n name: \"folder\",\n message: \"Which folder to pull the application to?\",\n default: \".\",\n },\n ]);\n const resolved = path.resolve(cwd, folder.trim() || \".\");\n targetDir = resolved;\n await fs.ensureDir(targetDir);\n debug(`Target folder created/resolved: ${targetDir}`);\n }\n\n const url = `${getBusinessApiBase()}/business/v1/cli/pull`;\n debug(`GET ${url}`);\n\n const tempZipPath = path.join(\n os.tmpdir(),\n `dashnex-pull-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`\n );\n\n try {\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n\n debug(`Response: ${response.status}`);\n\n if (!response.ok) {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to pull application.\";\n if (response.status === 401 || response.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (response.status === 404) {\n message = \"Business has no application. Run 'npx dashnex create' to create one.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n await fs.writeFile(tempZipPath, buffer);\n debug(\"Zip written to temp file\");\n\n const zip = new AdmZip(tempZipPath);\n zip.extractAllTo(targetDir, true);\n debug(\"Extracted to target folder\");\n\n if (hasApp) {\n console.log(chalk.green(`Application pulled to ${targetDir}`));\n } else {\n console.log(chalk.green(getSuccessMessageNew(targetDir, cwd)));\n }\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n } finally {\n await fs.remove(tempZipPath).catch(() => {});\n debug(\"Temp zip removed\");\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sources":["../../src/commands/push.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport os from \"os\";\nimport AdmZip from \"adm-zip\";\nimport ignore from \"ignore\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\nconst ALWAYS_EXCLUDE = [\".dashnex\", \".git\"];\n\nconst collectFilesToInclude = async (\n dir: string,\n ig: ReturnType<typeof ignore>\n): Promise<string[]> => {\n const result: string[] = [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const relativePath = path.relative(process.cwd(), path.join(dir, entry.name));\n const normalized = relativePath.split(path.sep).join(\"/\");\n\n if (ALWAYS_EXCLUDE.some((ex) => normalized === ex || normalized.startsWith(`${ex}/`))) {\n continue;\n }\n if (ig.ignores(normalized)) {\n continue;\n }\n\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectFilesToInclude(fullPath, ig);\n result.push(...nested);\n } else if (entry.isFile()) {\n result.push(fullPath);\n }\n }\n\n return result;\n};\n\nexport class PushCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Push flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n const cwd = process.cwd();\n const gitignorePath = path.join(cwd, \".gitignore\");\n\n const ig = ignore();\n ig.add(ALWAYS_EXCLUDE);\n if (await fs.pathExists(gitignorePath)) {\n const content = await fs.readFile(gitignorePath, \"utf8\");\n ig.add(content);\n }\n\n debug(\"Building file list\");\n const files = await collectFilesToInclude(cwd, ig);\n debug(`Including ${files.length} files`);\n\n const zip = new AdmZip();\n for (const filePath of files) {\n const relativePath = path.relative(cwd, filePath);\n const entryPath = relativePath.split(path.sep).join(\"/\");\n const zipPath = path.dirname(entryPath) === \".\" ? \"\" : path.dirname(entryPath);\n const zipName = path.basename(entryPath);\n zip.addLocalFile(filePath, zipPath, zipName);\n }\n\n const tempZipPath = path.join(\n os.tmpdir(),\n `dashnex-push-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`\n );\n\n try {\n zip.writeZip(tempZipPath);\n debug(`Zip written to ${tempZipPath}`);\n\n const url = `${getBusinessApiBase()}/business/v1/cli/push`;\n debug(`POST ${url}`);\n\n const formData = new FormData();\n formData.append(\"file\", new Blob([await fs.readFile(tempZipPath)]), \"archive.zip\");\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${session.token}` },\n body: formData,\n });\n\n debug(`Response: ${response.status}`);\n\n if (!response.ok) {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to push application.\";\n if (response.status === 401 || response.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n console.log(chalk.green(\"Application pushed successfully.\"));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n } finally {\n await fs.remove(tempZipPath).catch(() => {});\n debug(\"Temp zip removed\");\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sources":["../../src/commands/version.ts"],"sourcesContent":["import { CliCommand } from \"@dashnex/types\";\n\nclass VersionCommand implements CliCommand {\n async execute(options: any) {\n const packageJson = await import(\"../../package.json\", { with: { type: \"json\" } });\n console.log(packageJson.default.version);\n }\n}\n\nexport default VersionCommand;"],"names":[],"mappings":"AAEA,MAAM,eAAqC;AAAA,EACzC,MAAM,QAAQ,SAAc;AAC1B,UAAM,cAAc,MAAM,OAAO,oBAAgD;AACjF,YAAQ,IAAI,YAAY,QAAQ,OAAO;AAAA,EACzC;AACF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.js","sources":["../../src/commands/whoami.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\ninterface MemberUser {\n fullName?: string;\n name?: string;\n}\n\ninterface WhoamiResponse {\n name?: string;\n companyName?: string;\n memberUser?: MemberUser;\n}\n\nexport class WhoamiCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Whoami flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n const url = `${getApiBase()}/users/v1/`;\n debug(`GET ${url}`);\n\n try {\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n\n debug(`Response: ${response.status}`);\n\n if (!response.ok) {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to fetch user info.\";\n if (response.status === 401 || response.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n const data = (await response.json().catch(() => ({}))) as WhoamiResponse;\n const businessName =\n typeof data.name === \"string\"\n ? data.name\n : typeof data.companyName === \"string\"\n ? data.companyName\n : \"Unknown\";\n const memberUser = data.memberUser;\n const userName =\n memberUser && typeof memberUser.fullName === \"string\"\n ? memberUser.fullName\n : memberUser && typeof memberUser.name === \"string\"\n ? memberUser.name\n : \"Unknown\";\n\n debug(`Whoami: ${businessName} (${userName})`);\n console.log(chalk.green(`You are logged in as ${businessName} (${userName})`));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n}\n"],"names":[],"mappings":";;;;AAMA,MAAM,sBAAsB,CAAC,SAAsD;AACjF,MAAI,OAAO,KAAK,UAAU,iBAAiB,KAAK;AAChD,MAAI,OAAO,KAAK,YAAY,iBAAiB,KAAK;AAClD,SAAO;AACT;AAaO,MAAM,cAAoC;AAAA,EAC/C,MAAM,UAAyB;AAC7B,UAAM,qBAAqB;AAE3B,UAAM,UAAU,MAAM,eAAA;AACtB,QAAI,CAAC,QAAS;AAEd,UAAM,MAAM,GAAG,WAAA,CAAY;AAC3B,UAAM,OAAO,GAAG,EAAE;AAElB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,SAAS,EAAE,eAAe,UAAU,QAAQ,KAAK,GAAA;AAAA,MAAG,CACrD;AAED,YAAM,aAAa,SAAS,MAAM,EAAE;AAEpC,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,YAAI,UAAU;AACd,YAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,oBAAU;AAAA,QACZ,WAAW,YAAY,SAAS,kBAAkB,GAAG;AACnD,gBAAM,OAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,gBAAM,aAAa,oBAAoB,IAAI;AAC3C,cAAI,WAAY,WAAU;AAAA,QAC5B;AACA,gBAAQ,MAAM,MAAM,IAAI,OAAO,CAAC;AAChC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,YAAM,eACJ,OAAO,KAAK,SAAS,WACjB,KAAK,OACL,OAAO,KAAK,gBAAgB,WAC1B,KAAK,cACL;AACR,YAAM,aAAa,KAAK;AACxB,YAAM,WACJ,cAAc,OAAO,WAAW,aAAa,WACzC,WAAW,WACX,cAAc,OAAO,WAAW,SAAS,WACvC,WAAW,OACX;AAER,YAAM,WAAW,YAAY,KAAK,QAAQ,GAAG;AAC7C,cAAQ,IAAI,MAAM,MAAM,wBAAwB,YAAY,KAAK,QAAQ,GAAG,CAAC;AAAA,IAC/E,SAAS,OAAO;AACd,iBAAW,KAAK;AAChB,UAAI,iBAAiB,SAAS,MAAM,QAAQ,WAAW,OAAO,EAAG,OAAM;AACvE,cAAQ,MAAM,MAAM,IAAI,mEAAmE,CAAC;AAC5F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;"}
|
package/dist/dashnex.json.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dashnex.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/lib/api.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sources":["../../src/lib/api.ts"],"sourcesContent":["const getApiBase = (): string => {\n return process.env.NEXT_PUBLIC_DASHNEX_API_DOMAIN || \"https://api.dashnex.com\";\n};\n\nconst getBusinessApiBase = (): string => {\n return process.env.DASHNEX_BUSINESS_API_URL || \"https://api.business.dashnex.com\";\n};\n\nconst apiFetch = async (\n url: string,\n options: RequestInit = {}\n): Promise<{ response: Response; body: Record<string, unknown> }> => {\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n return { response, body };\n};\n\nexport { getApiBase, getBusinessApiBase, apiFetch };\n"],"names":[],"mappings":"AAAA,MAAM,aAAa,MAAc;AAC/B,SAAO,QAAQ,IAAI,kCAAkC;AACvD;AAEA,MAAM,qBAAqB,MAAc;AACvC,SAAO,QAAQ,IAAI,4BAA4B;AACjD;AAEA,MAAM,WAAW,OACf,KACA,UAAuB,OAC4C;AACnE,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,GAAG;AAAA,IACH,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAG,QAAQ;AAAA,IAAA;AAAA,EACb,CACD;AACD,QAAM,OAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,SAAO,EAAE,UAAU,KAAA;AACrB;"}
|
package/dist/lib/debug.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sources":["../../src/lib/debug.ts"],"sourcesContent":["import chalk from \"chalk\";\n\nconst isSensitiveKey = (key: string): boolean => {\n const k = key.toLowerCase();\n return k.includes(\"token\") || k.includes(\"password\") || k === \"auth_code\";\n};\n\nconst sanitizeForLog = (obj: unknown): unknown => {\n if (obj === null || typeof obj !== \"object\") return obj;\n if (Array.isArray(obj)) {\n return obj.map(sanitizeForLog);\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (isSensitiveKey(key)) {\n result[key] = \"[REDACTED]\";\n } else {\n result[key] = sanitizeForLog(value);\n }\n }\n return result;\n};\n\nexport const debug = (msg: string): void => {\n if (process.env.DEBUG) {\n console.log(chalk.dim(msg));\n }\n};\n\nexport const debugJson = (label: string, body: unknown): void => {\n if (process.env.DEBUG) {\n const sanitized = sanitizeForLog(body);\n console.log(chalk.dim(`${label}: ${JSON.stringify(sanitized, null, 2)}`));\n }\n};\n\nexport const debugError = (error: unknown): void => {\n if (process.env.DEBUG && error instanceof Error) {\n console.log(chalk.dim(`Error: ${error.message}`));\n if (error.stack) {\n console.log(chalk.dim(`Stack: ${error.stack}`));\n }\n }\n};\n"],"names":[],"mappings":";AAEA,MAAM,iBAAiB,CAAC,QAAyB;AAC/C,QAAM,IAAI,IAAI,YAAA;AACd,SAAO,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,UAAU,KAAK,MAAM;AAChE;AAEA,MAAM,iBAAiB,CAAC,QAA0B;AAChD,MAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU,QAAO;AACpD,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,cAAc;AAAA,EAC/B;AACA,QAAM,SAAkC,CAAA;AACxC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAA8B,GAAG;AACzE,QAAI,eAAe,GAAG,GAAG;AACvB,aAAO,GAAG,IAAI;AAAA,IAChB,OAAO;AACL,aAAO,GAAG,IAAI,eAAe,KAAK;AAAA,IACpC;AAAA,EACF;AACA,SAAO;AACT;AAEO,MAAM,QAAQ,CAAC,QAAsB;AAC1C,MAAI,QAAQ,IAAI,OAAO;AACrB,YAAQ,IAAI,MAAM,IAAI,GAAG,CAAC;AAAA,EAC5B;AACF;AAEO,MAAM,YAAY,CAAC,OAAe,SAAwB;AAC/D,MAAI,QAAQ,IAAI,OAAO;AACrB,UAAM,YAAY,eAAe,IAAI;AACrC,YAAQ,IAAI,MAAM,IAAI,GAAG,KAAK,KAAK,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC,EAAE,CAAC;AAAA,EAC1E;AACF;AAEO,MAAM,aAAa,CAAC,UAAyB;AAClD,MAAI,QAAQ,IAAI,SAAS,iBAAiB,OAAO;AAC/C,YAAQ,IAAI,MAAM,IAAI,UAAU,MAAM,OAAO,EAAE,CAAC;AAChD,QAAI,MAAM,OAAO;AACf,cAAQ,IAAI,MAAM,IAAI,UAAU,MAAM,KAAK,EAAE,CAAC;AAAA,IAChD;AAAA,EACF;AACF;"}
|
package/dist/package.json.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"package.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/dist/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../src/server.ts"],"sourcesContent":["\nimport { ModuleConfig } from '@dashnex/types';\n\nimport packageJson from '../package.json' with { type: \"json\" };\nimport dashnexConfig from '../dashnex.json' with { type: \"json\" };\n\nexport default {\n name: packageJson.name,\n version: packageJson.version,\n description: packageJson.description,\n ...dashnexConfig,\n} as ModuleConfig;\n"],"names":[],"mappings":";;AAMA,MAAA,SAAe;AAAA,EACX,MAAM,YAAY;AAAA,EAClB,SAAS,YAAY;AAAA,EACrB,aAAa,YAAY;AAAA,EACzB,GAAG;AACP;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sources":["../../src/services/auth.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { debug, debugJson, debugError } from \"../lib/debug.js\";\nimport { getApiBase, apiFetch } from \"../lib/api.js\";\n\ninterface DashnexConfig {\n token?: string;\n refreshToken?: string;\n businessId?: string;\n}\n\nexport interface EnsureLoggedInResult {\n token: string;\n businessId: string;\n userName?: string;\n}\n\nexport interface EnsureLoggedInOptions {\n exitOnFailure?: boolean;\n dashnexPath?: string;\n}\n\nconst findDashnexPath = async (startDir: string): Promise<string | null> => {\n let dir = path.resolve(startDir);\n while (true) {\n const candidate = path.join(dir, \".dashnex\");\n if (await fs.pathExists(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n};\n\nconst validateTokenAndRefreshIfNeeded = async (\n token: string,\n refreshToken: string | undefined,\n dashnexPath: string,\n config: DashnexConfig\n): Promise<EnsureLoggedInResult | null> => {\n debug(`GET ${getApiBase()}/users/v1/`);\n try {\n const { response, body } = await apiFetch(`${getApiBase()}/users/v1/`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n debug(`Response: ${response.status}`);\n debugJson(\"Users response\", body);\n\n if (response.ok) {\n const data = body as { id?: string; name?: string };\n if (typeof data.name === \"string\" && config.businessId) {\n debug(`Token valid, Already logged in as ${data.name}`);\n return {\n token,\n businessId: config.businessId,\n userName: data.name,\n };\n }\n }\n\n if (!refreshToken) {\n debug(\"Token invalid, no refreshToken available\");\n return null;\n }\n\n debug(`POST ${getApiBase()}/auth/v1/token/refresh`);\n const { response: refreshResponse, body: refreshBody } = await apiFetch(\n `${getApiBase()}/auth/v1/token/refresh`,\n {\n method: \"POST\",\n body: JSON.stringify({ refreshToken }),\n }\n );\n debug(`Response: ${refreshResponse.status}`);\n debugJson(\"Refresh response\", refreshBody);\n\n if (!refreshResponse.ok) {\n debug(\"Token refresh failed\");\n return null;\n }\n\n const refreshData = refreshBody as { token?: string; refreshToken?: string };\n if (!refreshData.token || !refreshData.refreshToken) {\n debug(\"Refresh response missing tokens\");\n return null;\n }\n\n const updatedConfig = (await fs.readJson(dashnexPath)) as DashnexConfig;\n updatedConfig.token = refreshData.token;\n updatedConfig.refreshToken = refreshData.refreshToken;\n await fs.writeJson(dashnexPath, updatedConfig, { spaces: 2 });\n debug(\"Updated .dashnex with new tokens, retrying session check\");\n\n return validateTokenAndRefreshIfNeeded(\n refreshData.token,\n refreshData.refreshToken,\n dashnexPath,\n { ...updatedConfig, token: refreshData.token, refreshToken: refreshData.refreshToken }\n );\n } catch (error) {\n debugError(error);\n return null;\n }\n};\n\nexport const ensureLoggedIn = async (\n options: EnsureLoggedInOptions = {}\n): Promise<EnsureLoggedInResult | null> => {\n const { exitOnFailure = true, dashnexPath: customPath } = options;\n const dashnexPath = customPath ?? (await findDashnexPath(process.cwd()));\n\n if (!dashnexPath || !(await fs.pathExists(dashnexPath))) {\n debug(\".dashnex not found\");\n if (exitOnFailure) {\n console.error(chalk.red(\"Please run 'npx dashnex login' to authenticate.\"));\n process.exit(1);\n }\n return null;\n }\n\n let config: DashnexConfig;\n try {\n config = (await fs.readJson(dashnexPath)) as DashnexConfig;\n } catch {\n debug(\".dashnex parse failed\");\n if (exitOnFailure) {\n console.error(chalk.red(\"Please run 'npx dashnex login' to authenticate.\"));\n process.exit(1);\n }\n return null;\n }\n\n const { token, refreshToken, businessId } = config;\n if (!token) {\n debug(\".dashnex missing token\");\n if (exitOnFailure) {\n console.error(chalk.red(\"Please run 'npx dashnex login' to authenticate.\"));\n process.exit(1);\n }\n return null;\n }\n\n const result = await validateTokenAndRefreshIfNeeded(token, refreshToken, dashnexPath, config);\n if (result) return result;\n\n if (exitOnFailure) {\n console.error(chalk.red(\"Please run 'npx dashnex login' to authenticate.\"));\n process.exit(1);\n }\n return null;\n};\n"],"names":[],"mappings":"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"}
|