@anythingai/cli 0.0.3 → 0.1.1
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/js/bin.mjs +1013 -575
- package/package.json +1 -1
- package/skills/anything-cli/SKILL.md +5 -2
package/dist/js/bin.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { hideBin } from "yargs/helpers";
|
|
4
4
|
import yargs from "yargs";
|
|
5
5
|
import { exec, execSync, spawn } from "node:child_process";
|
|
6
|
-
import fs, { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import fs, { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import path, { basename, dirname, extname, join, resolve } from "node:path";
|
|
8
8
|
import Conf from "conf";
|
|
9
9
|
import { err, ok } from "neverthrow";
|
|
@@ -3026,9 +3026,11 @@ const EXIT_CONFLICT = 5;
|
|
|
3026
3026
|
const EXIT_TIMEOUT = 6;
|
|
3027
3027
|
const EXIT_SERVER_ERROR = 7;
|
|
3028
3028
|
const EXIT_RATE_LIMITED = 8;
|
|
3029
|
+
const EXIT_CREDIT_LIMIT = 9;
|
|
3029
3030
|
function exitCodeFromHttpStatus(status) {
|
|
3030
3031
|
if (status === null) return EXIT_ERROR;
|
|
3031
3032
|
if (status === 401 || status === 403) return EXIT_AUTH_FAILURE;
|
|
3033
|
+
if (status === 402) return EXIT_CREDIT_LIMIT;
|
|
3032
3034
|
if (status === 404) return EXIT_NOT_FOUND;
|
|
3033
3035
|
if (status === 409) return EXIT_CONFLICT;
|
|
3034
3036
|
if (status === 408 || status === 504) return EXIT_TIMEOUT;
|
|
@@ -3037,9 +3039,23 @@ function exitCodeFromHttpStatus(status) {
|
|
|
3037
3039
|
if (status === 422 || status === 400) return EXIT_INVALID_ARGS;
|
|
3038
3040
|
return EXIT_ERROR;
|
|
3039
3041
|
}
|
|
3042
|
+
function errorCodeFromExitCode(exitCode) {
|
|
3043
|
+
switch (exitCode) {
|
|
3044
|
+
case EXIT_INVALID_ARGS: return "INVALID_ARGUMENTS";
|
|
3045
|
+
case EXIT_NOT_FOUND: return "NOT_FOUND";
|
|
3046
|
+
case EXIT_AUTH_FAILURE: return "AUTH_FAILURE";
|
|
3047
|
+
case EXIT_CREDIT_LIMIT: return "CREDIT_LIMIT_REACHED";
|
|
3048
|
+
case EXIT_CONFLICT: return "CONFLICT";
|
|
3049
|
+
case EXIT_TIMEOUT: return "TIMEOUT";
|
|
3050
|
+
case EXIT_SERVER_ERROR: return "SERVER_ERROR";
|
|
3051
|
+
case EXIT_RATE_LIMITED: return "RATE_LIMITED";
|
|
3052
|
+
default: return "ERROR";
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3040
3055
|
function errorCodeFromHttpStatus(status) {
|
|
3041
3056
|
if (status === null) return "NETWORK_ERROR";
|
|
3042
3057
|
if (status === 401) return "AUTH_FAILURE";
|
|
3058
|
+
if (status === 402) return "CREDIT_LIMIT_REACHED";
|
|
3043
3059
|
if (status === 403) return "FORBIDDEN";
|
|
3044
3060
|
if (status === 404) return "NOT_FOUND";
|
|
3045
3061
|
if (status === 409) return "CONFLICT";
|
|
@@ -3053,7 +3069,7 @@ function errorCodeFromHttpStatus(status) {
|
|
|
3053
3069
|
|
|
3054
3070
|
//#endregion
|
|
3055
3071
|
//#region package.json
|
|
3056
|
-
var version = "0.
|
|
3072
|
+
var version = "0.1.1";
|
|
3057
3073
|
|
|
3058
3074
|
//#endregion
|
|
3059
3075
|
//#region generated/core/bodySerializer.gen.ts
|
|
@@ -4315,14 +4331,23 @@ const USER_AGENT = `anything-cli/${version}`;
|
|
|
4315
4331
|
const ErrorWithMessageSchema = z.object({ message: z.string().min(1) });
|
|
4316
4332
|
const ErrorWithErrorStringSchema = z.object({ error: z.string().min(1) });
|
|
4317
4333
|
const ErrorWithNestedMessageSchema = z.object({ error: z.object({ message: z.string() }) });
|
|
4334
|
+
const HTML_DOCUMENT = /<!doctype html|<html[\s>]/i;
|
|
4335
|
+
function summarizeErrorString(raw, status) {
|
|
4336
|
+
const trimmed = raw.trim();
|
|
4337
|
+
if (!HTML_DOCUMENT.test(trimmed)) return trimmed;
|
|
4338
|
+
const pre = trimmed.match(/<pre[^>]*>([\s\S]*?)<\/pre>/i)?.[1];
|
|
4339
|
+
const title = trimmed.match(/<title[^>]*>([\s\S]*?)<\/title>/i)?.[1];
|
|
4340
|
+
const summary = (pre ?? title)?.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
4341
|
+
return summary && summary.length > 0 ? `API error (${status}): ${summary}` : `API error (${status})`;
|
|
4342
|
+
}
|
|
4318
4343
|
function extractErrorMessage(status, details) {
|
|
4319
4344
|
const withMessage = ErrorWithMessageSchema.safeParse(details);
|
|
4320
|
-
if (withMessage.success) return withMessage.data.message;
|
|
4345
|
+
if (withMessage.success) return summarizeErrorString(withMessage.data.message, status);
|
|
4321
4346
|
const withErrorString = ErrorWithErrorStringSchema.safeParse(details);
|
|
4322
|
-
if (withErrorString.success) return withErrorString.data.error;
|
|
4347
|
+
if (withErrorString.success) return summarizeErrorString(withErrorString.data.error, status);
|
|
4323
4348
|
const withNested = ErrorWithNestedMessageSchema.safeParse(details);
|
|
4324
|
-
if (withNested.success) return withNested.data.error.message;
|
|
4325
|
-
if (typeof details === "string" && details.length > 0) return details;
|
|
4349
|
+
if (withNested.success) return summarizeErrorString(withNested.data.error.message, status);
|
|
4350
|
+
if (typeof details === "string" && details.length > 0) return summarizeErrorString(details, status);
|
|
4326
4351
|
return `API error (${status})`;
|
|
4327
4352
|
}
|
|
4328
4353
|
function parseRetryAfter(response) {
|
|
@@ -4365,29 +4390,49 @@ const RollbackResponseSchema = z.object({
|
|
|
4365
4390
|
status: z.string()
|
|
4366
4391
|
}).optional()
|
|
4367
4392
|
});
|
|
4393
|
+
function wrapFetchWithTimeout(ms) {
|
|
4394
|
+
return (input, init) => {
|
|
4395
|
+
const signal = AbortSignal.timeout(ms);
|
|
4396
|
+
if (input instanceof Request) return globalThis.fetch(new Request(input, { signal }));
|
|
4397
|
+
return globalThis.fetch(input, {
|
|
4398
|
+
...init,
|
|
4399
|
+
signal
|
|
4400
|
+
});
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4368
4403
|
var AnythingApiClient = class {
|
|
4369
4404
|
client;
|
|
4370
|
-
|
|
4405
|
+
timeoutMs;
|
|
4406
|
+
constructor(config, options) {
|
|
4407
|
+
const apiUrl = config.apiUrl.replace(/\/$/, "");
|
|
4408
|
+
this.timeoutMs = options?.timeoutMs ?? null;
|
|
4371
4409
|
this.client = createClient$1(createConfig({
|
|
4372
|
-
baseUrl:
|
|
4410
|
+
baseUrl: apiUrl,
|
|
4373
4411
|
headers: {
|
|
4374
4412
|
authorization: buildAuthHeader$1(config.apiKey),
|
|
4375
4413
|
"user-agent": USER_AGENT
|
|
4376
|
-
}
|
|
4414
|
+
},
|
|
4415
|
+
...this.timeoutMs !== null ? { fetch: wrapFetchWithTimeout(this.timeoutMs) } : {}
|
|
4377
4416
|
}));
|
|
4378
4417
|
}
|
|
4379
4418
|
toResult(result) {
|
|
4380
4419
|
const { data, error, response } = result;
|
|
4381
|
-
if (!response)
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4420
|
+
if (!response) {
|
|
4421
|
+
const isTimeout = error instanceof DOMException && error.name === "TimeoutError";
|
|
4422
|
+
const timeoutSuffix = this.timeoutMs !== null ? ` after ${Math.round(this.timeoutMs / 1e3)}s` : "";
|
|
4423
|
+
return err({
|
|
4424
|
+
message: isTimeout ? `Request timed out${timeoutSuffix}. Use --timeout to increase.` : `Network error: ${error instanceof Error ? error.message : String(error)}`,
|
|
4425
|
+
status: isTimeout ? 408 : null
|
|
4426
|
+
});
|
|
4427
|
+
}
|
|
4385
4428
|
if (!response.ok) {
|
|
4386
4429
|
const retryAfter = parseRetryAfter(response);
|
|
4430
|
+
const hint = error && typeof error === "object" && "hint" in error && typeof error.hint === "string" ? error.hint : void 0;
|
|
4387
4431
|
return err({
|
|
4388
4432
|
message: extractErrorMessage(response.status, error),
|
|
4389
4433
|
status: response.status,
|
|
4390
4434
|
details: error,
|
|
4435
|
+
...hint ? { hint } : {},
|
|
4391
4436
|
...retryAfter !== null ? { retryAfter } : {}
|
|
4392
4437
|
});
|
|
4393
4438
|
}
|
|
@@ -4810,10 +4855,6 @@ function printApiError(error) {
|
|
|
4810
4855
|
if (withErrors.success) for (const e of withErrors.data.errors) console.error(` ${typeof e === "string" ? e : e.message}`);
|
|
4811
4856
|
}
|
|
4812
4857
|
function outputSuccess({ argv, command, data, primaryId, startTime }) {
|
|
4813
|
-
if (argv.quiet) {
|
|
4814
|
-
if (primaryId) console.log(primaryId);
|
|
4815
|
-
return true;
|
|
4816
|
-
}
|
|
4817
4858
|
if (argv.json) {
|
|
4818
4859
|
const envelope = {
|
|
4819
4860
|
ok: true,
|
|
@@ -4824,6 +4865,10 @@ function outputSuccess({ argv, command, data, primaryId, startTime }) {
|
|
|
4824
4865
|
console.log(JSON.stringify(envelope, null, 2));
|
|
4825
4866
|
return true;
|
|
4826
4867
|
}
|
|
4868
|
+
if (argv.quiet) {
|
|
4869
|
+
if (primaryId) console.log(primaryId);
|
|
4870
|
+
return true;
|
|
4871
|
+
}
|
|
4827
4872
|
return false;
|
|
4828
4873
|
}
|
|
4829
4874
|
const DetailsWithCodeSchema = z.object({ code: z.string() });
|
|
@@ -4835,8 +4880,9 @@ function outputError({ argv, command, error, hint, exitCode }) {
|
|
|
4835
4880
|
const status = "status" in error ? error.status ?? null : null;
|
|
4836
4881
|
const details = "details" in error ? error.details : void 0;
|
|
4837
4882
|
const retryAfter = "retryAfter" in error && typeof error.retryAfter === "number" ? error.retryAfter : null;
|
|
4883
|
+
const resolvedHint = hint ?? ("hint" in error && typeof error.hint === "string" ? error.hint : void 0);
|
|
4838
4884
|
process.exitCode = exitCode ?? exitCodeFromHttpStatus(status);
|
|
4839
|
-
const code = extractErrorCode(details) ?? errorCodeFromHttpStatus(status);
|
|
4885
|
+
const code = extractErrorCode(details) ?? (status === null && exitCode !== void 0 ? errorCodeFromExitCode(exitCode) : errorCodeFromHttpStatus(status));
|
|
4840
4886
|
if (argv.json || argv.quiet) {
|
|
4841
4887
|
console.error(JSON.stringify({
|
|
4842
4888
|
ok: false,
|
|
@@ -4844,7 +4890,7 @@ function outputError({ argv, command, error, hint, exitCode }) {
|
|
|
4844
4890
|
error: {
|
|
4845
4891
|
code,
|
|
4846
4892
|
message: error.message,
|
|
4847
|
-
...
|
|
4893
|
+
...resolvedHint ? { hint: resolvedHint } : {},
|
|
4848
4894
|
...retryAfter !== null ? { retry_after_seconds: retryAfter } : {}
|
|
4849
4895
|
}
|
|
4850
4896
|
}, null, 2));
|
|
@@ -4856,7 +4902,7 @@ function outputError({ argv, command, error, hint, exitCode }) {
|
|
|
4856
4902
|
details
|
|
4857
4903
|
});
|
|
4858
4904
|
if (retryAfter !== null) console.error(` ${styleText("dim", `Retry after ${retryAfter}s`)}`);
|
|
4859
|
-
if (
|
|
4905
|
+
if (resolvedHint) console.error(` ${styleText("dim", resolvedHint)}`);
|
|
4860
4906
|
}
|
|
4861
4907
|
function outputValidationError({ argv, command, message, hint }) {
|
|
4862
4908
|
outputError({
|
|
@@ -4871,7 +4917,6 @@ function outputValidationError({ argv, command, message, hint }) {
|
|
|
4871
4917
|
});
|
|
4872
4918
|
}
|
|
4873
4919
|
function outputDryRun({ argv, command, plannedActions }) {
|
|
4874
|
-
if (argv.quiet) return;
|
|
4875
4920
|
if (argv.json) {
|
|
4876
4921
|
console.log(JSON.stringify({
|
|
4877
4922
|
ok: true,
|
|
@@ -4881,6 +4926,7 @@ function outputDryRun({ argv, command, plannedActions }) {
|
|
|
4881
4926
|
}, null, 2));
|
|
4882
4927
|
return;
|
|
4883
4928
|
}
|
|
4929
|
+
if (argv.quiet) return;
|
|
4884
4930
|
printSuccess("Dry run — no changes made.");
|
|
4885
4931
|
for (const action of plannedActions) {
|
|
4886
4932
|
printLabel("Action", action.action);
|
|
@@ -4958,6 +5004,19 @@ const upload = {
|
|
|
4958
5004
|
});
|
|
4959
5005
|
return;
|
|
4960
5006
|
}
|
|
5007
|
+
if (argv["dry-run"]) {
|
|
5008
|
+
outputDryRun({
|
|
5009
|
+
argv,
|
|
5010
|
+
command,
|
|
5011
|
+
plannedActions: [{
|
|
5012
|
+
action: "upload_asset",
|
|
5013
|
+
projectGroupId: argv.projectId,
|
|
5014
|
+
file: filePath,
|
|
5015
|
+
...argv.name ? { name: argv.name } : {}
|
|
5016
|
+
}]
|
|
5017
|
+
});
|
|
5018
|
+
return;
|
|
5019
|
+
}
|
|
4961
5020
|
const config = resolveConfig({
|
|
4962
5021
|
dev: argv.dev,
|
|
4963
5022
|
apiUrl: argv.apiUrl
|
|
@@ -5097,6 +5156,18 @@ const remove$1 = {
|
|
|
5097
5156
|
}),
|
|
5098
5157
|
handler: async (argv) => {
|
|
5099
5158
|
const command = "assets remove";
|
|
5159
|
+
if (argv["dry-run"]) {
|
|
5160
|
+
outputDryRun({
|
|
5161
|
+
argv,
|
|
5162
|
+
command,
|
|
5163
|
+
plannedActions: [{
|
|
5164
|
+
action: "remove_asset",
|
|
5165
|
+
projectGroupId: argv.projectId,
|
|
5166
|
+
assetId: argv.assetId
|
|
5167
|
+
}]
|
|
5168
|
+
});
|
|
5169
|
+
return;
|
|
5170
|
+
}
|
|
5100
5171
|
const config = resolveConfig({
|
|
5101
5172
|
dev: argv.dev,
|
|
5102
5173
|
apiUrl: argv.apiUrl
|
|
@@ -5406,13 +5477,31 @@ const login = {
|
|
|
5406
5477
|
}).replace(/\/$/, "");
|
|
5407
5478
|
const nonInteractive = isNonInteractive(argv);
|
|
5408
5479
|
if (argv["api-key"]) {
|
|
5480
|
+
const apiKey = argv["api-key"];
|
|
5481
|
+
const probe = await new AnythingApiClient({
|
|
5482
|
+
apiKey,
|
|
5483
|
+
apiUrl
|
|
5484
|
+
}).getMe();
|
|
5485
|
+
if (probe.isErr()) {
|
|
5486
|
+
outputError({
|
|
5487
|
+
argv,
|
|
5488
|
+
command: "auth login",
|
|
5489
|
+
error: {
|
|
5490
|
+
message: `API key was rejected: ${probe.error.message}`,
|
|
5491
|
+
status: probe.error.status
|
|
5492
|
+
},
|
|
5493
|
+
hint: "Double-check the key and that it matches this API URL. Your existing login was left untouched.",
|
|
5494
|
+
exitCode: 4
|
|
5495
|
+
});
|
|
5496
|
+
return;
|
|
5497
|
+
}
|
|
5409
5498
|
saveConfig({
|
|
5410
|
-
apiKey
|
|
5499
|
+
apiKey,
|
|
5411
5500
|
apiUrl
|
|
5412
5501
|
});
|
|
5413
5502
|
const org = await selectAndSetOrg({
|
|
5414
5503
|
config: {
|
|
5415
|
-
apiKey
|
|
5504
|
+
apiKey,
|
|
5416
5505
|
apiUrl
|
|
5417
5506
|
},
|
|
5418
5507
|
json: argv.json,
|
|
@@ -5686,6 +5775,9 @@ const authCommand = {
|
|
|
5686
5775
|
//#endregion
|
|
5687
5776
|
//#region src/commands/database-connect.ts
|
|
5688
5777
|
const COMMAND$25 = "databases connect";
|
|
5778
|
+
function maskConnectionString(connectionString) {
|
|
5779
|
+
return connectionString.replace(/(\/\/[^:/?#@]+:)[^@/?#]*(@)/, "$1****$2");
|
|
5780
|
+
}
|
|
5689
5781
|
const databaseConnectCommand = {
|
|
5690
5782
|
command: "connect <databaseId>",
|
|
5691
5783
|
describe: "Print the connection string for a database",
|
|
@@ -5693,7 +5785,11 @@ const databaseConnectCommand = {
|
|
|
5693
5785
|
type: "string",
|
|
5694
5786
|
demandOption: true,
|
|
5695
5787
|
describe: "The database ID"
|
|
5696
|
-
}).
|
|
5788
|
+
}).option("mask", {
|
|
5789
|
+
type: "boolean",
|
|
5790
|
+
default: false,
|
|
5791
|
+
describe: "Redact the password in the connection string"
|
|
5792
|
+
}).example("anything databases connect db_123", "Print the connection string").example("anything databases connect db_123 --mask", "Print the connection string with the password redacted"),
|
|
5697
5793
|
handler: async (argv) => {
|
|
5698
5794
|
const config = resolveConfig({
|
|
5699
5795
|
dev: argv.dev,
|
|
@@ -5720,13 +5816,17 @@ const databaseConnectCommand = {
|
|
|
5720
5816
|
});
|
|
5721
5817
|
return;
|
|
5722
5818
|
}
|
|
5819
|
+
const connectionString = argv.mask ? maskConnectionString(result.value.connectionString) : result.value.connectionString;
|
|
5723
5820
|
if (outputSuccess({
|
|
5724
5821
|
argv,
|
|
5725
5822
|
command: COMMAND$25,
|
|
5726
|
-
data:
|
|
5727
|
-
|
|
5823
|
+
data: {
|
|
5824
|
+
...result.value,
|
|
5825
|
+
connectionString
|
|
5826
|
+
},
|
|
5827
|
+
primaryId: connectionString
|
|
5728
5828
|
})) return;
|
|
5729
|
-
console.log(
|
|
5829
|
+
console.log(connectionString);
|
|
5730
5830
|
}
|
|
5731
5831
|
};
|
|
5732
5832
|
|
|
@@ -5791,6 +5891,19 @@ const databaseCreateCommand = {
|
|
|
5791
5891
|
describe: "Database name"
|
|
5792
5892
|
}).example("anything databases create --project pg_123", "Create a database for a project"),
|
|
5793
5893
|
handler: async (argv) => {
|
|
5894
|
+
const name = argv.name?.trim();
|
|
5895
|
+
if (!name) {
|
|
5896
|
+
outputError({
|
|
5897
|
+
argv,
|
|
5898
|
+
command: COMMAND$24,
|
|
5899
|
+
error: {
|
|
5900
|
+
message: "Database name is required. Pass --name <name>.",
|
|
5901
|
+
status: null
|
|
5902
|
+
},
|
|
5903
|
+
exitCode: 2
|
|
5904
|
+
});
|
|
5905
|
+
return;
|
|
5906
|
+
}
|
|
5794
5907
|
const config = resolveConfig({
|
|
5795
5908
|
dev: argv.dev,
|
|
5796
5909
|
apiUrl: argv.apiUrl
|
|
@@ -5831,8 +5944,8 @@ const databaseCreateCommand = {
|
|
|
5831
5944
|
plannedActions: [{
|
|
5832
5945
|
action: "create_database",
|
|
5833
5946
|
org: orgResult.orgId,
|
|
5834
|
-
|
|
5835
|
-
...argv.
|
|
5947
|
+
name,
|
|
5948
|
+
...argv.project ? { project: argv.project } : {}
|
|
5836
5949
|
}]
|
|
5837
5950
|
});
|
|
5838
5951
|
return;
|
|
@@ -5840,7 +5953,7 @@ const databaseCreateCommand = {
|
|
|
5840
5953
|
const result = await new AnythingApiClient(config.value).createDatabase({
|
|
5841
5954
|
organizationId: orgResult.orgId,
|
|
5842
5955
|
projectGroupId: argv.project ?? null,
|
|
5843
|
-
name
|
|
5956
|
+
name
|
|
5844
5957
|
});
|
|
5845
5958
|
if (result.isErr()) {
|
|
5846
5959
|
outputError({
|
|
@@ -6712,153 +6825,381 @@ const domainsCommand = {
|
|
|
6712
6825
|
};
|
|
6713
6826
|
|
|
6714
6827
|
//#endregion
|
|
6715
|
-
//#region src/commands/
|
|
6716
|
-
const
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
idempotent: true,
|
|
6753
|
-
destructive: false
|
|
6754
|
-
},
|
|
6755
|
-
{
|
|
6756
|
-
name: "orgs get",
|
|
6757
|
-
flags: [{
|
|
6758
|
-
name: "<organizationId>",
|
|
6759
|
-
type: "string",
|
|
6760
|
-
required: true
|
|
6761
|
-
}],
|
|
6762
|
-
idempotent: true,
|
|
6763
|
-
destructive: false
|
|
6764
|
-
},
|
|
6765
|
-
{
|
|
6766
|
-
name: "orgs set",
|
|
6767
|
-
flags: [{
|
|
6768
|
-
name: "<org-id>",
|
|
6769
|
-
type: "string",
|
|
6770
|
-
required: true
|
|
6771
|
-
}],
|
|
6772
|
-
idempotent: true,
|
|
6773
|
-
destructive: false
|
|
6774
|
-
},
|
|
6775
|
-
{
|
|
6776
|
-
name: "orgs unset",
|
|
6777
|
-
flags: [],
|
|
6778
|
-
idempotent: true,
|
|
6779
|
-
destructive: false
|
|
6780
|
-
},
|
|
6781
|
-
{
|
|
6782
|
-
name: "orgs members",
|
|
6783
|
-
flags: [{
|
|
6784
|
-
name: "<organizationId>",
|
|
6785
|
-
type: "string",
|
|
6786
|
-
required: true
|
|
6787
|
-
}],
|
|
6788
|
-
idempotent: true,
|
|
6789
|
-
destructive: false
|
|
6790
|
-
},
|
|
6791
|
-
{
|
|
6792
|
-
name: "projects list",
|
|
6793
|
-
flags: [
|
|
6794
|
-
{
|
|
6795
|
-
name: "--org",
|
|
6796
|
-
type: "string",
|
|
6797
|
-
required: false
|
|
6798
|
-
},
|
|
6799
|
-
{
|
|
6800
|
-
name: "--search",
|
|
6801
|
-
type: "string",
|
|
6802
|
-
required: false
|
|
6803
|
-
},
|
|
6804
|
-
{
|
|
6805
|
-
name: "--limit",
|
|
6806
|
-
type: "number",
|
|
6807
|
-
required: false
|
|
6808
|
-
}
|
|
6809
|
-
],
|
|
6810
|
-
idempotent: true,
|
|
6811
|
-
destructive: false
|
|
6812
|
-
},
|
|
6813
|
-
{
|
|
6814
|
-
name: "projects create",
|
|
6815
|
-
flags: [
|
|
6816
|
-
{
|
|
6817
|
-
name: "--prompt",
|
|
6818
|
-
type: "string",
|
|
6819
|
-
required: true
|
|
6820
|
-
},
|
|
6821
|
-
{
|
|
6822
|
-
name: "--org",
|
|
6823
|
-
type: "string",
|
|
6824
|
-
required: false
|
|
6825
|
-
},
|
|
6826
|
-
{
|
|
6827
|
-
name: "--name",
|
|
6828
|
-
type: "string",
|
|
6829
|
-
required: false
|
|
6830
|
-
}
|
|
6831
|
-
],
|
|
6832
|
-
idempotent: false,
|
|
6833
|
-
destructive: false
|
|
6834
|
-
},
|
|
6835
|
-
{
|
|
6836
|
-
name: "projects get",
|
|
6837
|
-
flags: [{
|
|
6838
|
-
name: "<projectId>",
|
|
6839
|
-
type: "string",
|
|
6840
|
-
required: true
|
|
6841
|
-
}],
|
|
6842
|
-
idempotent: true,
|
|
6843
|
-
destructive: false
|
|
6844
|
-
},
|
|
6845
|
-
{
|
|
6846
|
-
name: "projects generate",
|
|
6847
|
-
flags: [
|
|
6848
|
-
{
|
|
6849
|
-
name: "<projectId>",
|
|
6850
|
-
type: "string",
|
|
6851
|
-
required: true
|
|
6852
|
-
},
|
|
6853
|
-
{
|
|
6854
|
-
name: "--prompt",
|
|
6855
|
-
type: "string",
|
|
6856
|
-
required: true
|
|
6828
|
+
//#region src/commands/submit.ts
|
|
6829
|
+
const POLL_INTERVAL_MS$1 = 2e3;
|
|
6830
|
+
const POLL_TIMEOUT_MS = 6e4;
|
|
6831
|
+
const STORE_CHOICES = ["app-store", "play-store"];
|
|
6832
|
+
async function waitForSubmission({ client, projectGroupId, submission }) {
|
|
6833
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
6834
|
+
let current = submission;
|
|
6835
|
+
while (current.status === "PENDING" && Date.now() < deadline) {
|
|
6836
|
+
const latestResult = await client.getProjectSubmission({
|
|
6837
|
+
projectGroupId,
|
|
6838
|
+
submissionId: current.id
|
|
6839
|
+
});
|
|
6840
|
+
if (latestResult.isErr()) return latestResult.map((value) => value.submission);
|
|
6841
|
+
current = latestResult.value.submission;
|
|
6842
|
+
if (current.status !== "PENDING") return latestResult.map((value) => value.submission);
|
|
6843
|
+
await setTimeout$1(POLL_INTERVAL_MS$1);
|
|
6844
|
+
}
|
|
6845
|
+
return ok(current);
|
|
6846
|
+
}
|
|
6847
|
+
function printSubmissionResult({ argv, command, pendingMessage, submission }) {
|
|
6848
|
+
const { projectGroupId: projectId, ...submissionRest } = submission;
|
|
6849
|
+
const submissionOut = {
|
|
6850
|
+
projectId,
|
|
6851
|
+
...submissionRest
|
|
6852
|
+
};
|
|
6853
|
+
if (submission.status === "FAILED") {
|
|
6854
|
+
printError(submission.errorMessage ?? "Submission failed.");
|
|
6855
|
+
process.exitCode = 1;
|
|
6856
|
+
return;
|
|
6857
|
+
}
|
|
6858
|
+
if (submission.status === "CREATED") {
|
|
6859
|
+
if (outputSuccess({
|
|
6860
|
+
argv,
|
|
6861
|
+
command,
|
|
6862
|
+
data: {
|
|
6863
|
+
success: true,
|
|
6864
|
+
submission: submissionOut
|
|
6857
6865
|
},
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6866
|
+
primaryId: submission.id
|
|
6867
|
+
})) return;
|
|
6868
|
+
printSuccess("App Store submission is ready.");
|
|
6869
|
+
printLabel("Submission ID", submission.id);
|
|
6870
|
+
printLabel("Launch URL", submission.launchUrl);
|
|
6871
|
+
printLabel("Auth URL", submission.authUrl);
|
|
6872
|
+
printLabel("Expires At", submission.expiresAt);
|
|
6873
|
+
return;
|
|
6874
|
+
}
|
|
6875
|
+
if (outputSuccess({
|
|
6876
|
+
argv,
|
|
6877
|
+
command,
|
|
6878
|
+
data: {
|
|
6879
|
+
success: true,
|
|
6880
|
+
submission
|
|
6881
|
+
},
|
|
6882
|
+
primaryId: submission.id
|
|
6883
|
+
})) return;
|
|
6884
|
+
printSuccess(pendingMessage);
|
|
6885
|
+
printLabel("Submission ID", submission.id);
|
|
6886
|
+
printLabel("Status", submission.status);
|
|
6887
|
+
printLabel("Next step", "Expo is still preparing the launch flow. Run the command again in a moment.");
|
|
6888
|
+
}
|
|
6889
|
+
const submitStatusCommand = {
|
|
6890
|
+
command: "status <projectId> <submissionId>",
|
|
6891
|
+
describe: "Check the status of an App Store submission",
|
|
6892
|
+
builder: (yargs) => yargs.positional("projectId", {
|
|
6893
|
+
type: "string",
|
|
6894
|
+
demandOption: true,
|
|
6895
|
+
describe: "The project ID"
|
|
6896
|
+
}).positional("submissionId", {
|
|
6897
|
+
type: "string",
|
|
6898
|
+
demandOption: true,
|
|
6899
|
+
describe: "The submission ID"
|
|
6900
|
+
}).example("anything projects submit status <project-id> <submission-id>", "Check a submission later").example("anything projects submit status <project-id> <submission-id> --json", "Return the submission status in JSON"),
|
|
6901
|
+
handler: async (argv) => {
|
|
6902
|
+
const command = "projects submit status";
|
|
6903
|
+
const config = resolveConfig({
|
|
6904
|
+
dev: argv.dev,
|
|
6905
|
+
apiUrl: argv.apiUrl
|
|
6906
|
+
});
|
|
6907
|
+
if (config.isErr()) {
|
|
6908
|
+
outputError({
|
|
6909
|
+
argv,
|
|
6910
|
+
command,
|
|
6911
|
+
error: {
|
|
6912
|
+
message: config.error.message,
|
|
6913
|
+
status: null
|
|
6914
|
+
},
|
|
6915
|
+
exitCode: 4
|
|
6916
|
+
});
|
|
6917
|
+
return;
|
|
6918
|
+
}
|
|
6919
|
+
const result = await new AnythingApiClient(config.value).getProjectSubmission({
|
|
6920
|
+
projectGroupId: argv.projectId,
|
|
6921
|
+
submissionId: argv.submissionId
|
|
6922
|
+
});
|
|
6923
|
+
if (result.isErr()) {
|
|
6924
|
+
outputError({
|
|
6925
|
+
argv,
|
|
6926
|
+
command,
|
|
6927
|
+
error: result.error
|
|
6928
|
+
});
|
|
6929
|
+
return;
|
|
6930
|
+
}
|
|
6931
|
+
printSubmissionResult({
|
|
6932
|
+
argv,
|
|
6933
|
+
command,
|
|
6934
|
+
pendingMessage: "Submission is still preparing.",
|
|
6935
|
+
submission: result.value.submission
|
|
6936
|
+
});
|
|
6937
|
+
}
|
|
6938
|
+
};
|
|
6939
|
+
const submitCommand = {
|
|
6940
|
+
command: "submit <projectId>",
|
|
6941
|
+
describe: "Start an App Store submission for an app",
|
|
6942
|
+
builder: (yargs) => yargs.command(submitStatusCommand).positional("projectId", {
|
|
6943
|
+
type: "string",
|
|
6944
|
+
demandOption: true,
|
|
6945
|
+
describe: "The project ID"
|
|
6946
|
+
}).option("store", {
|
|
6947
|
+
type: "string",
|
|
6948
|
+
choices: STORE_CHOICES,
|
|
6949
|
+
describe: "Submission target store"
|
|
6950
|
+
}).example("anything projects submit <project-id> --store app-store", "Start an App Store submission").example("anything projects submit <project-id> --store play-store", "Start a Play Store submission").example("anything projects submit <project-id> --store app-store --json", "Return the submission session in JSON").example("anything projects submit status <project-id> <submission-id>", "Check a submission later"),
|
|
6951
|
+
handler: async (argv) => {
|
|
6952
|
+
const command = "projects submit";
|
|
6953
|
+
if (argv.store === void 0) {
|
|
6954
|
+
outputError({
|
|
6955
|
+
argv,
|
|
6956
|
+
command,
|
|
6957
|
+
error: {
|
|
6958
|
+
message: "Missing required argument: store",
|
|
6959
|
+
status: null
|
|
6960
|
+
},
|
|
6961
|
+
exitCode: 2
|
|
6962
|
+
});
|
|
6963
|
+
return;
|
|
6964
|
+
}
|
|
6965
|
+
const store = STORE_CHOICES.find((s) => s === argv.store);
|
|
6966
|
+
if (!store) {
|
|
6967
|
+
outputError({
|
|
6968
|
+
argv,
|
|
6969
|
+
command,
|
|
6970
|
+
error: {
|
|
6971
|
+
message: `Unsupported store: ${argv.store}`,
|
|
6972
|
+
status: null
|
|
6973
|
+
},
|
|
6974
|
+
exitCode: 2
|
|
6975
|
+
});
|
|
6976
|
+
return;
|
|
6977
|
+
}
|
|
6978
|
+
if (argv["dry-run"]) {
|
|
6979
|
+
outputDryRun({
|
|
6980
|
+
argv,
|
|
6981
|
+
command,
|
|
6982
|
+
plannedActions: [{
|
|
6983
|
+
action: "submit_project",
|
|
6984
|
+
projectGroupId: argv.projectId,
|
|
6985
|
+
store
|
|
6986
|
+
}]
|
|
6987
|
+
});
|
|
6988
|
+
return;
|
|
6989
|
+
}
|
|
6990
|
+
const config = resolveConfig({
|
|
6991
|
+
dev: argv.dev,
|
|
6992
|
+
apiUrl: argv.apiUrl
|
|
6993
|
+
});
|
|
6994
|
+
if (config.isErr()) {
|
|
6995
|
+
outputError({
|
|
6996
|
+
argv,
|
|
6997
|
+
command,
|
|
6998
|
+
error: {
|
|
6999
|
+
message: config.error.message,
|
|
7000
|
+
status: null
|
|
7001
|
+
},
|
|
7002
|
+
exitCode: 4
|
|
7003
|
+
});
|
|
7004
|
+
return;
|
|
7005
|
+
}
|
|
7006
|
+
const client = new AnythingApiClient(config.value);
|
|
7007
|
+
const startResult = await client.submitProject({
|
|
7008
|
+
projectGroupId: argv.projectId,
|
|
7009
|
+
store
|
|
7010
|
+
});
|
|
7011
|
+
if (startResult.isErr()) {
|
|
7012
|
+
outputError({
|
|
7013
|
+
argv,
|
|
7014
|
+
command,
|
|
7015
|
+
error: startResult.error
|
|
7016
|
+
});
|
|
7017
|
+
return;
|
|
7018
|
+
}
|
|
7019
|
+
const finalResult = await waitForSubmission({
|
|
7020
|
+
client,
|
|
7021
|
+
projectGroupId: argv.projectId,
|
|
7022
|
+
submission: startResult.value.submission
|
|
7023
|
+
});
|
|
7024
|
+
if (finalResult.isErr()) {
|
|
7025
|
+
outputError({
|
|
7026
|
+
argv,
|
|
7027
|
+
command,
|
|
7028
|
+
error: finalResult.error
|
|
7029
|
+
});
|
|
7030
|
+
return;
|
|
7031
|
+
}
|
|
7032
|
+
printSubmissionResult({
|
|
7033
|
+
argv,
|
|
7034
|
+
command,
|
|
7035
|
+
pendingMessage: "Submission started.",
|
|
7036
|
+
submission: finalResult.value
|
|
7037
|
+
});
|
|
7038
|
+
}
|
|
7039
|
+
};
|
|
7040
|
+
|
|
7041
|
+
//#endregion
|
|
7042
|
+
//#region src/commands/introspect.ts
|
|
7043
|
+
const commandTree = [
|
|
7044
|
+
{
|
|
7045
|
+
name: "auth login",
|
|
7046
|
+
flags: [{
|
|
7047
|
+
name: "--api-key",
|
|
7048
|
+
type: "string",
|
|
7049
|
+
required: false
|
|
7050
|
+
}, {
|
|
7051
|
+
name: "--dev",
|
|
7052
|
+
type: "boolean",
|
|
7053
|
+
required: false
|
|
7054
|
+
}],
|
|
7055
|
+
idempotent: true,
|
|
7056
|
+
destructive: false
|
|
7057
|
+
},
|
|
7058
|
+
{
|
|
7059
|
+
name: "auth logout",
|
|
7060
|
+
flags: [],
|
|
7061
|
+
idempotent: true,
|
|
7062
|
+
destructive: true
|
|
7063
|
+
},
|
|
7064
|
+
{
|
|
7065
|
+
name: "auth status",
|
|
7066
|
+
flags: [],
|
|
7067
|
+
idempotent: true,
|
|
7068
|
+
destructive: false
|
|
7069
|
+
},
|
|
7070
|
+
{
|
|
7071
|
+
name: "user",
|
|
7072
|
+
flags: [{
|
|
7073
|
+
name: "--brief",
|
|
7074
|
+
type: "boolean",
|
|
7075
|
+
required: false
|
|
7076
|
+
}],
|
|
7077
|
+
idempotent: true,
|
|
7078
|
+
destructive: false
|
|
7079
|
+
},
|
|
7080
|
+
{
|
|
7081
|
+
name: "orgs list",
|
|
7082
|
+
flags: [],
|
|
7083
|
+
idempotent: true,
|
|
7084
|
+
destructive: false
|
|
7085
|
+
},
|
|
7086
|
+
{
|
|
7087
|
+
name: "orgs get",
|
|
7088
|
+
flags: [{
|
|
7089
|
+
name: "<organizationId>",
|
|
7090
|
+
type: "string",
|
|
7091
|
+
required: true
|
|
7092
|
+
}],
|
|
7093
|
+
idempotent: true,
|
|
7094
|
+
destructive: false
|
|
7095
|
+
},
|
|
7096
|
+
{
|
|
7097
|
+
name: "orgs set",
|
|
7098
|
+
flags: [{
|
|
7099
|
+
name: "<org-id>",
|
|
7100
|
+
type: "string",
|
|
7101
|
+
required: true
|
|
7102
|
+
}],
|
|
7103
|
+
idempotent: true,
|
|
7104
|
+
destructive: false
|
|
7105
|
+
},
|
|
7106
|
+
{
|
|
7107
|
+
name: "orgs unset",
|
|
7108
|
+
flags: [],
|
|
7109
|
+
idempotent: true,
|
|
7110
|
+
destructive: false
|
|
7111
|
+
},
|
|
7112
|
+
{
|
|
7113
|
+
name: "orgs members",
|
|
7114
|
+
flags: [{
|
|
7115
|
+
name: "<organizationId>",
|
|
7116
|
+
type: "string",
|
|
7117
|
+
required: true
|
|
7118
|
+
}],
|
|
7119
|
+
idempotent: true,
|
|
7120
|
+
destructive: false
|
|
7121
|
+
},
|
|
7122
|
+
{
|
|
7123
|
+
name: "projects list",
|
|
7124
|
+
flags: [
|
|
7125
|
+
{
|
|
7126
|
+
name: "--org",
|
|
7127
|
+
type: "string",
|
|
7128
|
+
required: false
|
|
7129
|
+
},
|
|
7130
|
+
{
|
|
7131
|
+
name: "--search",
|
|
7132
|
+
type: "string",
|
|
7133
|
+
required: false
|
|
7134
|
+
},
|
|
7135
|
+
{
|
|
7136
|
+
name: "--limit",
|
|
7137
|
+
type: "number",
|
|
7138
|
+
required: false
|
|
7139
|
+
}
|
|
7140
|
+
],
|
|
7141
|
+
idempotent: true,
|
|
7142
|
+
destructive: false
|
|
7143
|
+
},
|
|
7144
|
+
{
|
|
7145
|
+
name: "projects create",
|
|
7146
|
+
flags: [
|
|
7147
|
+
{
|
|
7148
|
+
name: "--prompt",
|
|
7149
|
+
type: "string",
|
|
7150
|
+
required: true
|
|
7151
|
+
},
|
|
7152
|
+
{
|
|
7153
|
+
name: "--org",
|
|
7154
|
+
type: "string",
|
|
7155
|
+
required: false
|
|
7156
|
+
},
|
|
7157
|
+
{
|
|
7158
|
+
name: "--name",
|
|
7159
|
+
type: "string",
|
|
7160
|
+
required: false
|
|
7161
|
+
},
|
|
7162
|
+
{
|
|
7163
|
+
name: "--wait",
|
|
7164
|
+
type: "boolean",
|
|
7165
|
+
required: false
|
|
7166
|
+
},
|
|
7167
|
+
{
|
|
7168
|
+
name: "--no-wait",
|
|
7169
|
+
type: "boolean",
|
|
7170
|
+
required: false
|
|
7171
|
+
}
|
|
7172
|
+
],
|
|
7173
|
+
idempotent: false,
|
|
7174
|
+
destructive: false
|
|
7175
|
+
},
|
|
7176
|
+
{
|
|
7177
|
+
name: "projects get",
|
|
7178
|
+
flags: [{
|
|
7179
|
+
name: "<projectId>",
|
|
7180
|
+
type: "string",
|
|
7181
|
+
required: true
|
|
7182
|
+
}],
|
|
7183
|
+
idempotent: true,
|
|
7184
|
+
destructive: false
|
|
7185
|
+
},
|
|
7186
|
+
{
|
|
7187
|
+
name: "projects generate",
|
|
7188
|
+
flags: [
|
|
7189
|
+
{
|
|
7190
|
+
name: "<projectId>",
|
|
7191
|
+
type: "string",
|
|
7192
|
+
required: true
|
|
7193
|
+
},
|
|
7194
|
+
{
|
|
7195
|
+
name: "--prompt",
|
|
7196
|
+
type: "string",
|
|
7197
|
+
required: true
|
|
7198
|
+
},
|
|
7199
|
+
{
|
|
7200
|
+
name: "--thread",
|
|
7201
|
+
type: "string",
|
|
7202
|
+
required: false
|
|
6862
7203
|
},
|
|
6863
7204
|
{
|
|
6864
7205
|
name: "--new-thread",
|
|
@@ -6931,7 +7272,7 @@ const commandTree = [
|
|
|
6931
7272
|
name: "--store",
|
|
6932
7273
|
type: "string",
|
|
6933
7274
|
required: true,
|
|
6934
|
-
choices: [
|
|
7275
|
+
choices: [...STORE_CHOICES]
|
|
6935
7276
|
}],
|
|
6936
7277
|
idempotent: false,
|
|
6937
7278
|
destructive: false
|
|
@@ -7171,7 +7512,12 @@ const commandTree = [
|
|
|
7171
7512
|
{
|
|
7172
7513
|
name: "--env",
|
|
7173
7514
|
type: "string",
|
|
7174
|
-
required: false
|
|
7515
|
+
required: false,
|
|
7516
|
+
choices: [
|
|
7517
|
+
"development",
|
|
7518
|
+
"preview",
|
|
7519
|
+
"production"
|
|
7520
|
+
]
|
|
7175
7521
|
}
|
|
7176
7522
|
],
|
|
7177
7523
|
idempotent: false,
|
|
@@ -7291,7 +7637,7 @@ const commandTree = [
|
|
|
7291
7637
|
{
|
|
7292
7638
|
name: "--name",
|
|
7293
7639
|
type: "string",
|
|
7294
|
-
required:
|
|
7640
|
+
required: true
|
|
7295
7641
|
}
|
|
7296
7642
|
],
|
|
7297
7643
|
idempotent: false,
|
|
@@ -7317,6 +7663,10 @@ const commandTree = [
|
|
|
7317
7663
|
name: "<databaseId>",
|
|
7318
7664
|
type: "string",
|
|
7319
7665
|
required: true
|
|
7666
|
+
}, {
|
|
7667
|
+
name: "--mask",
|
|
7668
|
+
type: "boolean",
|
|
7669
|
+
required: false
|
|
7320
7670
|
}],
|
|
7321
7671
|
idempotent: true,
|
|
7322
7672
|
destructive: false
|
|
@@ -7473,7 +7823,13 @@ const commandTree = [
|
|
|
7473
7823
|
{
|
|
7474
7824
|
name: "--role",
|
|
7475
7825
|
type: "string",
|
|
7476
|
-
required: false
|
|
7826
|
+
required: false,
|
|
7827
|
+
choices: [
|
|
7828
|
+
"owner",
|
|
7829
|
+
"admin",
|
|
7830
|
+
"editor",
|
|
7831
|
+
"viewer"
|
|
7832
|
+
]
|
|
7477
7833
|
}
|
|
7478
7834
|
],
|
|
7479
7835
|
idempotent: false,
|
|
@@ -7512,7 +7868,13 @@ const commandTree = [
|
|
|
7512
7868
|
{
|
|
7513
7869
|
name: "<role>",
|
|
7514
7870
|
type: "string",
|
|
7515
|
-
required: true
|
|
7871
|
+
required: true,
|
|
7872
|
+
choices: [
|
|
7873
|
+
"owner",
|
|
7874
|
+
"admin",
|
|
7875
|
+
"editor",
|
|
7876
|
+
"viewer"
|
|
7877
|
+
]
|
|
7516
7878
|
},
|
|
7517
7879
|
{
|
|
7518
7880
|
name: "--org",
|
|
@@ -7703,7 +8065,10 @@ function readLinkedProject() {
|
|
|
7703
8065
|
try {
|
|
7704
8066
|
const raw = readFileSync(filePath, "utf8");
|
|
7705
8067
|
const data = JSON.parse(raw);
|
|
7706
|
-
if (data.
|
|
8068
|
+
if (typeof data.projectId === "string" && data.projectId.length > 0) return {
|
|
8069
|
+
orgId: typeof data.orgId === "string" && data.orgId.length > 0 ? data.orgId : null,
|
|
8070
|
+
projectId: data.projectId
|
|
8071
|
+
};
|
|
7707
8072
|
return null;
|
|
7708
8073
|
} catch {
|
|
7709
8074
|
return null;
|
|
@@ -7756,7 +8121,7 @@ const linkCommand = {
|
|
|
7756
8121
|
});
|
|
7757
8122
|
return;
|
|
7758
8123
|
}
|
|
7759
|
-
const orgId = getStoredOrgId() ??
|
|
8124
|
+
const orgId = getStoredOrgId() ?? null;
|
|
7760
8125
|
const dir = join(process.cwd(), ANYTHING_DIR$1);
|
|
7761
8126
|
mkdirSync(dir, { recursive: true });
|
|
7762
8127
|
writeFileSync(join(dir, PROJECT_FILE), JSON.stringify({
|
|
@@ -7785,19 +8150,23 @@ const unlinkCommand = {
|
|
|
7785
8150
|
handler: (argv) => {
|
|
7786
8151
|
const command = "unlink";
|
|
7787
8152
|
const dir = join(process.cwd(), ANYTHING_DIR$1);
|
|
7788
|
-
|
|
8153
|
+
const projectFile = getProjectFilePath();
|
|
8154
|
+
if (!existsSync(projectFile)) {
|
|
7789
8155
|
outputError({
|
|
7790
8156
|
argv,
|
|
7791
8157
|
command,
|
|
7792
8158
|
error: {
|
|
7793
|
-
message: "No
|
|
8159
|
+
message: "No linked project found in current directory.",
|
|
7794
8160
|
status: null
|
|
7795
8161
|
},
|
|
7796
8162
|
exitCode: 3
|
|
7797
8163
|
});
|
|
7798
8164
|
return;
|
|
7799
8165
|
}
|
|
7800
|
-
rmSync(
|
|
8166
|
+
rmSync(projectFile);
|
|
8167
|
+
try {
|
|
8168
|
+
if (existsSync(dir) && readdirSync(dir).length === 0) rmSync(dir, { recursive: true });
|
|
8169
|
+
} catch {}
|
|
7801
8170
|
if (outputSuccess({
|
|
7802
8171
|
argv,
|
|
7803
8172
|
command,
|
|
@@ -7999,12 +8368,19 @@ const llmContextCommand = {
|
|
|
7999
8368
|
|
|
8000
8369
|
//#endregion
|
|
8001
8370
|
//#region src/commands/members.ts
|
|
8371
|
+
const MEMBER_ROLE_CHOICES = [
|
|
8372
|
+
"owner",
|
|
8373
|
+
"admin",
|
|
8374
|
+
"editor",
|
|
8375
|
+
"viewer"
|
|
8376
|
+
];
|
|
8377
|
+
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
8002
8378
|
const membersListCommand = {
|
|
8003
8379
|
command: "list",
|
|
8004
8380
|
describe: "List organization members and pending invites",
|
|
8005
8381
|
builder: (yargs) => yargs.option("org", {
|
|
8006
8382
|
type: "string",
|
|
8007
|
-
describe: "Organization ID"
|
|
8383
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8008
8384
|
}).example("anything members list --org org_123", "List members"),
|
|
8009
8385
|
handler: async (argv) => {
|
|
8010
8386
|
const command = "members list";
|
|
@@ -8093,13 +8469,26 @@ const membersInviteCommand = {
|
|
|
8093
8469
|
describe: "Email address to invite"
|
|
8094
8470
|
}).option("org", {
|
|
8095
8471
|
type: "string",
|
|
8096
|
-
describe: "Organization ID"
|
|
8472
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8097
8473
|
}).option("role", {
|
|
8098
8474
|
type: "string",
|
|
8099
|
-
|
|
8475
|
+
choices: MEMBER_ROLE_CHOICES,
|
|
8476
|
+
describe: "Role to assign: owner, admin, editor, or viewer"
|
|
8100
8477
|
}).example("anything members invite user@example.com --org org_123", "Invite a member"),
|
|
8101
8478
|
handler: async (argv) => {
|
|
8102
8479
|
const command = "members invite";
|
|
8480
|
+
if (!EMAIL_PATTERN.test(argv.email)) {
|
|
8481
|
+
outputError({
|
|
8482
|
+
argv,
|
|
8483
|
+
command,
|
|
8484
|
+
error: {
|
|
8485
|
+
message: `Invalid email address: "${argv.email}".`,
|
|
8486
|
+
status: null
|
|
8487
|
+
},
|
|
8488
|
+
exitCode: 2
|
|
8489
|
+
});
|
|
8490
|
+
return;
|
|
8491
|
+
}
|
|
8103
8492
|
const config = resolveConfig({
|
|
8104
8493
|
dev: argv.dev,
|
|
8105
8494
|
apiUrl: argv.apiUrl
|
|
@@ -8179,7 +8568,7 @@ const membersRemoveCommand = {
|
|
|
8179
8568
|
describe: "Email address of the member to remove"
|
|
8180
8569
|
}).option("org", {
|
|
8181
8570
|
type: "string",
|
|
8182
|
-
describe: "Organization ID"
|
|
8571
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8183
8572
|
}).option("yes", {
|
|
8184
8573
|
type: "boolean",
|
|
8185
8574
|
default: false,
|
|
@@ -8277,10 +8666,11 @@ const membersRoleCommand = {
|
|
|
8277
8666
|
}).positional("role", {
|
|
8278
8667
|
type: "string",
|
|
8279
8668
|
demandOption: true,
|
|
8280
|
-
|
|
8669
|
+
choices: MEMBER_ROLE_CHOICES,
|
|
8670
|
+
describe: "New role: owner, admin, editor, or viewer"
|
|
8281
8671
|
}).option("org", {
|
|
8282
8672
|
type: "string",
|
|
8283
|
-
describe: "Organization ID"
|
|
8673
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8284
8674
|
}).example("anything members role user@example.com admin --org org_123", "Change role to admin"),
|
|
8285
8675
|
handler: async (argv) => {
|
|
8286
8676
|
const command = "members role";
|
|
@@ -8317,6 +8707,19 @@ const membersRoleCommand = {
|
|
|
8317
8707
|
});
|
|
8318
8708
|
return;
|
|
8319
8709
|
}
|
|
8710
|
+
if (argv["dry-run"]) {
|
|
8711
|
+
outputDryRun({
|
|
8712
|
+
argv,
|
|
8713
|
+
command,
|
|
8714
|
+
plannedActions: [{
|
|
8715
|
+
action: "update_member_role",
|
|
8716
|
+
org: orgResult.orgId,
|
|
8717
|
+
email: argv.email,
|
|
8718
|
+
role: argv.role
|
|
8719
|
+
}]
|
|
8720
|
+
});
|
|
8721
|
+
return;
|
|
8722
|
+
}
|
|
8320
8723
|
const result = await new AnythingApiClient(config.value).updateMemberRole({
|
|
8321
8724
|
organizationId: orgResult.orgId,
|
|
8322
8725
|
email: argv.email,
|
|
@@ -8625,20 +9028,28 @@ const orgsCommand = {
|
|
|
8625
9028
|
|
|
8626
9029
|
//#endregion
|
|
8627
9030
|
//#region src/stream.ts
|
|
9031
|
+
function resultErrorMessage(error) {
|
|
9032
|
+
if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
|
|
9033
|
+
return "Operation failed";
|
|
9034
|
+
}
|
|
8628
9035
|
function createEmitter(argv) {
|
|
8629
9036
|
if (argv.quiet) return (_event) => {};
|
|
8630
9037
|
if (argv.json) return (event) => {
|
|
8631
9038
|
printNdjson(event);
|
|
8632
9039
|
};
|
|
8633
9040
|
return (event) => {
|
|
8634
|
-
if (event.type === "progress")
|
|
9041
|
+
if (event.type === "progress") {
|
|
9042
|
+
printStreamMarker(event.status === "complete" ? "done" : "progress", event.message ?? `${event.step}...`);
|
|
9043
|
+
return;
|
|
9044
|
+
}
|
|
9045
|
+
if (event.type === "result" && !event.ok) printError(`[error] ${resultErrorMessage(event.error)}`);
|
|
8635
9046
|
};
|
|
8636
9047
|
}
|
|
8637
9048
|
|
|
8638
9049
|
//#endregion
|
|
8639
9050
|
//#region src/watch-generation.ts
|
|
8640
9051
|
const TIMEOUT_MS = 300 * 1e3;
|
|
8641
|
-
const POLL_INTERVAL_MS
|
|
9052
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
8642
9053
|
const TERMINAL_SUCCESS_STATUSES = new Set(["COMPLETED", "VALID"]);
|
|
8643
9054
|
const TERMINAL_FAILURE_STATUSES = new Set([
|
|
8644
9055
|
"INVALID",
|
|
@@ -8762,7 +9173,7 @@ async function pollUntilTerminal({ client, projectGroupId, emit, sleepFn = sleep
|
|
|
8762
9173
|
while (Date.now() < deadlineMs) {
|
|
8763
9174
|
const result = await client.getProjectStatus({ projectGroupId });
|
|
8764
9175
|
if (result.isErr()) {
|
|
8765
|
-
await sleepFn(POLL_INTERVAL_MS
|
|
9176
|
+
await sleepFn(POLL_INTERVAL_MS);
|
|
8766
9177
|
continue;
|
|
8767
9178
|
}
|
|
8768
9179
|
const { status } = result.value;
|
|
@@ -8786,7 +9197,7 @@ async function pollUntilTerminal({ client, projectGroupId, emit, sleepFn = sleep
|
|
|
8786
9197
|
});
|
|
8787
9198
|
return false;
|
|
8788
9199
|
}
|
|
8789
|
-
await sleepFn(POLL_INTERVAL_MS
|
|
9200
|
+
await sleepFn(POLL_INTERVAL_MS);
|
|
8790
9201
|
}
|
|
8791
9202
|
emit({
|
|
8792
9203
|
type: "result",
|
|
@@ -8845,7 +9256,11 @@ const createCommand = {
|
|
|
8845
9256
|
}).option("name", {
|
|
8846
9257
|
type: "string",
|
|
8847
9258
|
describe: "App name (optional)"
|
|
8848
|
-
}).
|
|
9259
|
+
}).option("wait", {
|
|
9260
|
+
type: "boolean",
|
|
9261
|
+
default: true,
|
|
9262
|
+
describe: "Wait for generation to complete (use --no-wait to skip)"
|
|
9263
|
+
}).example("anything projects create --prompt \"Build a todo app\"", "Create an app using your saved organization").example("anything projects create --org org_1 --prompt \"Build a todo app\"", "Create an app in a specific organization").example("cat prompt.txt | anything projects create", "Create an app from stdin").example("anything projects create --prompt \"Build a todo app\" --no-wait --json", "Create an app and return immediately without streaming"),
|
|
8849
9264
|
handler: async (argv) => {
|
|
8850
9265
|
const config = resolveConfig({
|
|
8851
9266
|
dev: argv.dev,
|
|
@@ -8934,6 +9349,25 @@ const createCommand = {
|
|
|
8934
9349
|
status: "complete",
|
|
8935
9350
|
message: "Project created"
|
|
8936
9351
|
});
|
|
9352
|
+
if (!argv.wait) {
|
|
9353
|
+
if (argv.quiet) {
|
|
9354
|
+
console.log(result.value.projectGroupId);
|
|
9355
|
+
return;
|
|
9356
|
+
}
|
|
9357
|
+
if (argv.json) {
|
|
9358
|
+
printNdjson({
|
|
9359
|
+
type: "result",
|
|
9360
|
+
ok: true,
|
|
9361
|
+
data: result.value
|
|
9362
|
+
});
|
|
9363
|
+
return;
|
|
9364
|
+
}
|
|
9365
|
+
printStreamMarker("done", `project ${result.value.projectGroupId} created`);
|
|
9366
|
+
printSuccess("App created! Generation enqueued.");
|
|
9367
|
+
printLabel("Project Group ID", result.value.projectGroupId);
|
|
9368
|
+
printLabel("Revision ID", result.value.revisionId);
|
|
9369
|
+
return;
|
|
9370
|
+
}
|
|
8937
9371
|
emit({
|
|
8938
9372
|
type: "progress",
|
|
8939
9373
|
step: "generating",
|
|
@@ -9055,7 +9489,10 @@ const publishStatusCommand = {
|
|
|
9055
9489
|
}).example("anything projects publish status <project-id> <deployment-id>", "Check a deployment later").example("anything projects publish status <project-id> <deployment-id> --json", "Return deployment status in JSON"),
|
|
9056
9490
|
handler: async (argv) => {
|
|
9057
9491
|
const command = "projects publish status";
|
|
9058
|
-
const config = resolveConfig({
|
|
9492
|
+
const config = resolveConfig({
|
|
9493
|
+
dev: argv.dev,
|
|
9494
|
+
apiUrl: argv.apiUrl
|
|
9495
|
+
});
|
|
9059
9496
|
if (config.isErr()) {
|
|
9060
9497
|
outputError({
|
|
9061
9498
|
argv,
|
|
@@ -9079,14 +9516,23 @@ const publishStatusCommand = {
|
|
|
9079
9516
|
}
|
|
9080
9517
|
const { deployment } = result.value;
|
|
9081
9518
|
if (deployment.status === "FAILED") {
|
|
9082
|
-
|
|
9083
|
-
|
|
9519
|
+
const failure = getDeploymentError({
|
|
9520
|
+
result: {
|
|
9521
|
+
outcome: "completed",
|
|
9522
|
+
deployment
|
|
9523
|
+
},
|
|
9524
|
+
statusCommand: `anything deployments logs ${argv.deploymentId}`
|
|
9525
|
+
});
|
|
9526
|
+
outputError({
|
|
9084
9527
|
argv,
|
|
9085
9528
|
command,
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9529
|
+
error: {
|
|
9530
|
+
message: failure?.message ?? "Deployment failed (no logs available).",
|
|
9531
|
+
status: null
|
|
9532
|
+
},
|
|
9533
|
+
hint: `Inspect the full build logs with: anything deployments logs ${argv.deploymentId}`,
|
|
9534
|
+
exitCode: failure?.exitCode ?? 1
|
|
9535
|
+
});
|
|
9090
9536
|
return;
|
|
9091
9537
|
}
|
|
9092
9538
|
if (outputSuccess({
|
|
@@ -9338,7 +9784,7 @@ const list$1 = {
|
|
|
9338
9784
|
describe: "The project ID"
|
|
9339
9785
|
}).example("anything projects files list <id>", "List the files available in a project"),
|
|
9340
9786
|
handler: async (argv) => {
|
|
9341
|
-
const command = "files list";
|
|
9787
|
+
const command = "projects files list";
|
|
9342
9788
|
const config = resolveConfig({
|
|
9343
9789
|
dev: argv.dev,
|
|
9344
9790
|
apiUrl: argv.apiUrl
|
|
@@ -9393,7 +9839,7 @@ const get$1 = {
|
|
|
9393
9839
|
describe: "The file path"
|
|
9394
9840
|
}).example("anything projects files get <id> app/page.tsx", "Print a file to stdout"),
|
|
9395
9841
|
handler: async (argv) => {
|
|
9396
|
-
const command = "files get";
|
|
9842
|
+
const command = "projects files get";
|
|
9397
9843
|
const config = resolveConfig({
|
|
9398
9844
|
dev: argv.dev,
|
|
9399
9845
|
apiUrl: argv.apiUrl
|
|
@@ -9731,7 +10177,10 @@ const infoCommand = {
|
|
|
9731
10177
|
printLabel("Published URL", latestPublishedUrl);
|
|
9732
10178
|
printLabel("Created", new Date(info.createdAt).toLocaleString());
|
|
9733
10179
|
printLabel("Updated", new Date(info.updatedAt).toLocaleString());
|
|
9734
|
-
for (const url of info.publishedUrls)
|
|
10180
|
+
for (const url of info.publishedUrls) {
|
|
10181
|
+
if (url === latestPublishedUrl) continue;
|
|
10182
|
+
printLabel("Other Published URL", url);
|
|
10183
|
+
}
|
|
9735
10184
|
if (info.files.length > 0) {
|
|
9736
10185
|
console.log();
|
|
9737
10186
|
printTable({
|
|
@@ -10006,6 +10455,96 @@ const logsCommand = {
|
|
|
10006
10455
|
}
|
|
10007
10456
|
};
|
|
10008
10457
|
|
|
10458
|
+
//#endregion
|
|
10459
|
+
//#region src/format-assistant-message.ts
|
|
10460
|
+
const NAMED_ENTITIES = {
|
|
10461
|
+
""": "\"",
|
|
10462
|
+
"'": "'",
|
|
10463
|
+
"'": "'",
|
|
10464
|
+
"<": "<",
|
|
10465
|
+
">": ">",
|
|
10466
|
+
" ": " "
|
|
10467
|
+
};
|
|
10468
|
+
function decodeEntities(input) {
|
|
10469
|
+
return input.replace(/&(?:quot|apos|#39|lt|gt|nbsp);/g, (m) => NAMED_ENTITIES[m] ?? m).replace(/&/g, "&");
|
|
10470
|
+
}
|
|
10471
|
+
function stripTags(input) {
|
|
10472
|
+
return input.replace(/<[^>]+>/g, "");
|
|
10473
|
+
}
|
|
10474
|
+
function parseAttrs(attrString) {
|
|
10475
|
+
const attrs = {};
|
|
10476
|
+
const re = /([a-zA-Z][\w-]*)="([^"]*)"/g;
|
|
10477
|
+
let match;
|
|
10478
|
+
while ((match = re.exec(attrString)) !== null) {
|
|
10479
|
+
const [, key, value] = match;
|
|
10480
|
+
if (key !== void 0 && value !== void 0) attrs[key] = value;
|
|
10481
|
+
}
|
|
10482
|
+
return attrs;
|
|
10483
|
+
}
|
|
10484
|
+
function firstLine(text) {
|
|
10485
|
+
return (text.split("\n").map((l) => l.trim()).find(Boolean) ?? "").replace(/\*\*/g, "");
|
|
10486
|
+
}
|
|
10487
|
+
function indent(text) {
|
|
10488
|
+
return text.split("\n").map((l) => ` ${l}`).join("\n");
|
|
10489
|
+
}
|
|
10490
|
+
function parseTodos(raw) {
|
|
10491
|
+
if (!raw) return [];
|
|
10492
|
+
try {
|
|
10493
|
+
const parsed = JSON.parse(decodeEntities(raw));
|
|
10494
|
+
if (!Array.isArray(parsed)) return [];
|
|
10495
|
+
return parsed.filter((t) => !!t && typeof t === "object" && typeof t.content === "string").map((t) => ({
|
|
10496
|
+
content: t.content,
|
|
10497
|
+
status: typeof t.status === "string" ? t.status : "pending"
|
|
10498
|
+
}));
|
|
10499
|
+
} catch {
|
|
10500
|
+
return [];
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
function renderBlock(attrs) {
|
|
10504
|
+
const uiType = attrs.uiType ?? "block";
|
|
10505
|
+
const text = decodeEntities(attrs.text ?? "").trim();
|
|
10506
|
+
const subtext = decodeEntities(attrs.subtext ?? "").trim();
|
|
10507
|
+
if (uiType === "todo-list") {
|
|
10508
|
+
const lines = [`[plan] ${text || "Plan"}${subtext ? ` — ${subtext}` : ""}`];
|
|
10509
|
+
for (const todo of parseTodos(attrs.todos)) {
|
|
10510
|
+
const box = todo.status === "completed" ? "[x]" : todo.status === "in_progress" ? "[~]" : "[ ]";
|
|
10511
|
+
lines.push(` ${box} ${todo.content}`);
|
|
10512
|
+
}
|
|
10513
|
+
return lines.join("\n");
|
|
10514
|
+
}
|
|
10515
|
+
if (uiType === "thinking") {
|
|
10516
|
+
const summary = firstLine(subtext) || text;
|
|
10517
|
+
return summary ? `[thinking] ${summary}` : null;
|
|
10518
|
+
}
|
|
10519
|
+
if (uiType === "database") {
|
|
10520
|
+
const code = decodeEntities(attrs.code ?? "").trim();
|
|
10521
|
+
const head = `[database] ${text || "change"}`;
|
|
10522
|
+
return code ? `${head}\n${indent(code)}` : head;
|
|
10523
|
+
}
|
|
10524
|
+
const parts = [text, subtext].filter(Boolean);
|
|
10525
|
+
if (parts.length === 0) return null;
|
|
10526
|
+
return `[${uiType}] ${parts.join(" — ")}`;
|
|
10527
|
+
}
|
|
10528
|
+
function formatAssistantMessage(raw) {
|
|
10529
|
+
const blockRe = /<file-based-block\b([^>]*)>([\s\S]*?)<\/file-based-block>/g;
|
|
10530
|
+
const segments = [];
|
|
10531
|
+
let lastIndex = 0;
|
|
10532
|
+
let hadBlock = false;
|
|
10533
|
+
let match;
|
|
10534
|
+
while ((match = blockRe.exec(raw)) !== null) {
|
|
10535
|
+
hadBlock = true;
|
|
10536
|
+
const between = stripTags(raw.slice(lastIndex, match.index)).trim();
|
|
10537
|
+
if (between) segments.push(decodeEntities(between));
|
|
10538
|
+
const rendered = renderBlock(parseAttrs(match[1] ?? ""));
|
|
10539
|
+
if (rendered) segments.push(rendered);
|
|
10540
|
+
lastIndex = blockRe.lastIndex;
|
|
10541
|
+
}
|
|
10542
|
+
if (!hadBlock) return decodeEntities(stripTags(raw)).trim();
|
|
10543
|
+
const tail = stripTags(raw.slice(lastIndex)).trim();
|
|
10544
|
+
if (tail) segments.push(decodeEntities(tail));
|
|
10545
|
+
return segments.filter(Boolean).join("\n");
|
|
10546
|
+
}
|
|
10547
|
+
|
|
10009
10548
|
//#endregion
|
|
10010
10549
|
//#region src/commands/messages.ts
|
|
10011
10550
|
const COMMAND$9 = "projects messages";
|
|
@@ -10014,7 +10553,13 @@ function formatMessage(msg) {
|
|
|
10014
10553
|
const status = msg.status === "VALID" ? styleText("green", msg.status) : msg.status === "BUILDING" ? styleText("yellow", msg.status) : styleText("red", msg.status);
|
|
10015
10554
|
console.log(styleText("dim", `─── ${time} ─── ${status} ───`));
|
|
10016
10555
|
if (msg.userMessage) console.log(styleText("bold", "You: ") + msg.userMessage);
|
|
10017
|
-
if (msg.assistantMessage)
|
|
10556
|
+
if (msg.assistantMessage) {
|
|
10557
|
+
const text = formatAssistantMessage(msg.assistantMessage);
|
|
10558
|
+
if (text) {
|
|
10559
|
+
console.log(styleText("bold", "Assistant:"));
|
|
10560
|
+
console.log(text);
|
|
10561
|
+
}
|
|
10562
|
+
}
|
|
10018
10563
|
console.log();
|
|
10019
10564
|
}
|
|
10020
10565
|
const messagesCommand = {
|
|
@@ -10061,12 +10606,15 @@ const messagesCommand = {
|
|
|
10061
10606
|
});
|
|
10062
10607
|
return;
|
|
10063
10608
|
}
|
|
10609
|
+
const { messages } = result.value;
|
|
10064
10610
|
if (outputSuccess({
|
|
10065
10611
|
argv,
|
|
10066
10612
|
command: COMMAND$9,
|
|
10067
|
-
data:
|
|
10613
|
+
data: { messages: messages.map((msg) => ({
|
|
10614
|
+
...msg,
|
|
10615
|
+
assistantText: msg.assistantMessage ? formatAssistantMessage(msg.assistantMessage) : null
|
|
10616
|
+
})) }
|
|
10068
10617
|
})) return;
|
|
10069
|
-
const { messages } = result.value;
|
|
10070
10618
|
if (messages.length === 0) {
|
|
10071
10619
|
console.log("No messages found.");
|
|
10072
10620
|
return;
|
|
@@ -10223,6 +10771,11 @@ const renameCommand = {
|
|
|
10223
10771
|
|
|
10224
10772
|
//#endregion
|
|
10225
10773
|
//#region src/commands/secrets.ts
|
|
10774
|
+
const secretEnvironmentChoices = [
|
|
10775
|
+
"development",
|
|
10776
|
+
"preview",
|
|
10777
|
+
"production"
|
|
10778
|
+
];
|
|
10226
10779
|
const add = {
|
|
10227
10780
|
command: "add <projectId>",
|
|
10228
10781
|
describe: "Add a secret to an app",
|
|
@@ -10239,10 +10792,11 @@ const add = {
|
|
|
10239
10792
|
describe: "Secret value. If omitted, reads stdin when piped."
|
|
10240
10793
|
}).option("env", {
|
|
10241
10794
|
type: "string",
|
|
10242
|
-
|
|
10795
|
+
choices: secretEnvironmentChoices,
|
|
10796
|
+
describe: "Target environment for the secret"
|
|
10243
10797
|
}).example("anything projects secrets add <id> --name KEY --value \"secret\"", "Add a secret from an inline value").example("cat secret.txt | anything projects secrets add <id> --name KEY", "Read a secret value from stdin"),
|
|
10244
10798
|
handler: async (argv) => {
|
|
10245
|
-
const command = "secrets add";
|
|
10799
|
+
const command = "projects secrets add";
|
|
10246
10800
|
if (argv["dry-run"]) {
|
|
10247
10801
|
outputDryRun({
|
|
10248
10802
|
argv,
|
|
@@ -10251,7 +10805,7 @@ const add = {
|
|
|
10251
10805
|
action: "add_secret",
|
|
10252
10806
|
projectGroupId: argv.projectId,
|
|
10253
10807
|
name: argv.name,
|
|
10254
|
-
...argv.env ? { environment: argv.env } : {}
|
|
10808
|
+
...argv.env ? { environment: argv.env.toUpperCase() } : {}
|
|
10255
10809
|
}]
|
|
10256
10810
|
});
|
|
10257
10811
|
return;
|
|
@@ -10293,7 +10847,7 @@ const add = {
|
|
|
10293
10847
|
projectGroupId: argv.projectId,
|
|
10294
10848
|
displayName: argv.name,
|
|
10295
10849
|
value: valueResult.value,
|
|
10296
|
-
environment: argv.env
|
|
10850
|
+
environment: argv.env ? argv.env.toUpperCase() : null
|
|
10297
10851
|
});
|
|
10298
10852
|
if (result.isErr()) {
|
|
10299
10853
|
outputError({
|
|
@@ -10327,18 +10881,34 @@ const remove = {
|
|
|
10327
10881
|
type: "string",
|
|
10328
10882
|
demandOption: true,
|
|
10329
10883
|
describe: "The secret ID to remove"
|
|
10330
|
-
}).
|
|
10884
|
+
}).option("yes", {
|
|
10885
|
+
type: "boolean",
|
|
10886
|
+
default: false,
|
|
10887
|
+
describe: "Skip confirmation"
|
|
10888
|
+
}).example("anything projects secrets remove <project-id> <secret-id> --dry-run", "Preview a secret removal").example("anything projects secrets remove <project-id> <secret-id> --yes", "Delete a secret"),
|
|
10331
10889
|
handler: async (argv) => {
|
|
10332
|
-
const command = "secrets remove";
|
|
10890
|
+
const command = "projects secrets remove";
|
|
10333
10891
|
if (argv["dry-run"]) {
|
|
10334
10892
|
outputDryRun({
|
|
10335
10893
|
argv,
|
|
10336
10894
|
command,
|
|
10337
|
-
plannedActions: [{
|
|
10338
|
-
action: "remove_secret",
|
|
10339
|
-
projectGroupId: argv.projectId,
|
|
10340
|
-
secretId: argv.secretId
|
|
10341
|
-
}]
|
|
10895
|
+
plannedActions: [{
|
|
10896
|
+
action: "remove_secret",
|
|
10897
|
+
projectGroupId: argv.projectId,
|
|
10898
|
+
secretId: argv.secretId
|
|
10899
|
+
}]
|
|
10900
|
+
});
|
|
10901
|
+
return;
|
|
10902
|
+
}
|
|
10903
|
+
if (!argv.yes) {
|
|
10904
|
+
outputError({
|
|
10905
|
+
argv,
|
|
10906
|
+
command,
|
|
10907
|
+
error: {
|
|
10908
|
+
message: "Removing a secret is destructive. Pass --yes to confirm.",
|
|
10909
|
+
status: null
|
|
10910
|
+
},
|
|
10911
|
+
exitCode: 2
|
|
10342
10912
|
});
|
|
10343
10913
|
return;
|
|
10344
10914
|
}
|
|
@@ -10388,7 +10958,7 @@ const list = {
|
|
|
10388
10958
|
describe: "The project ID"
|
|
10389
10959
|
}).example("anything projects secrets list <project-id>", "List secrets for an app"),
|
|
10390
10960
|
handler: async (argv) => {
|
|
10391
|
-
const command = "secrets list";
|
|
10961
|
+
const command = "projects secrets list";
|
|
10392
10962
|
const config = resolveConfig({
|
|
10393
10963
|
dev: argv.dev,
|
|
10394
10964
|
apiUrl: argv.apiUrl
|
|
@@ -10515,272 +11085,41 @@ function parseSecrets({ secretArgs, environment }) {
|
|
|
10515
11085
|
environment
|
|
10516
11086
|
});
|
|
10517
11087
|
}
|
|
10518
|
-
return {
|
|
10519
|
-
ok: true,
|
|
10520
|
-
value: secrets
|
|
10521
|
-
};
|
|
10522
|
-
}
|
|
10523
|
-
function resolveSecretEnvironment(environment) {
|
|
10524
|
-
switch (environment) {
|
|
10525
|
-
case "development":
|
|
10526
|
-
case "preview":
|
|
10527
|
-
case "production": return environment;
|
|
10528
|
-
default: return null;
|
|
10529
|
-
}
|
|
10530
|
-
}
|
|
10531
|
-
const get = {
|
|
10532
|
-
command: "get [projectId]",
|
|
10533
|
-
describe: "Read project auth settings",
|
|
10534
|
-
builder: (yargs) => yargs.positional("projectId", {
|
|
10535
|
-
type: "string",
|
|
10536
|
-
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
10537
|
-
}).example("anything projects settings auth get <project-id>", "Inspect auth provider state for a project").example("anything projects settings auth get --json", "Return auth settings for the current project in JSON"),
|
|
10538
|
-
handler: async (argv) => {
|
|
10539
|
-
const command = "settings auth get";
|
|
10540
|
-
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
10541
|
-
if (projectGroupId === null) {
|
|
10542
|
-
outputError({
|
|
10543
|
-
argv,
|
|
10544
|
-
command,
|
|
10545
|
-
error: {
|
|
10546
|
-
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
10547
|
-
status: null
|
|
10548
|
-
},
|
|
10549
|
-
exitCode: 2
|
|
10550
|
-
});
|
|
10551
|
-
return;
|
|
10552
|
-
}
|
|
10553
|
-
const config = resolveConfig({
|
|
10554
|
-
dev: argv.dev,
|
|
10555
|
-
apiUrl: argv.apiUrl
|
|
10556
|
-
});
|
|
10557
|
-
if (config.isErr()) {
|
|
10558
|
-
outputError({
|
|
10559
|
-
argv,
|
|
10560
|
-
command,
|
|
10561
|
-
error: {
|
|
10562
|
-
message: config.error.message,
|
|
10563
|
-
status: null
|
|
10564
|
-
},
|
|
10565
|
-
exitCode: 4
|
|
10566
|
-
});
|
|
10567
|
-
return;
|
|
10568
|
-
}
|
|
10569
|
-
const result = await new AnythingApiClient(config.value).getProjectAuthSettings({ projectGroupId });
|
|
10570
|
-
if (result.isErr()) {
|
|
10571
|
-
outputError({
|
|
10572
|
-
argv,
|
|
10573
|
-
command,
|
|
10574
|
-
error: result.error
|
|
10575
|
-
});
|
|
10576
|
-
return;
|
|
10577
|
-
}
|
|
10578
|
-
if (outputSuccess({
|
|
10579
|
-
argv,
|
|
10580
|
-
command,
|
|
10581
|
-
data: result.value
|
|
10582
|
-
})) return;
|
|
10583
|
-
printAuthSettings(result.value);
|
|
10584
|
-
}
|
|
10585
|
-
};
|
|
10586
|
-
const set = {
|
|
10587
|
-
command: "set [projectId]",
|
|
10588
|
-
describe: "Update project auth settings for a provider",
|
|
10589
|
-
builder: (yargs) => yargs.positional("projectId", {
|
|
10590
|
-
type: "string",
|
|
10591
|
-
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
10592
|
-
}).option("provider", {
|
|
10593
|
-
choices: authProviderChoices,
|
|
10594
|
-
demandOption: true,
|
|
10595
|
-
describe: "The auth provider to update"
|
|
10596
|
-
}).option("enabled", {
|
|
10597
|
-
type: "boolean",
|
|
10598
|
-
demandOption: true,
|
|
10599
|
-
describe: "Whether to enable the provider. Use --no-enabled to disable it."
|
|
10600
|
-
}).option("secret", {
|
|
10601
|
-
type: "string",
|
|
10602
|
-
array: true,
|
|
10603
|
-
describe: "Provider secret in ENV_KEY=VALUE format. Repeat for multiple secrets."
|
|
10604
|
-
}).option("env", {
|
|
10605
|
-
choices: authEnvironmentChoices,
|
|
10606
|
-
default: "production",
|
|
10607
|
-
describe: "Environment for secrets passed via --secret"
|
|
10608
|
-
}).example("anything projects settings auth set <project-id> --provider google --enabled --secret GOOGLE_CLIENT_ID=abc --secret GOOGLE_CLIENT_SECRET=def", "Enable Google auth and store provider secrets").example("anything projects settings auth set <project-id> --provider email --no-enabled", "Disable email auth"),
|
|
10609
|
-
handler: async (argv) => {
|
|
10610
|
-
const command = "settings auth set";
|
|
10611
|
-
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
10612
|
-
if (projectGroupId === null) {
|
|
10613
|
-
outputError({
|
|
10614
|
-
argv,
|
|
10615
|
-
command,
|
|
10616
|
-
error: {
|
|
10617
|
-
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
10618
|
-
status: null
|
|
10619
|
-
},
|
|
10620
|
-
exitCode: 2
|
|
10621
|
-
});
|
|
10622
|
-
return;
|
|
10623
|
-
}
|
|
10624
|
-
const secretEnvironment = resolveSecretEnvironment(argv.env);
|
|
10625
|
-
if (secretEnvironment === null) {
|
|
10626
|
-
outputError({
|
|
10627
|
-
argv,
|
|
10628
|
-
command,
|
|
10629
|
-
error: {
|
|
10630
|
-
message: `Invalid --env value "${argv.env}".`,
|
|
10631
|
-
status: null
|
|
10632
|
-
},
|
|
10633
|
-
exitCode: 2
|
|
10634
|
-
});
|
|
10635
|
-
return;
|
|
10636
|
-
}
|
|
10637
|
-
const secretsResult = parseSecrets({
|
|
10638
|
-
secretArgs: argv.secret ?? [],
|
|
10639
|
-
environment: secretEnvironment
|
|
10640
|
-
});
|
|
10641
|
-
if (!secretsResult.ok) {
|
|
10642
|
-
outputError({
|
|
10643
|
-
argv,
|
|
10644
|
-
command,
|
|
10645
|
-
error: {
|
|
10646
|
-
message: secretsResult.error,
|
|
10647
|
-
status: null
|
|
10648
|
-
},
|
|
10649
|
-
exitCode: 2
|
|
10650
|
-
});
|
|
10651
|
-
return;
|
|
10652
|
-
}
|
|
10653
|
-
const config = resolveConfig({
|
|
10654
|
-
dev: argv.dev,
|
|
10655
|
-
apiUrl: argv.apiUrl
|
|
10656
|
-
});
|
|
10657
|
-
if (config.isErr()) {
|
|
10658
|
-
outputError({
|
|
10659
|
-
argv,
|
|
10660
|
-
command,
|
|
10661
|
-
error: {
|
|
10662
|
-
message: config.error.message,
|
|
10663
|
-
status: null
|
|
10664
|
-
},
|
|
10665
|
-
exitCode: 4
|
|
10666
|
-
});
|
|
10667
|
-
return;
|
|
10668
|
-
}
|
|
10669
|
-
const result = await new AnythingApiClient(config.value).updateProjectAuthSettings({
|
|
10670
|
-
projectGroupId,
|
|
10671
|
-
provider: argv.provider,
|
|
10672
|
-
enabled: argv.enabled,
|
|
10673
|
-
secrets: secretsResult.value,
|
|
10674
|
-
enableForAllModules: false
|
|
10675
|
-
});
|
|
10676
|
-
if (result.isErr()) {
|
|
10677
|
-
outputError({
|
|
10678
|
-
argv,
|
|
10679
|
-
command,
|
|
10680
|
-
error: result.error
|
|
10681
|
-
});
|
|
10682
|
-
return;
|
|
10683
|
-
}
|
|
10684
|
-
if (outputSuccess({
|
|
10685
|
-
argv,
|
|
10686
|
-
command,
|
|
10687
|
-
data: result.value
|
|
10688
|
-
})) return;
|
|
10689
|
-
printSuccess("Auth settings updated.");
|
|
10690
|
-
printAuthSettings(result.value);
|
|
10691
|
-
}
|
|
10692
|
-
};
|
|
10693
|
-
const authSettingsCommand = {
|
|
10694
|
-
command: "auth <command>",
|
|
10695
|
-
describe: "Manage auth-related project settings",
|
|
10696
|
-
builder: (yargs) => yargs.command(get).command(set).demandCommand(),
|
|
10697
|
-
handler: () => {}
|
|
10698
|
-
};
|
|
10699
|
-
|
|
10700
|
-
//#endregion
|
|
10701
|
-
//#region src/commands/settings.ts
|
|
10702
|
-
const settingsCommand = {
|
|
10703
|
-
command: "settings <command>",
|
|
10704
|
-
describe: "Inspect and update project settings",
|
|
10705
|
-
builder: (yargs) => yargs.command(authSettingsCommand).example("anything projects settings auth get <project-id>", "Inspect project auth settings").demandCommand(),
|
|
10706
|
-
handler: () => {}
|
|
10707
|
-
};
|
|
10708
|
-
|
|
10709
|
-
//#endregion
|
|
10710
|
-
//#region src/commands/submit.ts
|
|
10711
|
-
const POLL_INTERVAL_MS = 2e3;
|
|
10712
|
-
const POLL_TIMEOUT_MS = 6e4;
|
|
10713
|
-
async function waitForSubmission({ client, projectGroupId, submission }) {
|
|
10714
|
-
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
10715
|
-
let current = submission;
|
|
10716
|
-
while (current.status === "PENDING" && Date.now() < deadline) {
|
|
10717
|
-
const latestResult = await client.getProjectSubmission({
|
|
10718
|
-
projectGroupId,
|
|
10719
|
-
submissionId: current.id
|
|
10720
|
-
});
|
|
10721
|
-
if (latestResult.isErr()) return latestResult.map((value) => value.submission);
|
|
10722
|
-
current = latestResult.value.submission;
|
|
10723
|
-
if (current.status !== "PENDING") return latestResult.map((value) => value.submission);
|
|
10724
|
-
await setTimeout$1(POLL_INTERVAL_MS);
|
|
10725
|
-
}
|
|
10726
|
-
return ok(current);
|
|
10727
|
-
}
|
|
10728
|
-
function printSubmissionResult({ argv, command, pendingMessage, submission }) {
|
|
10729
|
-
const { projectGroupId: projectId, ...submissionRest } = submission;
|
|
10730
|
-
const submissionOut = {
|
|
10731
|
-
projectId,
|
|
10732
|
-
...submissionRest
|
|
10733
|
-
};
|
|
10734
|
-
if (submission.status === "FAILED") {
|
|
10735
|
-
printError(submission.errorMessage ?? "Submission failed.");
|
|
10736
|
-
process.exitCode = 1;
|
|
10737
|
-
return;
|
|
10738
|
-
}
|
|
10739
|
-
if (submission.status === "CREATED") {
|
|
10740
|
-
if (outputSuccess({
|
|
10741
|
-
argv,
|
|
10742
|
-
command,
|
|
10743
|
-
data: {
|
|
10744
|
-
success: true,
|
|
10745
|
-
submission: submissionOut
|
|
10746
|
-
},
|
|
10747
|
-
primaryId: submission.id
|
|
10748
|
-
})) return;
|
|
10749
|
-
printSuccess("App Store submission is ready.");
|
|
10750
|
-
printLabel("Submission ID", submission.id);
|
|
10751
|
-
printLabel("Launch URL", submission.launchUrl);
|
|
10752
|
-
printLabel("Auth URL", submission.authUrl);
|
|
10753
|
-
printLabel("Expires At", submission.expiresAt);
|
|
10754
|
-
return;
|
|
10755
|
-
}
|
|
10756
|
-
if (outputSuccess({
|
|
10757
|
-
argv,
|
|
10758
|
-
command,
|
|
10759
|
-
data: {
|
|
10760
|
-
success: true,
|
|
10761
|
-
submission
|
|
10762
|
-
},
|
|
10763
|
-
primaryId: submission.id
|
|
10764
|
-
})) return;
|
|
10765
|
-
printSuccess(pendingMessage);
|
|
10766
|
-
printLabel("Submission ID", submission.id);
|
|
10767
|
-
printLabel("Status", submission.status);
|
|
10768
|
-
printLabel("Next step", "Expo is still preparing the launch flow. Run the command again in a moment.");
|
|
11088
|
+
return {
|
|
11089
|
+
ok: true,
|
|
11090
|
+
value: secrets
|
|
11091
|
+
};
|
|
10769
11092
|
}
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
11093
|
+
function resolveSecretEnvironment(environment) {
|
|
11094
|
+
switch (environment) {
|
|
11095
|
+
case "development":
|
|
11096
|
+
case "preview":
|
|
11097
|
+
case "production": return environment;
|
|
11098
|
+
default: return null;
|
|
11099
|
+
}
|
|
11100
|
+
}
|
|
11101
|
+
const get = {
|
|
11102
|
+
command: "get [projectId]",
|
|
11103
|
+
describe: "Read project auth settings",
|
|
10773
11104
|
builder: (yargs) => yargs.positional("projectId", {
|
|
10774
11105
|
type: "string",
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
}).positional("submissionId", {
|
|
10778
|
-
type: "string",
|
|
10779
|
-
demandOption: true,
|
|
10780
|
-
describe: "The submission ID"
|
|
10781
|
-
}).example("anything projects submit status <project-id> <submission-id>", "Check a submission later").example("anything projects submit status <project-id> <submission-id> --json", "Return the submission status in JSON"),
|
|
11106
|
+
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
11107
|
+
}).example("anything projects settings auth get <project-id>", "Inspect auth provider state for a project").example("anything projects settings auth get --json", "Return auth settings for the current project in JSON"),
|
|
10782
11108
|
handler: async (argv) => {
|
|
10783
|
-
const command = "projects
|
|
11109
|
+
const command = "projects settings auth get";
|
|
11110
|
+
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
11111
|
+
if (projectGroupId === null) {
|
|
11112
|
+
outputError({
|
|
11113
|
+
argv,
|
|
11114
|
+
command,
|
|
11115
|
+
error: {
|
|
11116
|
+
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
11117
|
+
status: null
|
|
11118
|
+
},
|
|
11119
|
+
exitCode: 2
|
|
11120
|
+
});
|
|
11121
|
+
return;
|
|
11122
|
+
}
|
|
10784
11123
|
const config = resolveConfig({
|
|
10785
11124
|
dev: argv.dev,
|
|
10786
11125
|
apiUrl: argv.apiUrl
|
|
@@ -10797,10 +11136,7 @@ const submitStatusCommand = {
|
|
|
10797
11136
|
});
|
|
10798
11137
|
return;
|
|
10799
11138
|
}
|
|
10800
|
-
const result = await new AnythingApiClient(config.value).
|
|
10801
|
-
projectGroupId: argv.projectId,
|
|
10802
|
-
submissionId: argv.submissionId
|
|
10803
|
-
});
|
|
11139
|
+
const result = await new AnythingApiClient(config.value).getProjectAuthSettings({ projectGroupId });
|
|
10804
11140
|
if (result.isErr()) {
|
|
10805
11141
|
outputError({
|
|
10806
11142
|
argv,
|
|
@@ -10809,102 +11145,151 @@ const submitStatusCommand = {
|
|
|
10809
11145
|
});
|
|
10810
11146
|
return;
|
|
10811
11147
|
}
|
|
10812
|
-
|
|
11148
|
+
if (outputSuccess({
|
|
10813
11149
|
argv,
|
|
10814
11150
|
command,
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
11151
|
+
data: result.value
|
|
11152
|
+
})) return;
|
|
11153
|
+
printAuthSettings(result.value);
|
|
10818
11154
|
}
|
|
10819
11155
|
};
|
|
10820
|
-
const
|
|
10821
|
-
command: "
|
|
10822
|
-
describe: "
|
|
10823
|
-
builder: (yargs) => yargs.
|
|
11156
|
+
const set = {
|
|
11157
|
+
command: "set [projectId]",
|
|
11158
|
+
describe: "Update project auth settings for a provider",
|
|
11159
|
+
builder: (yargs) => yargs.positional("projectId", {
|
|
10824
11160
|
type: "string",
|
|
11161
|
+
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
11162
|
+
}).option("provider", {
|
|
11163
|
+
choices: authProviderChoices,
|
|
10825
11164
|
demandOption: true,
|
|
10826
|
-
describe: "The
|
|
10827
|
-
}).option("
|
|
11165
|
+
describe: "The auth provider to update"
|
|
11166
|
+
}).option("enabled", {
|
|
11167
|
+
type: "boolean",
|
|
11168
|
+
demandOption: true,
|
|
11169
|
+
describe: "Whether to enable the provider. Use --no-enabled to disable it."
|
|
11170
|
+
}).option("secret", {
|
|
10828
11171
|
type: "string",
|
|
10829
|
-
|
|
10830
|
-
describe: "
|
|
10831
|
-
}).
|
|
11172
|
+
array: true,
|
|
11173
|
+
describe: "Provider secret in ENV_KEY=VALUE format. Repeat for multiple secrets."
|
|
11174
|
+
}).option("env", {
|
|
11175
|
+
choices: authEnvironmentChoices,
|
|
11176
|
+
default: "production",
|
|
11177
|
+
describe: "Environment for secrets passed via --secret"
|
|
11178
|
+
}).example("anything projects settings auth set <project-id> --provider google --enabled --secret GOOGLE_CLIENT_ID=abc --secret GOOGLE_CLIENT_SECRET=def", "Enable Google auth and store provider secrets").example("anything projects settings auth set <project-id> --provider email --no-enabled", "Disable email auth"),
|
|
10832
11179
|
handler: async (argv) => {
|
|
10833
|
-
const command = "projects
|
|
10834
|
-
|
|
11180
|
+
const command = "projects settings auth set";
|
|
11181
|
+
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
11182
|
+
if (projectGroupId === null) {
|
|
10835
11183
|
outputError({
|
|
10836
11184
|
argv,
|
|
10837
11185
|
command,
|
|
10838
11186
|
error: {
|
|
10839
|
-
message: "
|
|
11187
|
+
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
10840
11188
|
status: null
|
|
10841
11189
|
},
|
|
10842
11190
|
exitCode: 2
|
|
10843
11191
|
});
|
|
10844
11192
|
return;
|
|
10845
11193
|
}
|
|
10846
|
-
|
|
11194
|
+
const secretEnvironment = resolveSecretEnvironment(argv.env);
|
|
11195
|
+
if (secretEnvironment === null) {
|
|
10847
11196
|
outputError({
|
|
10848
11197
|
argv,
|
|
10849
11198
|
command,
|
|
10850
11199
|
error: {
|
|
10851
|
-
message: "
|
|
11200
|
+
message: `Invalid --env value "${argv.env}".`,
|
|
10852
11201
|
status: null
|
|
10853
11202
|
},
|
|
10854
11203
|
exitCode: 2
|
|
10855
11204
|
});
|
|
10856
11205
|
return;
|
|
10857
11206
|
}
|
|
10858
|
-
const
|
|
10859
|
-
|
|
10860
|
-
|
|
11207
|
+
const secretsResult = parseSecrets({
|
|
11208
|
+
secretArgs: argv.secret ?? [],
|
|
11209
|
+
environment: secretEnvironment
|
|
10861
11210
|
});
|
|
10862
|
-
if (
|
|
11211
|
+
if (!secretsResult.ok) {
|
|
10863
11212
|
outputError({
|
|
10864
11213
|
argv,
|
|
10865
11214
|
command,
|
|
10866
11215
|
error: {
|
|
10867
|
-
message:
|
|
11216
|
+
message: secretsResult.error,
|
|
10868
11217
|
status: null
|
|
10869
11218
|
},
|
|
10870
|
-
exitCode:
|
|
11219
|
+
exitCode: 2
|
|
10871
11220
|
});
|
|
10872
11221
|
return;
|
|
10873
11222
|
}
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
11223
|
+
if (argv["dry-run"]) {
|
|
11224
|
+
outputDryRun({
|
|
11225
|
+
argv,
|
|
11226
|
+
command,
|
|
11227
|
+
plannedActions: [{
|
|
11228
|
+
action: "update_auth_settings",
|
|
11229
|
+
projectGroupId,
|
|
11230
|
+
provider: argv.provider,
|
|
11231
|
+
enabled: argv.enabled,
|
|
11232
|
+
environment: secretEnvironment,
|
|
11233
|
+
secretKeys: secretsResult.value.map((secret) => secret.envKey)
|
|
11234
|
+
}]
|
|
11235
|
+
});
|
|
11236
|
+
return;
|
|
11237
|
+
}
|
|
11238
|
+
const config = resolveConfig({
|
|
11239
|
+
dev: argv.dev,
|
|
11240
|
+
apiUrl: argv.apiUrl
|
|
10878
11241
|
});
|
|
10879
|
-
if (
|
|
11242
|
+
if (config.isErr()) {
|
|
10880
11243
|
outputError({
|
|
10881
11244
|
argv,
|
|
10882
11245
|
command,
|
|
10883
|
-
error:
|
|
11246
|
+
error: {
|
|
11247
|
+
message: config.error.message,
|
|
11248
|
+
status: null
|
|
11249
|
+
},
|
|
11250
|
+
exitCode: 4
|
|
10884
11251
|
});
|
|
10885
11252
|
return;
|
|
10886
11253
|
}
|
|
10887
|
-
const
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
11254
|
+
const result = await new AnythingApiClient(config.value).updateProjectAuthSettings({
|
|
11255
|
+
projectGroupId,
|
|
11256
|
+
provider: argv.provider,
|
|
11257
|
+
enabled: argv.enabled,
|
|
11258
|
+
secrets: secretsResult.value,
|
|
11259
|
+
enableForAllModules: false
|
|
10891
11260
|
});
|
|
10892
|
-
if (
|
|
11261
|
+
if (result.isErr()) {
|
|
10893
11262
|
outputError({
|
|
10894
11263
|
argv,
|
|
10895
11264
|
command,
|
|
10896
|
-
error:
|
|
11265
|
+
error: result.error
|
|
10897
11266
|
});
|
|
10898
11267
|
return;
|
|
10899
11268
|
}
|
|
10900
|
-
|
|
11269
|
+
if (outputSuccess({
|
|
10901
11270
|
argv,
|
|
10902
11271
|
command,
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
11272
|
+
data: result.value
|
|
11273
|
+
})) return;
|
|
11274
|
+
printSuccess("Auth settings updated.");
|
|
11275
|
+
printAuthSettings(result.value);
|
|
10906
11276
|
}
|
|
10907
11277
|
};
|
|
11278
|
+
const authSettingsCommand = {
|
|
11279
|
+
command: "auth <command>",
|
|
11280
|
+
describe: "Manage auth-related project settings",
|
|
11281
|
+
builder: (yargs) => yargs.command(get).command(set).demandCommand(),
|
|
11282
|
+
handler: () => {}
|
|
11283
|
+
};
|
|
11284
|
+
|
|
11285
|
+
//#endregion
|
|
11286
|
+
//#region src/commands/settings.ts
|
|
11287
|
+
const settingsCommand = {
|
|
11288
|
+
command: "settings <command>",
|
|
11289
|
+
describe: "Inspect and update project settings",
|
|
11290
|
+
builder: (yargs) => yargs.command(authSettingsCommand).example("anything projects settings auth get <project-id>", "Inspect project auth settings").demandCommand(),
|
|
11291
|
+
handler: () => {}
|
|
11292
|
+
};
|
|
10908
11293
|
|
|
10909
11294
|
//#endregion
|
|
10910
11295
|
//#region src/commands/unpublish.ts
|
|
@@ -10922,6 +11307,17 @@ const unpublishCommand = {
|
|
|
10922
11307
|
describe: "Confirm unpublishing without prompting"
|
|
10923
11308
|
}).example("anything projects unpublish <project-id> --yes", "Remove a published app from production").example("anything projects unpublish <project-id> --json --yes", "Unpublish an app and capture the result in JSON"),
|
|
10924
11309
|
handler: async (argv) => {
|
|
11310
|
+
if (argv["dry-run"]) {
|
|
11311
|
+
outputDryRun({
|
|
11312
|
+
argv,
|
|
11313
|
+
command: COMMAND$6,
|
|
11314
|
+
plannedActions: [{
|
|
11315
|
+
action: "unpublish_project",
|
|
11316
|
+
projectGroupId: argv.projectId
|
|
11317
|
+
}]
|
|
11318
|
+
});
|
|
11319
|
+
return;
|
|
11320
|
+
}
|
|
10925
11321
|
if (!argv.yes && !isNonInteractive(argv)) {
|
|
10926
11322
|
outputError({
|
|
10927
11323
|
argv,
|
|
@@ -10934,17 +11330,6 @@ const unpublishCommand = {
|
|
|
10934
11330
|
});
|
|
10935
11331
|
return;
|
|
10936
11332
|
}
|
|
10937
|
-
if (argv["dry-run"]) {
|
|
10938
|
-
outputDryRun({
|
|
10939
|
-
argv,
|
|
10940
|
-
command: COMMAND$6,
|
|
10941
|
-
plannedActions: [{
|
|
10942
|
-
action: "unpublish_project",
|
|
10943
|
-
projectGroupId: argv.projectId
|
|
10944
|
-
}]
|
|
10945
|
-
});
|
|
10946
|
-
return;
|
|
10947
|
-
}
|
|
10948
11333
|
const config = resolveConfig({
|
|
10949
11334
|
dev: argv.dev,
|
|
10950
11335
|
apiUrl: argv.apiUrl
|
|
@@ -11002,6 +11387,17 @@ const deleteProjectCommand = {
|
|
|
11002
11387
|
describe: "Confirm deletion without prompting"
|
|
11003
11388
|
}).example("anything projects delete <project-id> --yes", "Delete a project permanently").example("anything projects delete <project-id> --yes --json", "Delete a project and capture the result in JSON"),
|
|
11004
11389
|
handler: async (argv) => {
|
|
11390
|
+
if (argv["dry-run"]) {
|
|
11391
|
+
outputDryRun({
|
|
11392
|
+
argv,
|
|
11393
|
+
command: COMMAND$5,
|
|
11394
|
+
plannedActions: [{
|
|
11395
|
+
action: "delete_project",
|
|
11396
|
+
projectGroupId: argv.projectId
|
|
11397
|
+
}]
|
|
11398
|
+
});
|
|
11399
|
+
return;
|
|
11400
|
+
}
|
|
11005
11401
|
if (!argv.yes && !isNonInteractive(argv)) {
|
|
11006
11402
|
outputError({
|
|
11007
11403
|
argv,
|
|
@@ -11014,17 +11410,6 @@ const deleteProjectCommand = {
|
|
|
11014
11410
|
});
|
|
11015
11411
|
return;
|
|
11016
11412
|
}
|
|
11017
|
-
if (argv["dry-run"]) {
|
|
11018
|
-
outputDryRun({
|
|
11019
|
-
argv,
|
|
11020
|
-
command: COMMAND$5,
|
|
11021
|
-
plannedActions: [{
|
|
11022
|
-
action: "delete_project",
|
|
11023
|
-
projectGroupId: argv.projectId
|
|
11024
|
-
}]
|
|
11025
|
-
});
|
|
11026
|
-
return;
|
|
11027
|
-
}
|
|
11028
11413
|
const config = resolveConfig({
|
|
11029
11414
|
dev: argv.dev,
|
|
11030
11415
|
apiUrl: argv.apiUrl
|
|
@@ -11044,10 +11429,12 @@ const deleteProjectCommand = {
|
|
|
11044
11429
|
const startTime = performance.now();
|
|
11045
11430
|
const result = await new AnythingApiClient(config.value).deleteProject({ projectGroupId: argv.projectId });
|
|
11046
11431
|
if (result.isErr()) {
|
|
11432
|
+
const hint = result.error.status === 404 ? "If the project ID is correct, project deletion may not be enabled for your account." : void 0;
|
|
11047
11433
|
outputError({
|
|
11048
11434
|
argv,
|
|
11049
11435
|
command: COMMAND$5,
|
|
11050
|
-
error: result.error
|
|
11436
|
+
error: result.error,
|
|
11437
|
+
hint
|
|
11051
11438
|
});
|
|
11052
11439
|
return;
|
|
11053
11440
|
}
|
|
@@ -11153,11 +11540,16 @@ const projectsSetCommand = {
|
|
|
11153
11540
|
return;
|
|
11154
11541
|
}
|
|
11155
11542
|
setStoredProjectGroupId(result.value.id);
|
|
11156
|
-
if (
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11543
|
+
if (outputSuccess({
|
|
11544
|
+
argv,
|
|
11545
|
+
command: "projects set",
|
|
11546
|
+
data: {
|
|
11547
|
+
projectId: result.value.id,
|
|
11548
|
+
name: result.value.name
|
|
11549
|
+
},
|
|
11550
|
+
primaryId: result.value.id
|
|
11551
|
+
})) return;
|
|
11552
|
+
printSuccess(`Current project set to ${result.value.name} (${result.value.id})`);
|
|
11161
11553
|
}
|
|
11162
11554
|
};
|
|
11163
11555
|
const projectsUnsetCommand = {
|
|
@@ -11166,8 +11558,12 @@ const projectsUnsetCommand = {
|
|
|
11166
11558
|
builder: (yargs) => yargs.example("anything projects unset", "Clear the saved project"),
|
|
11167
11559
|
handler: (argv) => {
|
|
11168
11560
|
clearStoredProjectGroupId();
|
|
11169
|
-
if (
|
|
11170
|
-
|
|
11561
|
+
if (outputSuccess({
|
|
11562
|
+
argv,
|
|
11563
|
+
command: "projects unset",
|
|
11564
|
+
data: { projectId: null }
|
|
11565
|
+
})) return;
|
|
11566
|
+
printSuccess("Current project cleared.");
|
|
11171
11567
|
}
|
|
11172
11568
|
};
|
|
11173
11569
|
const projectsCommand = {
|
|
@@ -11181,7 +11577,8 @@ const projectsCommand = {
|
|
|
11181
11577
|
//#region src/commands/pull.ts
|
|
11182
11578
|
const ANYTHING_DIR = ".anything";
|
|
11183
11579
|
const FILES_DIR = "files";
|
|
11184
|
-
|
|
11580
|
+
const DEFAULT_TIMEOUT_SECONDS = 60;
|
|
11581
|
+
async function pullFiles({ client, projectGroupId, argv }) {
|
|
11185
11582
|
const listResult = await client.listProjectFiles({ projectGroupId });
|
|
11186
11583
|
if (listResult.isErr()) {
|
|
11187
11584
|
printApiError(listResult.error);
|
|
@@ -11190,6 +11587,7 @@ async function pullFiles({ client, projectGroupId }) {
|
|
|
11190
11587
|
}
|
|
11191
11588
|
const filesDir = join(process.cwd(), ANYTHING_DIR, FILES_DIR);
|
|
11192
11589
|
if (!existsSync(filesDir)) mkdirSync(filesDir, { recursive: true });
|
|
11590
|
+
const totalFiles = listResult.value.files.length;
|
|
11193
11591
|
const pulled = [];
|
|
11194
11592
|
for (const file of listResult.value.files) {
|
|
11195
11593
|
const fileResult = await client.getProjectFile({
|
|
@@ -11205,6 +11603,12 @@ async function pullFiles({ client, projectGroupId }) {
|
|
|
11205
11603
|
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
11206
11604
|
writeFileSync(destPath, fileResult.value.file.content);
|
|
11207
11605
|
pulled.push(file.path);
|
|
11606
|
+
if (argv.json) printNdjson({
|
|
11607
|
+
type: "progress",
|
|
11608
|
+
file: file.path,
|
|
11609
|
+
completed: pulled.length,
|
|
11610
|
+
total: totalFiles
|
|
11611
|
+
});
|
|
11208
11612
|
}
|
|
11209
11613
|
return pulled;
|
|
11210
11614
|
}
|
|
@@ -11231,8 +11635,13 @@ const pullCommand = {
|
|
|
11231
11635
|
}).option("env", {
|
|
11232
11636
|
type: "boolean",
|
|
11233
11637
|
describe: "Write secret names to .env.example only"
|
|
11638
|
+
}).option("timeout", {
|
|
11639
|
+
type: "number",
|
|
11640
|
+
default: DEFAULT_TIMEOUT_SECONDS,
|
|
11641
|
+
describe: "Request timeout in seconds"
|
|
11234
11642
|
}).example("anything pull", "Pull files + secret names").example("anything pull --files", "Pull project files only").example("anything pull --env", "Write secret names to .env.example"),
|
|
11235
11643
|
handler: async (argv) => {
|
|
11644
|
+
const startTime = performance.now();
|
|
11236
11645
|
const linked = readLinkedProject();
|
|
11237
11646
|
if (!linked) {
|
|
11238
11647
|
printError("No linked project. Run `anything link <project-id>` first.");
|
|
@@ -11248,7 +11657,8 @@ const pullCommand = {
|
|
|
11248
11657
|
process.exitCode = 1;
|
|
11249
11658
|
return;
|
|
11250
11659
|
}
|
|
11251
|
-
const
|
|
11660
|
+
const timeoutSeconds = argv.timeout ?? DEFAULT_TIMEOUT_SECONDS;
|
|
11661
|
+
const client = new AnythingApiClient(config.value, { timeoutMs: timeoutSeconds * 1e3 });
|
|
11252
11662
|
const pullBoth = !argv.files && !argv.env;
|
|
11253
11663
|
const projectResult = await client.getProject({ projectGroupId: linked.projectId });
|
|
11254
11664
|
if (projectResult.isErr()) {
|
|
@@ -11261,7 +11671,8 @@ const pullCommand = {
|
|
|
11261
11671
|
if (pullBoth || argv.files) {
|
|
11262
11672
|
pulledFiles = await pullFiles({
|
|
11263
11673
|
client,
|
|
11264
|
-
projectGroupId: linked.projectId
|
|
11674
|
+
projectGroupId: linked.projectId,
|
|
11675
|
+
argv
|
|
11265
11676
|
});
|
|
11266
11677
|
if (pulledFiles === null) return;
|
|
11267
11678
|
}
|
|
@@ -11276,6 +11687,7 @@ const pullCommand = {
|
|
|
11276
11687
|
if (outputSuccess({
|
|
11277
11688
|
argv,
|
|
11278
11689
|
command: "pull",
|
|
11690
|
+
startTime,
|
|
11279
11691
|
data: {
|
|
11280
11692
|
projectId: linked.projectId,
|
|
11281
11693
|
projectName: projectResult.value.name,
|
|
@@ -11296,9 +11708,9 @@ const pullCommand = {
|
|
|
11296
11708
|
//#region src/commands/ship.ts
|
|
11297
11709
|
const COMMAND$4 = "ship";
|
|
11298
11710
|
const shipCommand = {
|
|
11299
|
-
command: "ship",
|
|
11711
|
+
command: "ship [prompt]",
|
|
11300
11712
|
describe: "Create or update + generate + publish in one shot",
|
|
11301
|
-
builder: (yargs) => yargs.
|
|
11713
|
+
builder: (yargs) => yargs.positional("prompt", {
|
|
11302
11714
|
type: "string",
|
|
11303
11715
|
describe: "What to build or change. Reads stdin if omitted."
|
|
11304
11716
|
}).option("project", {
|
|
@@ -11321,7 +11733,7 @@ const shipCommand = {
|
|
|
11321
11733
|
type: "boolean",
|
|
11322
11734
|
default: true,
|
|
11323
11735
|
describe: "Wait for deployment to complete (use --no-wait to skip)"
|
|
11324
|
-
}).example("anything ship
|
|
11736
|
+
}).example("anything ship \"Build a markdown viewer to review blog posts\"", "Create, generate, and publish a new app").example("anything ship --project pg_123 \"Add a settings page\"", "Iterate on existing app and publish").example("anything ship --project pg_123 --skip-publish \"Add dark mode\"", "Generate changes without publishing").example("anything ship --no-wait \"Build a landing page\"", "Ship without waiting for deployment"),
|
|
11325
11737
|
handler: async (argv) => {
|
|
11326
11738
|
const promptResult = await resolveTextInput({
|
|
11327
11739
|
value: argv.prompt ?? null,
|
|
@@ -11575,13 +11987,14 @@ const skillCommand = {
|
|
|
11575
11987
|
}),
|
|
11576
11988
|
handler: async (argv) => {
|
|
11577
11989
|
if (argv.path) {
|
|
11578
|
-
if (
|
|
11579
|
-
|
|
11990
|
+
if (outputSuccess({
|
|
11991
|
+
argv,
|
|
11992
|
+
command: "skill",
|
|
11993
|
+
data: {
|
|
11580
11994
|
name: "anything-cli",
|
|
11581
11995
|
path: skillRootPath
|
|
11582
|
-
}
|
|
11583
|
-
|
|
11584
|
-
}
|
|
11996
|
+
}
|
|
11997
|
+
})) return;
|
|
11585
11998
|
console.log(skillRootPath);
|
|
11586
11999
|
return;
|
|
11587
12000
|
}
|
|
@@ -11594,15 +12007,16 @@ const skillCommand = {
|
|
|
11594
12007
|
process.exitCode = 1;
|
|
11595
12008
|
return;
|
|
11596
12009
|
}
|
|
11597
|
-
if (
|
|
11598
|
-
|
|
12010
|
+
if (outputSuccess({
|
|
12011
|
+
argv,
|
|
12012
|
+
command: "skill",
|
|
12013
|
+
data: {
|
|
11599
12014
|
name: "anything-cli",
|
|
11600
12015
|
path: skillRootPath,
|
|
11601
12016
|
file: relativePath,
|
|
11602
12017
|
content
|
|
11603
|
-
}
|
|
11604
|
-
|
|
11605
|
-
}
|
|
12018
|
+
}
|
|
12019
|
+
})) return;
|
|
11606
12020
|
process.stdout.write(content);
|
|
11607
12021
|
}
|
|
11608
12022
|
};
|
|
@@ -12090,6 +12504,11 @@ const userCommand = {
|
|
|
12090
12504
|
command: "user",
|
|
12091
12505
|
aliases: ["whoami"],
|
|
12092
12506
|
describe: "Show current user and organization context",
|
|
12507
|
+
builder: (yargs) => yargs.option("brief", {
|
|
12508
|
+
type: "boolean",
|
|
12509
|
+
default: false,
|
|
12510
|
+
describe: "Show only identity essentials (id, name, email, active org)"
|
|
12511
|
+
}).example("anything user --brief", "Show just the current identity").example("anything whoami --brief --json", "Identity essentials as JSON"),
|
|
12093
12512
|
handler: async (argv) => {
|
|
12094
12513
|
const config = resolveConfig({
|
|
12095
12514
|
dev: argv.dev,
|
|
@@ -12128,10 +12547,29 @@ const userCommand = {
|
|
|
12128
12547
|
defaultOrganizationHasCredits: defaultOrganization !== null ? BigInt(defaultOrganization.creditBalance) > 0n : null
|
|
12129
12548
|
};
|
|
12130
12549
|
const activeOrg = activeOrgId ? result.value.organizations.find((o) => o.id === activeOrgId) ?? null : null;
|
|
12131
|
-
if (argv.quiet) {
|
|
12550
|
+
if (argv.quiet && !argv.json) {
|
|
12132
12551
|
console.log(result.value.id);
|
|
12133
12552
|
return;
|
|
12134
12553
|
}
|
|
12554
|
+
if (argv.brief) {
|
|
12555
|
+
const briefData = {
|
|
12556
|
+
id: result.value.id,
|
|
12557
|
+
name: result.value.name ?? null,
|
|
12558
|
+
email: result.value.email ?? null,
|
|
12559
|
+
activeOrgId: activeOrgId ?? null,
|
|
12560
|
+
activeOrgName: activeOrg?.name ?? null
|
|
12561
|
+
};
|
|
12562
|
+
if (outputSuccess({
|
|
12563
|
+
argv,
|
|
12564
|
+
command: COMMAND,
|
|
12565
|
+
data: briefData
|
|
12566
|
+
})) return;
|
|
12567
|
+
printLabel("Name", briefData.name);
|
|
12568
|
+
printLabel("Email", briefData.email);
|
|
12569
|
+
printLabel("User ID", briefData.id);
|
|
12570
|
+
printLabel("Active Org", activeOrg ? `${activeOrg.name} (${activeOrgId})` : null);
|
|
12571
|
+
return;
|
|
12572
|
+
}
|
|
12135
12573
|
if (outputSuccess({
|
|
12136
12574
|
argv,
|
|
12137
12575
|
command: COMMAND,
|