@sammydev/justask 1.3.6
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/.justalk.json +4 -0
- package/README.md +0 -0
- package/commands/apikey.js +57 -0
- package/commands/deploy.js +67 -0
- package/commands/env.js +41 -0
- package/commands/history.js +25 -0
- package/commands/init.js +76 -0
- package/commands/install.js +254 -0
- package/commands/link.js +45 -0
- package/commands/login.js +55 -0
- package/commands/logout.js +20 -0
- package/commands/logs.js +27 -0
- package/commands/me.js +26 -0
- package/commands/ping.js +27 -0
- package/commands/plugins.js +25 -0
- package/commands/projects.js +34 -0
- package/commands/promote.js +24 -0
- package/commands/rollback.js +24 -0
- package/commands/run.js +56 -0
- package/commands/search.js +37 -0
- package/commands/status.js +33 -0
- package/commands/use.js +22 -0
- package/index.js +88 -0
- package/justalk.json +4 -0
- package/lib/api.js +42 -0
- package/lib/config.js +62 -0
- package/lib/gitContext.js +23 -0
- package/lib/loadCommands.js +46 -0
- package/lib/projectContext.js +16 -0
- package/package.json +21 -0
- package/plugin-slack/index.js +18 -0
- package/plugin-slack/plugin.json +8 -0
- package/plugins/slack.js +9 -0
package/.justalk.json
ADDED
package/README.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { apiPost } = require("../lib/api");
|
|
2
|
+
const {
|
|
3
|
+
getConfig,
|
|
4
|
+
saveConfig
|
|
5
|
+
} = require("../lib/config");
|
|
6
|
+
|
|
7
|
+
// --------------------
|
|
8
|
+
// apikey [node index.js apikey 1]
|
|
9
|
+
// --------------------
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module.exports = function (program) {
|
|
13
|
+
program
|
|
14
|
+
.command(
|
|
15
|
+
"apikey <projectId>"
|
|
16
|
+
)
|
|
17
|
+
.description(
|
|
18
|
+
"Generate API key"
|
|
19
|
+
)
|
|
20
|
+
.action(
|
|
21
|
+
async (projectId) => {
|
|
22
|
+
try {
|
|
23
|
+
const res =
|
|
24
|
+
await apiPost(
|
|
25
|
+
`/api/cli/projects/${projectId}/keys`
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const config =
|
|
29
|
+
getConfig();
|
|
30
|
+
|
|
31
|
+
saveConfig({
|
|
32
|
+
...config,
|
|
33
|
+
api_key:
|
|
34
|
+
res.data.key
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(
|
|
38
|
+
"š API Key generated:"
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
console.log(
|
|
42
|
+
res.data.key
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.log(
|
|
47
|
+
"ā Failed to generate API key"
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
console.log(
|
|
51
|
+
err.response?.data ||
|
|
52
|
+
err.message
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const { apiPost } = require("../lib/api");
|
|
2
|
+
const { getConfig } = require("../lib/config");
|
|
3
|
+
const { getLinkedProject } = require("../lib/projectContext");
|
|
4
|
+
const { getCurrentBranch } = require("../lib/gitContext");
|
|
5
|
+
|
|
6
|
+
module.exports = function (program) {
|
|
7
|
+
program
|
|
8
|
+
.command("deploy")
|
|
9
|
+
.description("Deploy active project")
|
|
10
|
+
.option("--prod", "Deploy to production")
|
|
11
|
+
.option("--staging", "Deploy to staging")
|
|
12
|
+
.option("--dev", "Deploy to development")
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
|
|
15
|
+
const config = getConfig();
|
|
16
|
+
|
|
17
|
+
const project =
|
|
18
|
+
getLinkedProject() ||
|
|
19
|
+
config.active_project ||
|
|
20
|
+
(config.projects?.length ? config.projects[0].id : null);
|
|
21
|
+
|
|
22
|
+
if (!project) {
|
|
23
|
+
console.log("ā No project found");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const branch = getCurrentBranch();
|
|
28
|
+
|
|
29
|
+
let env = "prod"; // default fallback
|
|
30
|
+
|
|
31
|
+
if (options.staging) {
|
|
32
|
+
env = "staging";
|
|
33
|
+
} else if (options.dev) {
|
|
34
|
+
env = "dev";
|
|
35
|
+
} else if (options.prod) {
|
|
36
|
+
env = "prod";
|
|
37
|
+
} else {
|
|
38
|
+
// š§ smart inference
|
|
39
|
+
if (branch === "main" || branch === "master") {
|
|
40
|
+
env = "prod";
|
|
41
|
+
} else if (branch === "develop" || branch === "dev") {
|
|
42
|
+
env = "staging";
|
|
43
|
+
} else {
|
|
44
|
+
env = "dev";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`šæ Branch: ${branch || "no git repo"}`);
|
|
49
|
+
console.log(`šæ Branch: ${branch || "unknown"}`);
|
|
50
|
+
console.log(`š Environment: ${env}`);
|
|
51
|
+
console.log(`š Deploying project ${project} to ${env}`);
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const res = await apiPost("/api/cli/deploy", {
|
|
55
|
+
project_id: project,
|
|
56
|
+
env
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
console.log("ā
Deployment successful š");
|
|
60
|
+
console.log(res.data);
|
|
61
|
+
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.log("ā Deploy failed");
|
|
64
|
+
console.log(err.response?.data || err.message);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
};
|
package/commands/env.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getConfig,
|
|
3
|
+
saveConfig
|
|
4
|
+
} = require("../lib/config");
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// --------------------
|
|
8
|
+
// ENV [ node index.js env prod ]
|
|
9
|
+
// --------------------
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module.exports = function (program) {
|
|
13
|
+
program
|
|
14
|
+
.command("env <type>")
|
|
15
|
+
.description(
|
|
16
|
+
"Set environment (dev or prod)"
|
|
17
|
+
)
|
|
18
|
+
.action((type) => {
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
!["dev", "prod"].includes(type)
|
|
22
|
+
) {
|
|
23
|
+
console.log(
|
|
24
|
+
"ā Invalid environment. Use dev or prod."
|
|
25
|
+
);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const config =
|
|
30
|
+
getConfig();
|
|
31
|
+
|
|
32
|
+
saveConfig({
|
|
33
|
+
...config,
|
|
34
|
+
env: type
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(
|
|
38
|
+
`š Environment set to: ${type}`
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const { apiGet } = require("../lib/api");
|
|
2
|
+
|
|
3
|
+
module.exports = function (program) {
|
|
4
|
+
program
|
|
5
|
+
.command("history")
|
|
6
|
+
.description("Show deployment history")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
console.log("š Loading deployment history...\n");
|
|
11
|
+
|
|
12
|
+
const res = await apiGet("/api/cli/deployments/history");
|
|
13
|
+
|
|
14
|
+
res.data.forEach(d => {
|
|
15
|
+
console.log(
|
|
16
|
+
`#${d.id} | Project ${d.project_id} | ${d.env} | ${d.status} | ${d.version}`
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.log("ā Failed to load history");
|
|
22
|
+
console.log(err.response?.data || err.message);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
};
|
package/commands/init.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const fs = require("fs-extra");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { apiGet } = require("../lib/api");
|
|
4
|
+
const { apiPost } = require("../lib/api");
|
|
5
|
+
const { saveConfig, getConfig } = require("../lib/config");
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = function (program) {
|
|
9
|
+
program
|
|
10
|
+
.command("init")
|
|
11
|
+
.description("Initialize Justalk project in current folder")
|
|
12
|
+
.action(async () => {
|
|
13
|
+
|
|
14
|
+
console.log("š Initializing Justalk project...\n");
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
|
|
19
|
+
// 1. fetch projects from backend
|
|
20
|
+
const res = await apiGet("/api/cli/projects");
|
|
21
|
+
const projects = res.data;
|
|
22
|
+
|
|
23
|
+
if (!projects.length) {
|
|
24
|
+
console.log("ā No projects found");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log("š¦ Available projects:\n");
|
|
29
|
+
|
|
30
|
+
projects.forEach(p => {
|
|
31
|
+
console.log(`${p.id}. ${p.name} (${p.slug})`);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
const folderName = path.basename(process.cwd()).toLowerCase();
|
|
36
|
+
|
|
37
|
+
let project = projects.find(p =>
|
|
38
|
+
p.name.toLowerCase() === folderName ||
|
|
39
|
+
p.slug.toLowerCase().includes(folderName)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!project) {
|
|
43
|
+
console.log("š No matching project found");
|
|
44
|
+
console.log(`š Creating new project: ${folderName}\n`);
|
|
45
|
+
|
|
46
|
+
const res = await apiPost("/api/cli/projects/auto-create", {
|
|
47
|
+
name: folderName
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
project = res.data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 3. create .justalk.json in current folder
|
|
54
|
+
const file = path.join(process.cwd(), ".justalk.json");
|
|
55
|
+
|
|
56
|
+
fs.writeJSONSync(file, {
|
|
57
|
+
project_id: project.id,
|
|
58
|
+
project_slug: project.slug
|
|
59
|
+
}, { spaces: 2 });
|
|
60
|
+
|
|
61
|
+
saveConfig({
|
|
62
|
+
...config,
|
|
63
|
+
active_project: project.id,
|
|
64
|
+
projects: [...(config.projects || []), project]
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log("ā
Project initialized successfully!");
|
|
68
|
+
console.log("š Linked to folder");
|
|
69
|
+
console.log("š You can now run: justalk deploy");
|
|
70
|
+
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.log("ā Init failed");
|
|
73
|
+
console.log(err.response?.data || err.message);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// const fs = require("fs-extra");
|
|
2
|
+
// const path = require("path");
|
|
3
|
+
// const axios = require("axios");
|
|
4
|
+
|
|
5
|
+
// module.exports = function (program) {
|
|
6
|
+
// program
|
|
7
|
+
// .command("install <type> <source>")
|
|
8
|
+
// .description("Install plugins from remote sources")
|
|
9
|
+
// .action(async (type, source) => {
|
|
10
|
+
|
|
11
|
+
// if (type !== "plugin") {
|
|
12
|
+
// console.log("ā Only 'plugin' installs supported for now");
|
|
13
|
+
// return;
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
// try {
|
|
17
|
+
|
|
18
|
+
// console.log(`š¦ Installing plugin: ${source}`);
|
|
19
|
+
|
|
20
|
+
// // =========================
|
|
21
|
+
// // VERSION PARSING
|
|
22
|
+
// // =========================
|
|
23
|
+
// let version = "latest";
|
|
24
|
+
|
|
25
|
+
// if (source.includes("@")) {
|
|
26
|
+
// const parts = source.split("@");
|
|
27
|
+
// source = parts[0];
|
|
28
|
+
// version = parts[1];
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// let code = "";
|
|
32
|
+
// let metadata = null;
|
|
33
|
+
|
|
34
|
+
// // =========================
|
|
35
|
+
// // REGISTRY RESOLUTION
|
|
36
|
+
// // =========================
|
|
37
|
+
// if (!source.startsWith("github:") && !source.startsWith("http")) {
|
|
38
|
+
|
|
39
|
+
// console.log(`š¦ Resolving "${source}" from registry...`);
|
|
40
|
+
|
|
41
|
+
// const res = await axios.get(
|
|
42
|
+
// `http://127.0.0.1:8000/api/cli/plugins/search?q=${source}`
|
|
43
|
+
// );
|
|
44
|
+
|
|
45
|
+
// const plugin = res.data?.[0];
|
|
46
|
+
|
|
47
|
+
// if (!plugin) {
|
|
48
|
+
// console.log("ā Plugin not found in registry");
|
|
49
|
+
// return;
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// source = `github:${plugin.repo}`;
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
// // =========================
|
|
56
|
+
// // GITHUB RESOLUTION (FIXED + SAFE)
|
|
57
|
+
// // =========================
|
|
58
|
+
// if (source.startsWith("github:")) {
|
|
59
|
+
|
|
60
|
+
// const repo = source.replace("github:", "");
|
|
61
|
+
|
|
62
|
+
// const branchesToTry = [
|
|
63
|
+
// version && version !== "latest" ? `v${version}` : null,
|
|
64
|
+
// "main",
|
|
65
|
+
// "master"
|
|
66
|
+
// ].filter(Boolean);
|
|
67
|
+
|
|
68
|
+
// const possibleFiles = [
|
|
69
|
+
// "plugin.json",
|
|
70
|
+
// "index.js",
|
|
71
|
+
// "plugin.js",
|
|
72
|
+
// "justalk.js",
|
|
73
|
+
// "src/index.js"
|
|
74
|
+
// ];
|
|
75
|
+
|
|
76
|
+
// let success = false;
|
|
77
|
+
|
|
78
|
+
// for (const branch of branchesToTry) {
|
|
79
|
+
|
|
80
|
+
// // -------------------------
|
|
81
|
+
// // TRY METADATA FIRST
|
|
82
|
+
// // -------------------------
|
|
83
|
+
// try {
|
|
84
|
+
// const metaUrl = `https://raw.githubusercontent.com/${repo}/${branch}/plugin.json`;
|
|
85
|
+
// const metaRes = await axios.get(metaUrl);
|
|
86
|
+
// metadata = metaRes.data;
|
|
87
|
+
// } catch (e) {}
|
|
88
|
+
|
|
89
|
+
// const entryFile =
|
|
90
|
+
// metadata?.entry ||
|
|
91
|
+
// metadata?.main ||
|
|
92
|
+
// null;
|
|
93
|
+
|
|
94
|
+
// const filesToTry = entryFile
|
|
95
|
+
// ? [entryFile]
|
|
96
|
+
// : possibleFiles;
|
|
97
|
+
|
|
98
|
+
// for (const file of filesToTry) {
|
|
99
|
+
|
|
100
|
+
// try {
|
|
101
|
+
// const url = `https://raw.githubusercontent.com/${repo}/${branch}/${file}`;
|
|
102
|
+
// const res = await axios.get(url);
|
|
103
|
+
|
|
104
|
+
// code = res.data;
|
|
105
|
+
// success = true;
|
|
106
|
+
|
|
107
|
+
// console.log(`š Loaded from ${branch}/${file}`);
|
|
108
|
+
// break;
|
|
109
|
+
|
|
110
|
+
// } catch (e) {}
|
|
111
|
+
// }
|
|
112
|
+
|
|
113
|
+
// if (success) break;
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
// if (!success) {
|
|
117
|
+
// console.log("ā Failed to load plugin entry file");
|
|
118
|
+
// console.log("š Check repo structure (index.js or plugin.json)");
|
|
119
|
+
// return;
|
|
120
|
+
// }
|
|
121
|
+
// }
|
|
122
|
+
|
|
123
|
+
// // =========================
|
|
124
|
+
// // SAFETY CHECK
|
|
125
|
+
// // =========================
|
|
126
|
+
// if (!code || code.trim().length === 0) {
|
|
127
|
+
// console.log("ā Plugin download failed (empty code)");
|
|
128
|
+
// return;
|
|
129
|
+
// }
|
|
130
|
+
|
|
131
|
+
// // =========================
|
|
132
|
+
// // ENSURE PLUGINS DIR EXISTS
|
|
133
|
+
// // =========================
|
|
134
|
+
// const pluginsDir = path.join(process.cwd(), "plugins");
|
|
135
|
+
// fs.ensureDirSync(pluginsDir);
|
|
136
|
+
|
|
137
|
+
// // =========================
|
|
138
|
+
// // SAFE PLUGIN NAME
|
|
139
|
+
// // =========================
|
|
140
|
+
// const pluginName =
|
|
141
|
+
// metadata?.name ||
|
|
142
|
+
// source
|
|
143
|
+
// .replace("github:", "")
|
|
144
|
+
// .split("/")
|
|
145
|
+
// .pop()
|
|
146
|
+
// .replace(".js", "");
|
|
147
|
+
|
|
148
|
+
// const filePath = path.join(pluginsDir, `${pluginName}.js`);
|
|
149
|
+
|
|
150
|
+
// // =========================
|
|
151
|
+
// // SAVE PLUGIN CODE
|
|
152
|
+
// // =========================
|
|
153
|
+
// fs.writeFileSync(filePath, code);
|
|
154
|
+
|
|
155
|
+
// // =========================
|
|
156
|
+
// // SAVE METADATA
|
|
157
|
+
// // =========================
|
|
158
|
+
// if (metadata) {
|
|
159
|
+
// fs.writeJSONSync(
|
|
160
|
+
// path.join(pluginsDir, `${pluginName}.json`),
|
|
161
|
+
// metadata,
|
|
162
|
+
// { spaces: 2 }
|
|
163
|
+
// );
|
|
164
|
+
// }
|
|
165
|
+
|
|
166
|
+
// console.log(`ā
Plugin installed: ${pluginName}`);
|
|
167
|
+
// console.log(`š Saved to plugins/${pluginName}.js`);
|
|
168
|
+
|
|
169
|
+
// if (metadata) {
|
|
170
|
+
// console.log(`š Metadata saved: plugins/${pluginName}.json`);
|
|
171
|
+
// }
|
|
172
|
+
|
|
173
|
+
// } catch (err) {
|
|
174
|
+
// console.log("ā Install failed");
|
|
175
|
+
// console.log(err.message);
|
|
176
|
+
// }
|
|
177
|
+
// });
|
|
178
|
+
// };
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
const fs = require("fs-extra");
|
|
187
|
+
const path = require("path");
|
|
188
|
+
const axios = require("axios");
|
|
189
|
+
|
|
190
|
+
module.exports = function (program) {
|
|
191
|
+
program
|
|
192
|
+
.command("install <type> <source>")
|
|
193
|
+
.description("Install plugins from registry")
|
|
194
|
+
.action(async (type, source) => {
|
|
195
|
+
|
|
196
|
+
if (type !== "plugin") {
|
|
197
|
+
console.log("ā Only 'plugin' installs supported for now");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
console.log(`š¦ Installing plugin: ${source}`);
|
|
203
|
+
|
|
204
|
+
let version = "latest";
|
|
205
|
+
|
|
206
|
+
if (source.includes("@")) {
|
|
207
|
+
const parts = source.split("@");
|
|
208
|
+
source = parts[0];
|
|
209
|
+
version = parts[1];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// -------------------------
|
|
213
|
+
// REGISTRY ONLY
|
|
214
|
+
// -------------------------
|
|
215
|
+
console.log(`š¦ Resolving "${source}" from registry...`);
|
|
216
|
+
|
|
217
|
+
const res = await axios.get(
|
|
218
|
+
`http://127.0.0.1:8000/api/cli/plugins/search?q=${source}`
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const plugin = res.data?.[0];
|
|
222
|
+
|
|
223
|
+
if (!plugin) {
|
|
224
|
+
console.log("ā Plugin not found in registry");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (!plugin.code) {
|
|
229
|
+
console.log("ā Plugin has no code field");
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// -------------------------
|
|
234
|
+
// ENSURE PLUGINS DIR
|
|
235
|
+
// -------------------------
|
|
236
|
+
const pluginsDir = path.join(process.cwd(), "plugins");
|
|
237
|
+
fs.ensureDirSync(pluginsDir);
|
|
238
|
+
|
|
239
|
+
// -------------------------
|
|
240
|
+
// SAVE FILE
|
|
241
|
+
// -------------------------
|
|
242
|
+
const filePath = path.join(pluginsDir, `${plugin.name}.js`);
|
|
243
|
+
|
|
244
|
+
fs.writeFileSync(filePath, plugin.code);
|
|
245
|
+
|
|
246
|
+
console.log(`ā
Plugin installed: ${plugin.name}`);
|
|
247
|
+
console.log(`š Saved to plugins/${plugin.name}.js`);
|
|
248
|
+
|
|
249
|
+
} catch (err) {
|
|
250
|
+
console.log("ā Install failed");
|
|
251
|
+
console.log(err.message);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
};
|
package/commands/link.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const fs = require("fs-extra");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { getConfig, saveConfig } = require("../lib/config");
|
|
4
|
+
|
|
5
|
+
module.exports = function (program) {
|
|
6
|
+
program
|
|
7
|
+
.command("link")
|
|
8
|
+
.description("Link current folder to a project")
|
|
9
|
+
.action(async () => {
|
|
10
|
+
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
|
|
13
|
+
if (!config.projects) {
|
|
14
|
+
console.log("ā Run: justalk projects first");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log("\nš¦ Available projects:\n");
|
|
19
|
+
|
|
20
|
+
config.projects.forEach(p => {
|
|
21
|
+
console.log(`${p.id}. ${p.name} (${p.slug})`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log("\nš Linking project 1 for demo...\n");
|
|
25
|
+
|
|
26
|
+
const project = config.projects[0];
|
|
27
|
+
|
|
28
|
+
const linkFile = {
|
|
29
|
+
project_id: project.id,
|
|
30
|
+
project_slug: project.slug
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
fs.writeJSONSync(path.join(process.cwd(), ".justalk.json"), linkFile, {
|
|
34
|
+
spaces: 2
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
saveConfig({
|
|
38
|
+
...config,
|
|
39
|
+
active_project: project.id
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log("ā
Project linked:");
|
|
43
|
+
console.log(project.name);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const readline = require("readline");
|
|
2
|
+
const { apiPost } = require("../lib/api");
|
|
3
|
+
const { saveConfig } = require("../lib/config");
|
|
4
|
+
|
|
5
|
+
// --------------------
|
|
6
|
+
// LOGIN COMMAND
|
|
7
|
+
// --------------------
|
|
8
|
+
|
|
9
|
+
module.exports = function (program) {
|
|
10
|
+
program
|
|
11
|
+
.command("login")
|
|
12
|
+
.description("Login to your Laravel API (CLI)")
|
|
13
|
+
.action(async () => {
|
|
14
|
+
|
|
15
|
+
const rl = readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const ask = (q) =>
|
|
21
|
+
new Promise(resolve => rl.question(q, resolve));
|
|
22
|
+
|
|
23
|
+
const email = await ask("Email: ");
|
|
24
|
+
const password = await ask("Password: ");
|
|
25
|
+
|
|
26
|
+
rl.close();
|
|
27
|
+
|
|
28
|
+
console.log("\nš Logging in...\n");
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const res = await apiPost("/api/cli/login", {
|
|
32
|
+
email,
|
|
33
|
+
password
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const apiKey = res.data.api_key;
|
|
37
|
+
|
|
38
|
+
if (!apiKey) {
|
|
39
|
+
throw new Error("API key not returned from server");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
saveConfig({
|
|
43
|
+
api_key: apiKey
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log("ā
Login successful!");
|
|
47
|
+
console.log("š API key saved locally.");
|
|
48
|
+
console.log(apiKey);
|
|
49
|
+
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.log("ā Login failed");
|
|
52
|
+
console.log(err.response?.data || err.message);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getConfig,
|
|
3
|
+
saveConfig
|
|
4
|
+
} = require("../lib/config");
|
|
5
|
+
|
|
6
|
+
module.exports = function (program) {
|
|
7
|
+
program
|
|
8
|
+
.command("logout")
|
|
9
|
+
.description("Log out and clear saved credentials")
|
|
10
|
+
.action(() => {
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
|
|
13
|
+
saveConfig({
|
|
14
|
+
env: config.env || "dev"
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log("ā
Logged out successfully.");
|
|
18
|
+
console.log("š Token, API key, and active project removed.");
|
|
19
|
+
});
|
|
20
|
+
};
|
package/commands/logs.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { apiGet } = require("../lib/api");
|
|
2
|
+
|
|
3
|
+
module.exports = function (program) {
|
|
4
|
+
program
|
|
5
|
+
.command("logs")
|
|
6
|
+
.description("Show deployment history")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
console.log("š Loading deployments...\n");
|
|
11
|
+
|
|
12
|
+
const res = await apiGet("/api/cli/deployments");
|
|
13
|
+
|
|
14
|
+
const logs = res.data;
|
|
15
|
+
|
|
16
|
+
logs.forEach((log) => {
|
|
17
|
+
console.log(
|
|
18
|
+
`#${log.id} | Project ${log.project_id} | ${log.env} | ${log.status} | ${log.created_at}`
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.log("ā Failed to load logs");
|
|
24
|
+
console.log(err.response?.data || err.message);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|