@instafy/cli 0.1.7 → 0.1.8-staging.350
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/README.md +7 -1
- package/dist/api.js +3 -1
- package/dist/auth.js +112 -0
- package/dist/config-command.js +104 -0
- package/dist/config.js +111 -0
- package/dist/errors.js +10 -0
- package/dist/git-credential.js +201 -0
- package/dist/git-setup.js +56 -0
- package/dist/git.js +4 -1
- package/dist/index.js +286 -41
- package/dist/org.js +5 -18
- package/dist/project.js +11 -24
- package/dist/runtime.js +266 -57
- package/dist/tunnel.js +300 -13
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -2,11 +2,14 @@ import { Command, Option } from "commander";
|
|
|
2
2
|
import { pathToFileURL } from "node:url";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import kleur from "kleur";
|
|
5
|
-
import { runtimeStart, runtimeStatus, runtimeStop, runtimeToken, } from "./runtime.js";
|
|
5
|
+
import { runtimeStart, runtimeStatus, runtimeStop, runtimeToken, findProjectManifest, } from "./runtime.js";
|
|
6
|
+
import { login, logout } from "./auth.js";
|
|
6
7
|
import { gitToken } from "./git.js";
|
|
8
|
+
import { runGitCredentialHelper } from "./git-credential.js";
|
|
7
9
|
import { projectInit } from "./project.js";
|
|
8
|
-
import { runTunnelCommand } from "./tunnel.js";
|
|
10
|
+
import { listTunnelSessions, startTunnelDetached, stopTunnelSession, tailTunnelLogs, runTunnelCommand } from "./tunnel.js";
|
|
9
11
|
import { requestControllerApi } from "./api.js";
|
|
12
|
+
import { configGet, configList, configPath, configSet, configUnset } from "./config-command.js";
|
|
10
13
|
export const program = new Command();
|
|
11
14
|
const require = createRequire(import.meta.url);
|
|
12
15
|
const pkg = require("../package.json");
|
|
@@ -32,6 +35,146 @@ program
|
|
|
32
35
|
.name("instafy")
|
|
33
36
|
.description("Instafy CLI — run your project locally and connect to Studio")
|
|
34
37
|
.version(pkg.version ?? "0.1.0");
|
|
38
|
+
program
|
|
39
|
+
.command("login")
|
|
40
|
+
.description("Log in and save an access token for future CLI commands")
|
|
41
|
+
.option("--studio-url <url>", "Studio web URL (default: staging or localhost)")
|
|
42
|
+
.option("--server-url <url>", "Instafy server/controller URL")
|
|
43
|
+
.option("--token <token>", "Provide token directly (skips prompt)")
|
|
44
|
+
.option("--no-git-setup", "Do not configure git credential helper")
|
|
45
|
+
.option("--no-store", "Do not save token to ~/.instafy/config.json")
|
|
46
|
+
.option("--json", "Output JSON")
|
|
47
|
+
.action(async (opts) => {
|
|
48
|
+
try {
|
|
49
|
+
await login({
|
|
50
|
+
controllerUrl: opts.serverUrl,
|
|
51
|
+
studioUrl: opts.studioUrl,
|
|
52
|
+
token: opts.token,
|
|
53
|
+
gitSetup: opts.gitSetup,
|
|
54
|
+
noStore: opts.store === false,
|
|
55
|
+
json: opts.json,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error(kleur.red(String(error)));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
program
|
|
64
|
+
.command("logout")
|
|
65
|
+
.description("Clear the saved CLI access token")
|
|
66
|
+
.option("--json", "Output JSON")
|
|
67
|
+
.action(async (opts) => {
|
|
68
|
+
try {
|
|
69
|
+
await logout({ json: opts.json });
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error(kleur.red(String(error)));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
const projectInitCommand = program
|
|
77
|
+
.command("project:init")
|
|
78
|
+
.description("Create an Instafy project and link this folder (.instafy/project.json)")
|
|
79
|
+
.option("--path <dir>", "Directory where the manifest should be written (default: cwd)");
|
|
80
|
+
addServerUrlOptions(projectInitCommand);
|
|
81
|
+
projectInitCommand
|
|
82
|
+
.option("--access-token <token>", "Instafy or Supabase access token")
|
|
83
|
+
.option("--project-type <type>", "Project type (customer|sandbox)")
|
|
84
|
+
.option("--org-id <uuid>", "Optional organization id")
|
|
85
|
+
.option("--org-name <name>", "Optional organization name")
|
|
86
|
+
.option("--org-slug <slug>", "Optional organization slug")
|
|
87
|
+
.option("--owner-user-id <uuid>", "Explicit owner user id (defaults to caller)")
|
|
88
|
+
.option("--json", "Output JSON")
|
|
89
|
+
.action(async (opts) => {
|
|
90
|
+
try {
|
|
91
|
+
await projectInit({
|
|
92
|
+
path: opts.path,
|
|
93
|
+
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
94
|
+
accessToken: opts.accessToken,
|
|
95
|
+
projectType: opts.projectType,
|
|
96
|
+
orgId: opts.orgId,
|
|
97
|
+
orgName: opts.orgName,
|
|
98
|
+
orgSlug: opts.orgSlug,
|
|
99
|
+
ownerUserId: opts.ownerUserId,
|
|
100
|
+
json: opts.json,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error(kleur.red(String(error)));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
const configCommand = program.command("config").description("Get/set saved CLI configuration");
|
|
109
|
+
configCommand
|
|
110
|
+
.command("path")
|
|
111
|
+
.description("Print the config file path")
|
|
112
|
+
.option("--json", "Output JSON")
|
|
113
|
+
.action(async (opts) => {
|
|
114
|
+
try {
|
|
115
|
+
configPath({ json: opts.json });
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error(kleur.red(String(error)));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
configCommand
|
|
123
|
+
.command("list")
|
|
124
|
+
.description("List saved configuration")
|
|
125
|
+
.option("--json", "Output JSON")
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
try {
|
|
128
|
+
configList({ json: opts.json });
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error(kleur.red(String(error)));
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
configCommand
|
|
136
|
+
.command("get")
|
|
137
|
+
.description("Get a config value (controller-url, studio-url)")
|
|
138
|
+
.argument("<key>", "Config key")
|
|
139
|
+
.option("--json", "Output JSON")
|
|
140
|
+
.action(async (key, opts) => {
|
|
141
|
+
try {
|
|
142
|
+
configGet({ key, json: opts.json });
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error(kleur.red(String(error)));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
configCommand
|
|
150
|
+
.command("set")
|
|
151
|
+
.description("Set a config value (controller-url, studio-url)")
|
|
152
|
+
.argument("<key>", "Config key")
|
|
153
|
+
.argument("<value>", "Config value")
|
|
154
|
+
.option("--json", "Output JSON")
|
|
155
|
+
.action(async (key, value, opts) => {
|
|
156
|
+
try {
|
|
157
|
+
configSet({ key, value, json: opts.json });
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.error(kleur.red(String(error)));
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
configCommand
|
|
165
|
+
.command("unset")
|
|
166
|
+
.description("Unset a config value (controller-url, studio-url)")
|
|
167
|
+
.argument("<key>", "Config key")
|
|
168
|
+
.option("--json", "Output JSON")
|
|
169
|
+
.action(async (key, opts) => {
|
|
170
|
+
try {
|
|
171
|
+
configUnset({ key, json: opts.json });
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error(kleur.red(String(error)));
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
35
178
|
const runtimeStartCommand = program
|
|
36
179
|
.command("runtime:start")
|
|
37
180
|
.description("Start a local runtime for this project")
|
|
@@ -46,6 +189,7 @@ runtimeStartCommand
|
|
|
46
189
|
.option("--codex-bin <path>", "Path to codex binary (fallback to PATH)")
|
|
47
190
|
.option("--proxy-base-url <url>", "Codex proxy base URL")
|
|
48
191
|
.option("--workspace <path>", "Workspace directory (defaults to ./.instafy/workspace)")
|
|
192
|
+
.option("--runtime-mode <mode>", "Runtime runner (auto|docker|process)", "auto")
|
|
49
193
|
.option("--origin-id <uuid>", "Origin ID to use (auto-generated if omitted)")
|
|
50
194
|
.option("--origin-endpoint <url>", "Explicit origin endpoint (skip tunnel setup when provided)")
|
|
51
195
|
.option("--origin-token <token>", "Runtime/origin access token for Studio registration")
|
|
@@ -100,7 +244,7 @@ program
|
|
|
100
244
|
const runtimeTokenCommand = program
|
|
101
245
|
.command("runtime:token")
|
|
102
246
|
.description("Mint a runtime access token")
|
|
103
|
-
.
|
|
247
|
+
.option("--project <id>", "Project UUID (defaults to .instafy/project.json)");
|
|
104
248
|
addServerUrlOptions(runtimeTokenCommand);
|
|
105
249
|
addAccessTokenOptions(runtimeTokenCommand, "Instafy access token (required)");
|
|
106
250
|
runtimeTokenCommand
|
|
@@ -109,8 +253,14 @@ runtimeTokenCommand
|
|
|
109
253
|
.option("--json", "Output token as JSON")
|
|
110
254
|
.action(async (opts) => {
|
|
111
255
|
try {
|
|
256
|
+
const project = typeof opts.project === "string" && opts.project.trim()
|
|
257
|
+
? opts.project.trim()
|
|
258
|
+
: findProjectManifest(process.cwd()).manifest?.projectId ?? null;
|
|
259
|
+
if (!project) {
|
|
260
|
+
throw new Error("No project configured. Run `instafy project:init` or pass --project.");
|
|
261
|
+
}
|
|
112
262
|
await runtimeToken({
|
|
113
|
-
project
|
|
263
|
+
project,
|
|
114
264
|
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
115
265
|
controllerAccessToken: opts.accessToken ?? opts.controllerAccessToken,
|
|
116
266
|
runtimeId: opts.runtimeId,
|
|
@@ -126,7 +276,7 @@ runtimeTokenCommand
|
|
|
126
276
|
const gitTokenCommand = program
|
|
127
277
|
.command("git:token")
|
|
128
278
|
.description("Mint a git access token for the project repo")
|
|
129
|
-
.
|
|
279
|
+
.option("--project <id>", "Project UUID (defaults to .instafy/project.json)");
|
|
130
280
|
addServerUrlOptions(gitTokenCommand);
|
|
131
281
|
addAccessTokenOptions(gitTokenCommand, "Instafy access token (required)");
|
|
132
282
|
gitTokenCommand
|
|
@@ -137,13 +287,19 @@ gitTokenCommand
|
|
|
137
287
|
.option("--json", "Output token response as JSON")
|
|
138
288
|
.action(async (opts) => {
|
|
139
289
|
try {
|
|
290
|
+
const project = typeof opts.project === "string" && opts.project.trim()
|
|
291
|
+
? opts.project.trim()
|
|
292
|
+
: findProjectManifest(process.cwd()).manifest?.projectId ?? null;
|
|
293
|
+
if (!project) {
|
|
294
|
+
throw new Error("No project configured. Run `instafy project:init` or pass --project.");
|
|
295
|
+
}
|
|
140
296
|
const ttlSecondsRaw = typeof opts.ttlSeconds === "string" ? opts.ttlSeconds.trim() : "";
|
|
141
297
|
const ttlSeconds = ttlSecondsRaw.length > 0 ? Number.parseInt(ttlSecondsRaw, 10) : undefined;
|
|
142
298
|
if (ttlSecondsRaw.length > 0 && (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0)) {
|
|
143
299
|
throw new Error("--ttl-seconds must be a positive integer");
|
|
144
300
|
}
|
|
145
301
|
await gitToken({
|
|
146
|
-
project
|
|
302
|
+
project,
|
|
147
303
|
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
148
304
|
controllerAccessToken: opts.accessToken ?? opts.controllerAccessToken,
|
|
149
305
|
supabaseAccessToken: opts.supabaseAccessToken,
|
|
@@ -158,56 +314,145 @@ gitTokenCommand
|
|
|
158
314
|
process.exit(1);
|
|
159
315
|
}
|
|
160
316
|
});
|
|
161
|
-
|
|
162
|
-
.command("
|
|
163
|
-
.description("
|
|
164
|
-
.
|
|
165
|
-
|
|
166
|
-
projectInitCommand
|
|
167
|
-
.option("--access-token <token>", "Instafy or Supabase access token")
|
|
168
|
-
.option("--project-type <type>", "Project type (customer|sandbox)")
|
|
169
|
-
.option("--org-id <uuid>", "Optional organization id")
|
|
170
|
-
.option("--org-name <name>", "Optional organization name")
|
|
171
|
-
.option("--org-slug <slug>", "Optional organization slug")
|
|
172
|
-
.option("--owner-user-id <uuid>", "Explicit owner user id (defaults to caller)")
|
|
173
|
-
.option("--json", "Output JSON")
|
|
174
|
-
.action(async (opts) => {
|
|
317
|
+
program
|
|
318
|
+
.command("git:credential", { hidden: true })
|
|
319
|
+
.description("Internal: git credential helper (used by Git when configured)")
|
|
320
|
+
.argument("<operation>", "Operation (get|store|erase)")
|
|
321
|
+
.action(async (operation) => {
|
|
175
322
|
try {
|
|
176
|
-
await
|
|
177
|
-
path: opts.path,
|
|
178
|
-
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
179
|
-
accessToken: opts.accessToken,
|
|
180
|
-
projectType: opts.projectType,
|
|
181
|
-
orgId: opts.orgId,
|
|
182
|
-
orgName: opts.orgName,
|
|
183
|
-
orgSlug: opts.orgSlug,
|
|
184
|
-
ownerUserId: opts.ownerUserId,
|
|
185
|
-
json: opts.json,
|
|
186
|
-
});
|
|
323
|
+
await runGitCredentialHelper(operation);
|
|
187
324
|
}
|
|
188
325
|
catch (error) {
|
|
189
|
-
console.error(
|
|
326
|
+
console.error(String(error));
|
|
190
327
|
process.exit(1);
|
|
191
328
|
}
|
|
192
329
|
});
|
|
193
330
|
const tunnelCommand = program
|
|
194
331
|
.command("tunnel")
|
|
195
|
-
.description("
|
|
196
|
-
.option("--
|
|
332
|
+
.description("Start a shareable tunnel URL for a local port (defaults to detached)")
|
|
333
|
+
.option("--port <port>", "Local port to expose (default 3000)")
|
|
334
|
+
.option("--project <id>", "Project UUID (defaults to .instafy/project.json or PROJECT_ID)");
|
|
197
335
|
addServerUrlOptions(tunnelCommand);
|
|
336
|
+
addAccessTokenOptions(tunnelCommand, "Instafy access token (defaults to saved `instafy login` token)");
|
|
198
337
|
addServiceTokenOptions(tunnelCommand, "Instafy service token (advanced)");
|
|
199
338
|
tunnelCommand
|
|
200
|
-
.option("--
|
|
339
|
+
.option("--no-detach", "Run in foreground until interrupted")
|
|
201
340
|
.option("--rathole-bin <path>", "Path to rathole binary (or set RATHOLE_BIN)")
|
|
341
|
+
.option("--log-file <path>", "Write tunnel logs to a file (default: ~/.instafy/cli-tunnel-logs/*)")
|
|
342
|
+
.option("--json", "Output JSON")
|
|
202
343
|
.action(async (opts) => {
|
|
203
344
|
try {
|
|
204
345
|
const port = opts.port ? Number(opts.port) : undefined;
|
|
205
|
-
|
|
346
|
+
const controllerToken = opts.serviceToken ??
|
|
347
|
+
opts.controllerToken ??
|
|
348
|
+
opts.accessToken ??
|
|
349
|
+
opts.controllerAccessToken;
|
|
350
|
+
if (opts.detach === false) {
|
|
351
|
+
await runTunnelCommand({
|
|
352
|
+
project: opts.project,
|
|
353
|
+
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
354
|
+
controllerToken,
|
|
355
|
+
port,
|
|
356
|
+
ratholeBin: opts.ratholeBin,
|
|
357
|
+
});
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const started = await startTunnelDetached({
|
|
206
361
|
project: opts.project,
|
|
207
362
|
controllerUrl: opts.serverUrl ?? opts.controllerUrl,
|
|
208
|
-
controllerToken
|
|
363
|
+
controllerToken,
|
|
209
364
|
port,
|
|
210
365
|
ratholeBin: opts.ratholeBin,
|
|
366
|
+
logFile: opts.logFile,
|
|
367
|
+
});
|
|
368
|
+
if (opts.json) {
|
|
369
|
+
console.log(JSON.stringify(started, null, 2));
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
console.log(kleur.green(`Tunnel started: ${started.url} (tunnelId=${started.tunnelId})`));
|
|
373
|
+
console.log(kleur.gray(`pid=${started.pid} · port=${started.localPort}`));
|
|
374
|
+
console.log(kleur.gray(`log: ${started.logFile}`));
|
|
375
|
+
console.log("");
|
|
376
|
+
console.log("Next:");
|
|
377
|
+
console.log(`- ${kleur.cyan(`instafy tunnel:list`)}`);
|
|
378
|
+
console.log(`- ${kleur.cyan(`instafy tunnel:logs ${started.tunnelId} --follow`)}`);
|
|
379
|
+
console.log(`- ${kleur.cyan(`instafy tunnel:stop ${started.tunnelId}`)}`);
|
|
380
|
+
if (process.platform !== "win32") {
|
|
381
|
+
console.log(kleur.gray(`(or) tail -n 200 -f ${started.logFile}`));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
console.error(kleur.red(String(error)));
|
|
386
|
+
process.exit(1);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
program
|
|
390
|
+
.command("tunnel:list")
|
|
391
|
+
.description("List local tunnel sessions started by this CLI")
|
|
392
|
+
.option("--all", "Include stopped/stale tunnels")
|
|
393
|
+
.option("--json", "Output JSON")
|
|
394
|
+
.action(async (opts) => {
|
|
395
|
+
try {
|
|
396
|
+
const tunnels = listTunnelSessions({ all: Boolean(opts.all), json: Boolean(opts.json) });
|
|
397
|
+
if (opts.json) {
|
|
398
|
+
console.log(JSON.stringify(tunnels, null, 2));
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (tunnels.length === 0) {
|
|
402
|
+
console.log(kleur.yellow("No tunnels found."));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
for (const tunnel of tunnels) {
|
|
406
|
+
console.log(`${tunnel.tunnelId} · ${tunnel.url} · port=${tunnel.localPort} · pid=${tunnel.pid}`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
console.error(kleur.red(String(error)));
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
program
|
|
415
|
+
.command("tunnel:stop")
|
|
416
|
+
.description("Stop a local tunnel session and revoke it")
|
|
417
|
+
.argument("[tunnelId]", "Tunnel ID (defaults to the only active tunnel)")
|
|
418
|
+
.option("--server-url <url>", "Instafy server URL")
|
|
419
|
+
.option("--access-token <token>", "Instafy access token (defaults to saved `instafy login` token)")
|
|
420
|
+
.option("--service-token <token>", "Instafy service token (advanced)")
|
|
421
|
+
.option("--json", "Output JSON")
|
|
422
|
+
.action(async (tunnelId, opts) => {
|
|
423
|
+
try {
|
|
424
|
+
const result = await stopTunnelSession({
|
|
425
|
+
tunnelId,
|
|
426
|
+
controllerUrl: opts.serverUrl,
|
|
427
|
+
controllerToken: opts.serviceToken ?? opts.accessToken,
|
|
428
|
+
json: opts.json,
|
|
429
|
+
});
|
|
430
|
+
if (opts.json) {
|
|
431
|
+
console.log(JSON.stringify(result, null, 2));
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
console.log(kleur.green(`Tunnel stopped: ${result.tunnelId}`));
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
console.error(kleur.red(String(error)));
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
program
|
|
442
|
+
.command("tunnel:logs")
|
|
443
|
+
.description("Show logs for a local tunnel session")
|
|
444
|
+
.argument("[tunnelId]", "Tunnel ID (defaults to the only active tunnel)")
|
|
445
|
+
.option("--lines <n>", "Number of lines to show", "200")
|
|
446
|
+
.option("--follow", "Follow log output (like tail -f)")
|
|
447
|
+
.option("--json", "Output JSON")
|
|
448
|
+
.action(async (tunnelId, opts) => {
|
|
449
|
+
try {
|
|
450
|
+
const lines = typeof opts.lines === "string" ? Number(opts.lines) : undefined;
|
|
451
|
+
await tailTunnelLogs({
|
|
452
|
+
tunnelId,
|
|
453
|
+
lines,
|
|
454
|
+
follow: Boolean(opts.follow),
|
|
455
|
+
json: Boolean(opts.json),
|
|
211
456
|
});
|
|
212
457
|
}
|
|
213
458
|
catch (error) {
|
|
@@ -292,22 +537,22 @@ function configureApiCommand(command, method) {
|
|
|
292
537
|
}
|
|
293
538
|
const apiGetCommand = program
|
|
294
539
|
.command("api:get")
|
|
295
|
-
.description("
|
|
540
|
+
.description("Advanced: authenticated GET request to the controller API")
|
|
296
541
|
.argument("<path>", "API path (or full URL), e.g. /conversations/<id>/messages?limit=50");
|
|
297
542
|
configureApiCommand(apiGetCommand, "GET");
|
|
298
543
|
const apiPostCommand = program
|
|
299
544
|
.command("api:post")
|
|
300
|
-
.description("
|
|
545
|
+
.description("Advanced: authenticated POST request to the controller API")
|
|
301
546
|
.argument("<path>", "API path (or full URL)");
|
|
302
547
|
configureApiCommand(apiPostCommand, "POST");
|
|
303
548
|
const apiPatchCommand = program
|
|
304
549
|
.command("api:patch")
|
|
305
|
-
.description("
|
|
550
|
+
.description("Advanced: authenticated PATCH request to the controller API")
|
|
306
551
|
.argument("<path>", "API path (or full URL)");
|
|
307
552
|
configureApiCommand(apiPatchCommand, "PATCH");
|
|
308
553
|
const apiDeleteCommand = program
|
|
309
554
|
.command("api:delete")
|
|
310
|
-
.description("
|
|
555
|
+
.description("Advanced: authenticated DELETE request to the controller API")
|
|
311
556
|
.argument("<path>", "API path (or full URL)");
|
|
312
557
|
configureApiCommand(apiDeleteCommand, "DELETE");
|
|
313
558
|
export async function runCli(argv = process.argv) {
|
package/dist/org.js
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import kleur from "kleur";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (!value)
|
|
5
|
-
return "http://127.0.0.1:8788";
|
|
6
|
-
return value.replace(/\/$/, "");
|
|
7
|
-
}
|
|
8
|
-
function normalizeToken(raw) {
|
|
9
|
-
if (!raw)
|
|
10
|
-
return null;
|
|
11
|
-
const trimmed = raw.trim();
|
|
12
|
-
return trimmed.length ? trimmed : null;
|
|
13
|
-
}
|
|
2
|
+
import { resolveControllerUrl, resolveUserAccessToken } from "./config.js";
|
|
3
|
+
import { formatAuthRequiredError } from "./errors.js";
|
|
14
4
|
export async function listOrganizations(params) {
|
|
15
|
-
const controllerUrl =
|
|
16
|
-
const token =
|
|
17
|
-
normalizeToken(process.env["INSTAFY_ACCESS_TOKEN"]) ??
|
|
18
|
-
normalizeToken(process.env["CONTROLLER_ACCESS_TOKEN"]) ??
|
|
19
|
-
normalizeToken(process.env["SUPABASE_ACCESS_TOKEN"]);
|
|
5
|
+
const controllerUrl = resolveControllerUrl({ controllerUrl: params.controllerUrl ?? null });
|
|
6
|
+
const token = resolveUserAccessToken({ accessToken: params.accessToken ?? null });
|
|
20
7
|
if (!token) {
|
|
21
|
-
throw
|
|
8
|
+
throw formatAuthRequiredError({ retryCommand: "instafy org:list" });
|
|
22
9
|
}
|
|
23
10
|
const response = await fetch(`${controllerUrl}/orgs`, {
|
|
24
11
|
headers: { authorization: `Bearer ${token}` },
|
package/dist/project.js
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import kleur from "kleur";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (!value)
|
|
7
|
-
return "http://127.0.0.1:8788";
|
|
8
|
-
return value.replace(/\/$/, "");
|
|
9
|
-
}
|
|
10
|
-
function normalizeToken(raw) {
|
|
11
|
-
if (!raw)
|
|
12
|
-
return null;
|
|
13
|
-
const trimmed = raw.trim();
|
|
14
|
-
return trimmed.length ? trimmed : null;
|
|
15
|
-
}
|
|
4
|
+
import { resolveControllerUrl, resolveUserAccessToken } from "./config.js";
|
|
5
|
+
import { formatAuthRequiredError } from "./errors.js";
|
|
16
6
|
async function fetchOrganizations(controllerUrl, token) {
|
|
17
7
|
const response = await fetch(`${controllerUrl}/orgs`, {
|
|
18
8
|
headers: {
|
|
@@ -73,13 +63,10 @@ async function resolveOrg(controllerUrl, token, options) {
|
|
|
73
63
|
return { orgId, orgName: json.org_name ?? null };
|
|
74
64
|
}
|
|
75
65
|
export async function listProjects(options) {
|
|
76
|
-
const controllerUrl =
|
|
77
|
-
const token =
|
|
78
|
-
normalizeToken(process.env["INSTAFY_ACCESS_TOKEN"]) ??
|
|
79
|
-
normalizeToken(process.env["CONTROLLER_ACCESS_TOKEN"]) ??
|
|
80
|
-
normalizeToken(process.env["SUPABASE_ACCESS_TOKEN"]);
|
|
66
|
+
const controllerUrl = resolveControllerUrl({ controllerUrl: options.controllerUrl ?? null });
|
|
67
|
+
const token = resolveUserAccessToken({ accessToken: options.accessToken ?? null });
|
|
81
68
|
if (!token) {
|
|
82
|
-
throw
|
|
69
|
+
throw formatAuthRequiredError({ retryCommand: "instafy project:list" });
|
|
83
70
|
}
|
|
84
71
|
const orgs = await fetchOrganizations(controllerUrl, token);
|
|
85
72
|
let targetOrgs = orgs;
|
|
@@ -124,13 +111,13 @@ export async function listProjects(options) {
|
|
|
124
111
|
}
|
|
125
112
|
export async function projectInit(options) {
|
|
126
113
|
const rootDir = path.resolve(options.path ?? process.cwd());
|
|
127
|
-
const controllerUrl =
|
|
128
|
-
const token =
|
|
129
|
-
normalizeToken(process.env["INSTAFY_ACCESS_TOKEN"]) ??
|
|
130
|
-
normalizeToken(process.env["CONTROLLER_ACCESS_TOKEN"]) ??
|
|
131
|
-
normalizeToken(process.env["SUPABASE_ACCESS_TOKEN"]);
|
|
114
|
+
const controllerUrl = resolveControllerUrl({ controllerUrl: options.controllerUrl ?? null });
|
|
115
|
+
const token = resolveUserAccessToken({ accessToken: options.accessToken ?? null });
|
|
132
116
|
if (!token) {
|
|
133
|
-
throw
|
|
117
|
+
throw formatAuthRequiredError({
|
|
118
|
+
retryCommand: "instafy project:init",
|
|
119
|
+
advancedHint: "pass --access-token or set INSTAFY_ACCESS_TOKEN / SUPABASE_ACCESS_TOKEN",
|
|
120
|
+
});
|
|
134
121
|
}
|
|
135
122
|
const org = await resolveOrg(controllerUrl, token, options);
|
|
136
123
|
const body = {
|