@instafy/cli 0.1.8-staging.372 → 0.1.8-staging.374
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/project.js +74 -64
- package/package.json +2 -1
package/dist/project.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import kleur from "kleur";
|
|
4
|
-
import {
|
|
5
|
-
import { stdin as input, stdout as output } from "node:process";
|
|
4
|
+
import { stdin as input } from "node:process";
|
|
6
5
|
import { getInstafyProfileConfigPath, resolveConfiguredStudioUrl, resolveControllerUrl, resolveUserAccessToken, } from "./config.js";
|
|
7
6
|
import { formatAuthRequiredError } from "./errors.js";
|
|
8
7
|
import { findProjectManifest } from "./project-manifest.js";
|
|
8
|
+
let promptsModule = null;
|
|
9
|
+
async function loadPrompts() {
|
|
10
|
+
promptsModule ?? (promptsModule = import("@clack/prompts"));
|
|
11
|
+
return promptsModule;
|
|
12
|
+
}
|
|
9
13
|
async function fetchOrganizations(controllerUrl, token) {
|
|
10
14
|
const response = await fetch(`${controllerUrl}/orgs`, {
|
|
11
15
|
headers: {
|
|
@@ -60,19 +64,32 @@ async function resolveOrg(controllerUrl, token, options) {
|
|
|
60
64
|
const orgName = options.orgName?.trim() || null;
|
|
61
65
|
const studioUrl = resolveConfiguredStudioUrl({ profile: options.profile ?? null }) ?? "https://staging.instafy.dev";
|
|
62
66
|
const studioOrgUrl = `${studioUrl.replace(/\/$/, "")}/studio?panel=settings`;
|
|
63
|
-
const allowInteractive = input.isTTY && options.json !== true;
|
|
64
|
-
async function promptAndCreateOrg(
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
|
|
67
|
+
const allowInteractive = Boolean(input.isTTY && process.stdout.isTTY && options.json !== true && process.env.CI !== "true");
|
|
68
|
+
async function promptAndCreateOrg() {
|
|
69
|
+
const { isCancel, text } = await loadPrompts();
|
|
70
|
+
const enteredName = await text({
|
|
71
|
+
message: "Organization name",
|
|
72
|
+
defaultValue: "Personal",
|
|
73
|
+
});
|
|
74
|
+
if (isCancel(enteredName)) {
|
|
75
|
+
throw new Error("Cancelled.");
|
|
76
|
+
}
|
|
77
|
+
const chosenName = String(enteredName).trim() || "Personal";
|
|
78
|
+
const enteredSlug = await text({
|
|
79
|
+
message: "Organization slug (optional)",
|
|
80
|
+
});
|
|
81
|
+
if (isCancel(enteredSlug)) {
|
|
82
|
+
throw new Error("Cancelled.");
|
|
83
|
+
}
|
|
84
|
+
const chosenSlug = String(enteredSlug).trim();
|
|
68
85
|
const payload = {
|
|
69
86
|
orgName: chosenName,
|
|
70
87
|
};
|
|
71
88
|
if (options.ownerUserId) {
|
|
72
89
|
payload.ownerUserId = options.ownerUserId;
|
|
73
90
|
}
|
|
74
|
-
if (
|
|
75
|
-
payload.orgSlug =
|
|
91
|
+
if (chosenSlug) {
|
|
92
|
+
payload.orgSlug = chosenSlug;
|
|
76
93
|
}
|
|
77
94
|
const created = await createOrganization(controllerUrl, token, payload);
|
|
78
95
|
return { orgId: created.orgId, orgName: created.orgName ?? chosenName };
|
|
@@ -88,80 +105,73 @@ async function resolveOrg(controllerUrl, token, options) {
|
|
|
88
105
|
const orgs = await fetchOrganizations(controllerUrl, token);
|
|
89
106
|
if (orgs.length === 0) {
|
|
90
107
|
if (allowInteractive) {
|
|
108
|
+
const { confirm, isCancel } = await loadPrompts();
|
|
91
109
|
console.log(kleur.yellow("No organizations found for this account."));
|
|
92
110
|
console.log("");
|
|
93
111
|
console.log(`Create one in Studio: ${kleur.cyan(studioOrgUrl)}`);
|
|
94
112
|
console.log("");
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return await promptAndCreateOrg(rl);
|
|
102
|
-
}
|
|
103
|
-
finally {
|
|
104
|
-
rl.close();
|
|
113
|
+
const shouldCreate = await confirm({
|
|
114
|
+
message: "Create a new organization now?",
|
|
115
|
+
initialValue: true,
|
|
116
|
+
});
|
|
117
|
+
if (isCancel(shouldCreate) || !shouldCreate) {
|
|
118
|
+
throw new Error("No organization selected.");
|
|
105
119
|
}
|
|
120
|
+
return await promptAndCreateOrg();
|
|
106
121
|
}
|
|
107
122
|
throw new Error(`No organizations found.\n\nNext:\n- Create an org in Studio: ${studioOrgUrl}\n- Or rerun: instafy project init --org-name \"My Org\"`);
|
|
108
123
|
}
|
|
124
|
+
if (orgs.length === 1) {
|
|
125
|
+
return { orgId: orgs[0].id, orgName: orgs[0].name ?? null };
|
|
126
|
+
}
|
|
109
127
|
if (allowInteractive) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
128
|
+
const { isCancel, select } = await loadPrompts();
|
|
129
|
+
const selection = await select({
|
|
130
|
+
message: "Choose an organization for this project",
|
|
131
|
+
options: [
|
|
132
|
+
{ value: "__create__", label: "+ Create a new organization" },
|
|
133
|
+
...orgs.map((org) => ({
|
|
134
|
+
value: org.id,
|
|
135
|
+
label: org.name,
|
|
136
|
+
hint: `${org.slug ? `${org.slug} · ` : ""}${org.id}`,
|
|
137
|
+
})),
|
|
138
|
+
],
|
|
139
|
+
initialValue: orgs[0].id,
|
|
115
140
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
while (true) {
|
|
120
|
-
const answer = (await rl.question("Select org number (default 1): ")).trim();
|
|
121
|
-
if (!answer) {
|
|
122
|
-
const picked = orgs[0];
|
|
123
|
-
return { orgId: picked.id, orgName: picked.name ?? null };
|
|
124
|
-
}
|
|
125
|
-
const selected = Number(answer);
|
|
126
|
-
if (selected === 0) {
|
|
127
|
-
return await promptAndCreateOrg(rl);
|
|
128
|
-
}
|
|
129
|
-
if (!Number.isFinite(selected) || selected < 1 || selected > orgs.length) {
|
|
130
|
-
console.log(kleur.red("Invalid selection."));
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
const picked = orgs[selected - 1];
|
|
134
|
-
return { orgId: picked.id, orgName: picked.name ?? null };
|
|
135
|
-
}
|
|
141
|
+
if (isCancel(selection)) {
|
|
142
|
+
throw new Error("Cancelled.");
|
|
136
143
|
}
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
if (selection === "__create__") {
|
|
145
|
+
return await promptAndCreateOrg();
|
|
139
146
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
const pickedOrg = orgs.find((org) => org.id === selection);
|
|
148
|
+
if (!pickedOrg) {
|
|
149
|
+
throw new Error("Selected organization not found.");
|
|
150
|
+
}
|
|
151
|
+
return { orgId: pickedOrg.id, orgName: pickedOrg.name ?? null };
|
|
143
152
|
}
|
|
144
153
|
throw new Error("Multiple organizations found.\n\nNext:\n- instafy org list\n- instafy project init --org-id <uuid>");
|
|
145
154
|
}
|
|
146
155
|
if (orgSlug && !orgName) {
|
|
147
156
|
if (allowInteractive) {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
const created = await createOrganization(controllerUrl, token, payload);
|
|
160
|
-
return { orgId: created.orgId, orgName: created.orgName ?? chosenName };
|
|
157
|
+
const { isCancel, text } = await loadPrompts();
|
|
158
|
+
console.log(kleur.yellow("Organization slug did not match an existing org."));
|
|
159
|
+
console.log(`Create one in Studio: ${kleur.cyan(studioOrgUrl)}`);
|
|
160
|
+
console.log("");
|
|
161
|
+
const enteredName = await text({
|
|
162
|
+
message: "Organization name",
|
|
163
|
+
defaultValue: "Personal",
|
|
164
|
+
});
|
|
165
|
+
if (isCancel(enteredName)) {
|
|
166
|
+
throw new Error("Cancelled.");
|
|
161
167
|
}
|
|
162
|
-
|
|
163
|
-
|
|
168
|
+
const chosenName = String(enteredName).trim() || "Personal";
|
|
169
|
+
const payload = { orgName: chosenName, orgSlug };
|
|
170
|
+
if (options.ownerUserId) {
|
|
171
|
+
payload.ownerUserId = options.ownerUserId;
|
|
164
172
|
}
|
|
173
|
+
const created = await createOrganization(controllerUrl, token, payload);
|
|
174
|
+
return { orgId: created.orgId, orgName: created.orgName ?? chosenName };
|
|
165
175
|
}
|
|
166
176
|
throw new Error(`Organization slug "${orgSlug}" did not match an existing org, and org name is required to create one.\n\nNext:\n- Create an org in Studio: ${studioOrgUrl}\n- Or rerun: instafy project init --org-name \"My Org\" --org-slug "${orgSlug}"`);
|
|
167
177
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instafy/cli",
|
|
3
|
-
"version": "0.1.8-staging.
|
|
3
|
+
"version": "0.1.8-staging.374",
|
|
4
4
|
"description": "Run Instafy projects locally, link folders to Studio, and share previews/webhooks via tunnels.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test:live": "pnpm build && TUNNEL_E2E_LIVE=1 vitest run test/tunnel-live.e2e.spec.ts"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@clack/prompts": "^0.11.0",
|
|
27
28
|
"commander": "^12.1.0",
|
|
28
29
|
"kleur": "^4.1.5"
|
|
29
30
|
},
|