@apso/cli 0.24.0 → 0.25.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.
- package/dist/commands/deploy.js +24 -2
- package/dist/commands/init.js +59 -26
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -140,9 +140,31 @@ class Deploy extends base_command_1.default {
|
|
|
140
140
|
git.initRepo(cwd);
|
|
141
141
|
// Pick the repo: prefer what the local project is already wired to, then the
|
|
142
142
|
// service's connected repo, then --repo, then ask.
|
|
143
|
-
|
|
143
|
+
let conn = await services_1.githubApi.getConnection();
|
|
144
144
|
if (!conn.connected || !conn.connectionId) {
|
|
145
|
-
|
|
145
|
+
// Connecting GitHub is a browser OAuth flow a machine can't complete.
|
|
146
|
+
// Headless: fail with instructions. Interactive: offer to launch it now
|
|
147
|
+
// (opens the browser), wait for the human, then continue the deploy.
|
|
148
|
+
if (!(0, interactive_1.isInteractive)()) {
|
|
149
|
+
this.error("GitHub is not connected. Run 'apso github connect' first, then re-run deploy.");
|
|
150
|
+
}
|
|
151
|
+
const inquirer = await Promise.resolve().then(() => tslib_1.__importStar(require("inquirer")));
|
|
152
|
+
const { connectNow } = await inquirer.default.prompt([
|
|
153
|
+
{
|
|
154
|
+
type: "confirm",
|
|
155
|
+
name: "connectNow",
|
|
156
|
+
message: "GitHub is not connected (required to push code). Connect now? This opens your browser.",
|
|
157
|
+
default: true,
|
|
158
|
+
},
|
|
159
|
+
]);
|
|
160
|
+
if (!connectNow) {
|
|
161
|
+
this.error("GitHub connection is required to deploy. Run 'apso github connect' when ready, then re-run deploy.");
|
|
162
|
+
}
|
|
163
|
+
await this.config.runCommand("github:connect", []);
|
|
164
|
+
conn = await services_1.githubApi.getConnection();
|
|
165
|
+
if (!conn.connected || !conn.connectionId) {
|
|
166
|
+
this.error("GitHub still isn't connected. Complete 'apso github connect' and re-run deploy.");
|
|
167
|
+
}
|
|
146
168
|
}
|
|
147
169
|
let repoFullName = git.localRepoFullName(cwd) || service.githubRepo || repoFlag;
|
|
148
170
|
if (!repoFullName) {
|
package/dist/commands/init.js
CHANGED
|
@@ -10,6 +10,8 @@ const base_command_1 = tslib_1.__importDefault(require("../lib/base-command"));
|
|
|
10
10
|
const config_1 = require("../lib/config");
|
|
11
11
|
const services_1 = require("../lib/api/services");
|
|
12
12
|
const upgrade_1 = require("../lib/upgrade");
|
|
13
|
+
const interactive_1 = require("../lib/utils/interactive");
|
|
14
|
+
const config_2 = require("../lib/config");
|
|
13
15
|
const template_1 = require("../lib/utils/template");
|
|
14
16
|
class Init extends base_command_1.default {
|
|
15
17
|
async run() {
|
|
@@ -28,18 +30,28 @@ class Init extends base_command_1.default {
|
|
|
28
30
|
await (isAuthenticated ? this.runAuthenticated(flags) : this.runOffline(flags));
|
|
29
31
|
}
|
|
30
32
|
async runAuthenticated(flags) {
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
// Headless: init is the guided human path; require the essentials up-front so
|
|
34
|
+
// no prompt is reached. Agents should prefer 'apso generate' + 'apso link --create'.
|
|
35
|
+
if (!(0, interactive_1.isInteractive)() && (!flags.name || !flags.language)) {
|
|
36
|
+
this.error((0, interactive_1.missingFlag)("apso init needs --name and --language non-interactively (or use 'apso generate' + 'apso link --create')."));
|
|
37
|
+
}
|
|
38
|
+
// Ask: create new or clone existing. Headless: default to "create" (the
|
|
39
|
+
// scaffold path); requires --name/--language, which createNew enforces.
|
|
40
|
+
let action = "create";
|
|
41
|
+
if ((0, interactive_1.isInteractive)()) {
|
|
42
|
+
const answer = await inquirer_1.default.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: "list",
|
|
45
|
+
name: "action",
|
|
46
|
+
message: "What would you like to do?",
|
|
47
|
+
choices: [
|
|
48
|
+
{ name: "Create a new project", value: "create" },
|
|
49
|
+
{ name: "Clone an existing project", value: "clone" },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
action = answer.action;
|
|
54
|
+
}
|
|
43
55
|
await (action === "clone" ? this.cloneExisting() : this.createNew(flags));
|
|
44
56
|
}
|
|
45
57
|
async cloneExisting() {
|
|
@@ -158,26 +170,41 @@ class Init extends base_command_1.default {
|
|
|
158
170
|
if (!resolvedPath.startsWith(path.resolve(process.cwd()))) {
|
|
159
171
|
this.error("Invalid project name: path traversal detected");
|
|
160
172
|
}
|
|
161
|
-
// Select workspace
|
|
173
|
+
// Select workspace: active workspace (apso use), else prompt (interactive),
|
|
174
|
+
// else error headless.
|
|
162
175
|
const workspaces = await services_1.workspacesApi.list();
|
|
163
176
|
if (workspaces.length === 0) {
|
|
164
177
|
this.error("No workspaces found. Create a workspace at https://app.apso.cloud first.");
|
|
165
178
|
}
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
const activeSlug = config_2.globalConfig.read().activeWorkspaceSlug;
|
|
180
|
+
let workspace = activeSlug
|
|
181
|
+
? workspaces.find((w) => w.slug === activeSlug)
|
|
182
|
+
: undefined;
|
|
183
|
+
if (!workspace) {
|
|
184
|
+
if (!(0, interactive_1.isInteractive)()) {
|
|
185
|
+
this.error((0, interactive_1.missingFlag)("Set a workspace first with 'apso use <slug>'."));
|
|
186
|
+
}
|
|
187
|
+
const answer = await inquirer_1.default.prompt([
|
|
188
|
+
{
|
|
189
|
+
type: "list",
|
|
190
|
+
name: "workspace",
|
|
191
|
+
message: "Select a workspace:",
|
|
192
|
+
choices: workspaces.map((ws) => ({
|
|
193
|
+
name: `${ws.name} (${ws.slug})`,
|
|
194
|
+
value: ws,
|
|
195
|
+
})),
|
|
196
|
+
},
|
|
197
|
+
]);
|
|
198
|
+
workspace = answer.workspace;
|
|
199
|
+
}
|
|
200
|
+
if (!workspace) {
|
|
201
|
+
throw new Error("No workspace selected.");
|
|
202
|
+
}
|
|
203
|
+
const ws = workspace;
|
|
177
204
|
// Create service on platform
|
|
178
|
-
this.log(`Creating service "${projectName}" in workspace "${
|
|
205
|
+
this.log(`Creating service "${projectName}" in workspace "${ws.name}"...`);
|
|
179
206
|
const serviceName = projectName;
|
|
180
|
-
const service = await (0, upgrade_1.withUpgradeRetry)(() => services_1.servicesApi.create(
|
|
207
|
+
const service = await (0, upgrade_1.withUpgradeRetry)(() => services_1.servicesApi.create(ws.id, {
|
|
181
208
|
name: serviceName,
|
|
182
209
|
}));
|
|
183
210
|
// Clone template
|
|
@@ -196,6 +223,12 @@ class Init extends base_command_1.default {
|
|
|
196
223
|
this.log(`\nProject created at ${projectPath}`);
|
|
197
224
|
this.log(`Language: ${language}`);
|
|
198
225
|
this.log(`Linked to workspace "${workspace.name}" / service "${service.name}"`);
|
|
226
|
+
this.log("");
|
|
227
|
+
this.log("Next steps:");
|
|
228
|
+
this.log(` cd ${projectName}`);
|
|
229
|
+
this.log(" # edit .apsorc to shape your schema, then:");
|
|
230
|
+
this.log(" apso generate # scaffold code from the schema");
|
|
231
|
+
this.log(" apso deploy # ship it (prompts to connect GitHub if needed)");
|
|
199
232
|
}
|
|
200
233
|
async runOffline(flags) {
|
|
201
234
|
// Prompt for name if not provided
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apso/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@apso/cli",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.25.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@biomejs/biome": "^1.9.4",
|
package/oclif.manifest.json
CHANGED