dockup-cli 1.0.0

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.
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.api = void 0;
7
+ const node_fetch_1 = __importDefault(require("node-fetch"));
8
+ const config_1 = require("./config");
9
+ class ApiClient {
10
+ getHeaders(includeContentType = false) {
11
+ const headers = {};
12
+ if (includeContentType) {
13
+ headers['Content-Type'] = 'application/json';
14
+ }
15
+ const token = (0, config_1.getToken)();
16
+ if (token) {
17
+ headers['Authorization'] = `Bearer ${token}`;
18
+ }
19
+ return headers;
20
+ }
21
+ async get(path) {
22
+ const url = `${(0, config_1.getApiUrl)()}${path}`;
23
+ const response = await (0, node_fetch_1.default)(url, {
24
+ method: 'GET',
25
+ headers: this.getHeaders(),
26
+ });
27
+ if (!response.ok) {
28
+ const error = await response.json().catch(() => ({}));
29
+ throw new Error(error.error || error.message || `Request failed with status ${response.status}`);
30
+ }
31
+ return response.json();
32
+ }
33
+ async post(path, body) {
34
+ const url = `${(0, config_1.getApiUrl)()}${path}`;
35
+ const response = await (0, node_fetch_1.default)(url, {
36
+ method: 'POST',
37
+ headers: this.getHeaders(!!body),
38
+ body: body ? JSON.stringify(body) : undefined,
39
+ });
40
+ if (!response.ok) {
41
+ const error = await response.json().catch(() => ({}));
42
+ throw new Error(error.error || error.message || `Request failed with status ${response.status}`);
43
+ }
44
+ return response.json();
45
+ }
46
+ async put(path, body) {
47
+ const url = `${(0, config_1.getApiUrl)()}${path}`;
48
+ const response = await (0, node_fetch_1.default)(url, {
49
+ method: 'PUT',
50
+ headers: this.getHeaders(!!body),
51
+ body: body ? JSON.stringify(body) : undefined,
52
+ });
53
+ if (!response.ok) {
54
+ const error = await response.json().catch(() => ({}));
55
+ throw new Error(error.error || error.message || `Request failed with status ${response.status}`);
56
+ }
57
+ return response.json();
58
+ }
59
+ async delete(path) {
60
+ const url = `${(0, config_1.getApiUrl)()}${path}`;
61
+ const response = await (0, node_fetch_1.default)(url, {
62
+ method: 'DELETE',
63
+ headers: this.getHeaders(),
64
+ });
65
+ if (!response.ok) {
66
+ const error = await response.json().catch(() => ({}));
67
+ throw new Error(error.error || error.message || `Request failed with status ${response.status}`);
68
+ }
69
+ return response.json();
70
+ }
71
+ // Verify token and get user info
72
+ async verifyToken() {
73
+ try {
74
+ const response = await this.get('/auth/me');
75
+ return response.user;
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ // Get projects list
82
+ async getProjects() {
83
+ const response = await this.get('/projects');
84
+ return response.projects || [];
85
+ }
86
+ // Get services for a project
87
+ async getServices(projectSlug) {
88
+ const response = await this.get(`/projects/${projectSlug}/services`);
89
+ return response.services || [];
90
+ }
91
+ // Trigger deploy
92
+ async deploy(projectSlug, serviceSlug, options) {
93
+ return this.post(`/projects/${projectSlug}/services/${serviceSlug}/deploy`, options);
94
+ }
95
+ // Get service status
96
+ async getServiceStatus(projectSlug, serviceSlug) {
97
+ return this.get(`/projects/${projectSlug}/services/${serviceSlug}`);
98
+ }
99
+ // Get env variables
100
+ async getEnvVariables(projectSlug, serviceSlug) {
101
+ const service = await this.getServiceStatus(projectSlug, serviceSlug);
102
+ return service.envVariables || [];
103
+ }
104
+ // Set env variable
105
+ async setEnvVariable(projectSlug, serviceSlug, key, value, isSecret = false) {
106
+ await this.post(`/projects/${projectSlug}/services/${serviceSlug}/env`, {
107
+ key,
108
+ value,
109
+ isSecret
110
+ });
111
+ }
112
+ // Delete env variable
113
+ async deleteEnvVariable(projectSlug, serviceSlug, key) {
114
+ await this.delete(`/projects/${projectSlug}/services/${serviceSlug}/env/${key}`);
115
+ }
116
+ // =================== WORKSPACE METHODS ===================
117
+ // Get all workspaces (projects)
118
+ async getWorkspaces() {
119
+ const response = await this.get('/projects');
120
+ return response.projects || [];
121
+ }
122
+ // Create workspace
123
+ async createWorkspace(name) {
124
+ const response = await this.post('/projects', { name });
125
+ return response.project;
126
+ }
127
+ // Rename workspace
128
+ async renameWorkspace(id, name) {
129
+ const response = await this.put(`/projects/${id}`, { name });
130
+ return response.project;
131
+ }
132
+ // Delete workspace
133
+ async deleteWorkspace(id) {
134
+ await this.delete(`/projects/${id}`);
135
+ }
136
+ // =================== DATABASE METHODS ===================
137
+ // Get databases for workspace (uses project slug)
138
+ async getDatabases(projectSlug) {
139
+ const response = await this.get(`/projects/${projectSlug}/databases`);
140
+ return response.databases || [];
141
+ }
142
+ // Create database
143
+ async createDatabase(projectSlug, name, dbType, dbVersion) {
144
+ const response = await this.post(`/projects/${projectSlug}/databases`, {
145
+ name,
146
+ dbType,
147
+ dbVersion: dbVersion || '17'
148
+ });
149
+ return response.database;
150
+ }
151
+ // Get database details
152
+ async getDatabase(projectSlug, dbSlug) {
153
+ const response = await this.get(`/projects/${projectSlug}/databases/${dbSlug}`);
154
+ return response.database;
155
+ }
156
+ // Rename database
157
+ async renameDatabase(projectSlug, dbSlug, name) {
158
+ const response = await this.put(`/projects/${projectSlug}/databases/${dbSlug}`, { name });
159
+ return response.database;
160
+ }
161
+ // Delete database
162
+ async deleteDatabase(projectSlug, dbSlug) {
163
+ await this.delete(`/projects/${projectSlug}/databases/${dbSlug}`);
164
+ }
165
+ // Get database credentials (from details endpoint)
166
+ async getDatabaseCredentials(projectSlug, dbSlug) {
167
+ const response = await this.get(`/projects/${projectSlug}/databases/${dbSlug}`);
168
+ return response.database?.connection || response.database;
169
+ }
170
+ // Restart database
171
+ async restartDatabase(projectSlug, dbSlug) {
172
+ return this.post(`/projects/${projectSlug}/databases/${dbSlug}/restart`);
173
+ }
174
+ // Get database logs
175
+ async getDatabaseLogs(projectSlug, dbSlug, tail = 100) {
176
+ return this.get(`/projects/${projectSlug}/databases/${dbSlug}/logs?tail=${tail}`);
177
+ }
178
+ // Get database size
179
+ async getDatabaseSize(projectSlug, dbSlug) {
180
+ return this.get(`/projects/${projectSlug}/databases/${dbSlug}/size`);
181
+ }
182
+ // Get database backups
183
+ async getDatabaseBackups(projectSlug, dbSlug) {
184
+ const response = await this.get(`/projects/${projectSlug}/databases/${dbSlug}/backups`);
185
+ return response.backups || [];
186
+ }
187
+ // Create database backup
188
+ async createDatabaseBackup(projectSlug, dbSlug) {
189
+ return this.post(`/projects/${projectSlug}/databases/${dbSlug}/backups`);
190
+ }
191
+ // Delete database backup
192
+ async deleteDatabaseBackup(projectSlug, dbSlug, backupId) {
193
+ return this.delete(`/projects/${projectSlug}/databases/${dbSlug}/backups/${backupId}`);
194
+ }
195
+ }
196
+ exports.api = new ApiClient();
@@ -0,0 +1,51 @@
1
+ interface ConfigData {
2
+ token?: string;
3
+ user?: {
4
+ id: string;
5
+ email: string;
6
+ name: string;
7
+ };
8
+ apiUrl?: string;
9
+ currentWorkspace?: {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ };
14
+ }
15
+ declare const config: {
16
+ get(key: keyof ConfigData): any;
17
+ set(key: keyof ConfigData, value: any): void;
18
+ delete(key: keyof ConfigData): void;
19
+ clear(): void;
20
+ };
21
+ export interface User {
22
+ id: string;
23
+ email: string;
24
+ name: string;
25
+ }
26
+ export interface ProjectConfig {
27
+ projectSlug: string;
28
+ serviceSlug: string;
29
+ serviceName: string;
30
+ projectName: string;
31
+ }
32
+ export interface Workspace {
33
+ id: string;
34
+ name: string;
35
+ slug: string;
36
+ }
37
+ export declare function getToken(): string | undefined;
38
+ export declare function setToken(token: string): void;
39
+ export declare function clearToken(): void;
40
+ export declare function getUser(): User | undefined;
41
+ export declare function setUser(user: User): void;
42
+ export declare function getApiUrl(): string;
43
+ export declare function getCurrentWorkspace(): Workspace | undefined;
44
+ export declare function setCurrentWorkspace(workspace: Workspace): void;
45
+ export declare function clearCurrentWorkspace(): void;
46
+ export declare function setApiUrl(url: string): void;
47
+ export declare function getProjectConfig(): ProjectConfig | null;
48
+ export declare function saveProjectConfig(projectConfig: ProjectConfig): void;
49
+ export declare function removeProjectConfig(): boolean;
50
+ export declare function isLoggedIn(): boolean;
51
+ export default config;
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getToken = getToken;
37
+ exports.setToken = setToken;
38
+ exports.clearToken = clearToken;
39
+ exports.getUser = getUser;
40
+ exports.setUser = setUser;
41
+ exports.getApiUrl = getApiUrl;
42
+ exports.getCurrentWorkspace = getCurrentWorkspace;
43
+ exports.setCurrentWorkspace = setCurrentWorkspace;
44
+ exports.clearCurrentWorkspace = clearCurrentWorkspace;
45
+ exports.setApiUrl = setApiUrl;
46
+ exports.getProjectConfig = getProjectConfig;
47
+ exports.saveProjectConfig = saveProjectConfig;
48
+ exports.removeProjectConfig = removeProjectConfig;
49
+ exports.isLoggedIn = isLoggedIn;
50
+ const fs = __importStar(require("fs"));
51
+ const path = __importStar(require("path"));
52
+ const os = __importStar(require("os"));
53
+ // Config file path: ~/.dockup/config.json
54
+ const CONFIG_DIR = path.join(os.homedir(), '.dockup');
55
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
56
+ // Ensure config directory exists
57
+ function ensureConfigDir() {
58
+ if (!fs.existsSync(CONFIG_DIR)) {
59
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
60
+ }
61
+ }
62
+ // Read config file
63
+ function readConfig() {
64
+ ensureConfigDir();
65
+ if (!fs.existsSync(CONFIG_FILE)) {
66
+ return {};
67
+ }
68
+ try {
69
+ return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
70
+ }
71
+ catch {
72
+ return {};
73
+ }
74
+ }
75
+ // Write config file
76
+ function writeConfig(data) {
77
+ ensureConfigDir();
78
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2));
79
+ }
80
+ // Simple config object that mimics Conf API
81
+ const config = {
82
+ get(key) {
83
+ const data = readConfig();
84
+ return data[key];
85
+ },
86
+ set(key, value) {
87
+ const data = readConfig();
88
+ data[key] = value;
89
+ writeConfig(data);
90
+ },
91
+ delete(key) {
92
+ const data = readConfig();
93
+ delete data[key];
94
+ writeConfig(data);
95
+ },
96
+ clear() {
97
+ writeConfig({});
98
+ }
99
+ };
100
+ // Get API token
101
+ function getToken() {
102
+ return config.get('token');
103
+ }
104
+ // Set API token
105
+ function setToken(token) {
106
+ config.set('token', token);
107
+ }
108
+ // Clear token (logout)
109
+ function clearToken() {
110
+ config.delete('token');
111
+ config.delete('user');
112
+ config.delete('currentWorkspace');
113
+ }
114
+ // Get current user
115
+ function getUser() {
116
+ return config.get('user');
117
+ }
118
+ // Set current user
119
+ function setUser(user) {
120
+ config.set('user', user);
121
+ }
122
+ // Get API URL
123
+ function getApiUrl() {
124
+ return config.get('apiUrl') || 'https://app.dockup.ai/api';
125
+ }
126
+ // Get current workspace
127
+ function getCurrentWorkspace() {
128
+ return config.get('currentWorkspace');
129
+ }
130
+ // Set current workspace
131
+ function setCurrentWorkspace(workspace) {
132
+ config.set('currentWorkspace', workspace);
133
+ }
134
+ // Clear current workspace
135
+ function clearCurrentWorkspace() {
136
+ config.delete('currentWorkspace');
137
+ }
138
+ // Set API URL (for development)
139
+ function setApiUrl(url) {
140
+ config.set('apiUrl', url);
141
+ }
142
+ // Project-level config stored in .dockup file
143
+ const PROJECT_CONFIG_FILE = '.dockup';
144
+ // Get project config from current directory
145
+ function getProjectConfig() {
146
+ const configPath = path.join(process.cwd(), PROJECT_CONFIG_FILE);
147
+ if (!fs.existsSync(configPath)) {
148
+ return null;
149
+ }
150
+ try {
151
+ const content = fs.readFileSync(configPath, 'utf-8');
152
+ return JSON.parse(content);
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
158
+ // Save project config to current directory
159
+ function saveProjectConfig(projectConfig) {
160
+ const configPath = path.join(process.cwd(), PROJECT_CONFIG_FILE);
161
+ fs.writeFileSync(configPath, JSON.stringify(projectConfig, null, 2));
162
+ }
163
+ // Remove project config
164
+ function removeProjectConfig() {
165
+ const configPath = path.join(process.cwd(), PROJECT_CONFIG_FILE);
166
+ if (fs.existsSync(configPath)) {
167
+ fs.unlinkSync(configPath);
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+ // Check if logged in
173
+ function isLoggedIn() {
174
+ return !!getToken();
175
+ }
176
+ exports.default = config;
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "dockup-cli",
3
+ "version": "1.0.0",
4
+ "description": "Dockup CLI - Manage your databases and workspaces from the terminal",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "dockup": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "ts-node src/index.ts",
15
+ "start": "node dist/index.js",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "cli",
20
+ "dockup",
21
+ "database",
22
+ "postgresql",
23
+ "mysql",
24
+ "mongodb",
25
+ "redis",
26
+ "deploy",
27
+ "paas"
28
+ ],
29
+ "author": "Dockup",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/dockup/cli.git"
34
+ },
35
+ "homepage": "https://dockup.dev",
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ },
39
+ "dependencies": {
40
+ "chalk": "^4.1.2",
41
+ "commander": "^11.1.0",
42
+ "node-fetch": "^2.7.0",
43
+ "open": "^8.4.2",
44
+ "ora": "^5.4.1"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.10.0",
48
+ "@types/node-fetch": "^2.6.13",
49
+ "ts-node": "^10.9.2",
50
+ "typescript": "^5.3.0"
51
+ }
52
+ }