@anythingai/cli 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/js/bin.mjs +1006 -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";
|
|
@@ -3037,6 +3037,18 @@ function exitCodeFromHttpStatus(status) {
|
|
|
3037
3037
|
if (status === 422 || status === 400) return EXIT_INVALID_ARGS;
|
|
3038
3038
|
return EXIT_ERROR;
|
|
3039
3039
|
}
|
|
3040
|
+
function errorCodeFromExitCode(exitCode) {
|
|
3041
|
+
switch (exitCode) {
|
|
3042
|
+
case EXIT_INVALID_ARGS: return "INVALID_ARGUMENTS";
|
|
3043
|
+
case EXIT_NOT_FOUND: return "NOT_FOUND";
|
|
3044
|
+
case EXIT_AUTH_FAILURE: return "AUTH_FAILURE";
|
|
3045
|
+
case EXIT_CONFLICT: return "CONFLICT";
|
|
3046
|
+
case EXIT_TIMEOUT: return "TIMEOUT";
|
|
3047
|
+
case EXIT_SERVER_ERROR: return "SERVER_ERROR";
|
|
3048
|
+
case EXIT_RATE_LIMITED: return "RATE_LIMITED";
|
|
3049
|
+
default: return "ERROR";
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3040
3052
|
function errorCodeFromHttpStatus(status) {
|
|
3041
3053
|
if (status === null) return "NETWORK_ERROR";
|
|
3042
3054
|
if (status === 401) return "AUTH_FAILURE";
|
|
@@ -3053,7 +3065,7 @@ function errorCodeFromHttpStatus(status) {
|
|
|
3053
3065
|
|
|
3054
3066
|
//#endregion
|
|
3055
3067
|
//#region package.json
|
|
3056
|
-
var version = "0.0
|
|
3068
|
+
var version = "0.1.0";
|
|
3057
3069
|
|
|
3058
3070
|
//#endregion
|
|
3059
3071
|
//#region generated/core/bodySerializer.gen.ts
|
|
@@ -4315,14 +4327,23 @@ const USER_AGENT = `anything-cli/${version}`;
|
|
|
4315
4327
|
const ErrorWithMessageSchema = z.object({ message: z.string().min(1) });
|
|
4316
4328
|
const ErrorWithErrorStringSchema = z.object({ error: z.string().min(1) });
|
|
4317
4329
|
const ErrorWithNestedMessageSchema = z.object({ error: z.object({ message: z.string() }) });
|
|
4330
|
+
const HTML_DOCUMENT = /<!doctype html|<html[\s>]/i;
|
|
4331
|
+
function summarizeErrorString(raw, status) {
|
|
4332
|
+
const trimmed = raw.trim();
|
|
4333
|
+
if (!HTML_DOCUMENT.test(trimmed)) return trimmed;
|
|
4334
|
+
const pre = trimmed.match(/<pre[^>]*>([\s\S]*?)<\/pre>/i)?.[1];
|
|
4335
|
+
const title = trimmed.match(/<title[^>]*>([\s\S]*?)<\/title>/i)?.[1];
|
|
4336
|
+
const summary = (pre ?? title)?.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
4337
|
+
return summary && summary.length > 0 ? `API error (${status}): ${summary}` : `API error (${status})`;
|
|
4338
|
+
}
|
|
4318
4339
|
function extractErrorMessage(status, details) {
|
|
4319
4340
|
const withMessage = ErrorWithMessageSchema.safeParse(details);
|
|
4320
|
-
if (withMessage.success) return withMessage.data.message;
|
|
4341
|
+
if (withMessage.success) return summarizeErrorString(withMessage.data.message, status);
|
|
4321
4342
|
const withErrorString = ErrorWithErrorStringSchema.safeParse(details);
|
|
4322
|
-
if (withErrorString.success) return withErrorString.data.error;
|
|
4343
|
+
if (withErrorString.success) return summarizeErrorString(withErrorString.data.error, status);
|
|
4323
4344
|
const withNested = ErrorWithNestedMessageSchema.safeParse(details);
|
|
4324
|
-
if (withNested.success) return withNested.data.error.message;
|
|
4325
|
-
if (typeof details === "string" && details.length > 0) return details;
|
|
4345
|
+
if (withNested.success) return summarizeErrorString(withNested.data.error.message, status);
|
|
4346
|
+
if (typeof details === "string" && details.length > 0) return summarizeErrorString(details, status);
|
|
4326
4347
|
return `API error (${status})`;
|
|
4327
4348
|
}
|
|
4328
4349
|
function parseRetryAfter(response) {
|
|
@@ -4365,23 +4386,41 @@ const RollbackResponseSchema = z.object({
|
|
|
4365
4386
|
status: z.string()
|
|
4366
4387
|
}).optional()
|
|
4367
4388
|
});
|
|
4389
|
+
function wrapFetchWithTimeout(ms) {
|
|
4390
|
+
return (input, init) => {
|
|
4391
|
+
const signal = AbortSignal.timeout(ms);
|
|
4392
|
+
if (input instanceof Request) return globalThis.fetch(new Request(input, { signal }));
|
|
4393
|
+
return globalThis.fetch(input, {
|
|
4394
|
+
...init,
|
|
4395
|
+
signal
|
|
4396
|
+
});
|
|
4397
|
+
};
|
|
4398
|
+
}
|
|
4368
4399
|
var AnythingApiClient = class {
|
|
4369
4400
|
client;
|
|
4370
|
-
|
|
4401
|
+
timeoutMs;
|
|
4402
|
+
constructor(config, options) {
|
|
4403
|
+
const apiUrl = config.apiUrl.replace(/\/$/, "");
|
|
4404
|
+
this.timeoutMs = options?.timeoutMs ?? null;
|
|
4371
4405
|
this.client = createClient$1(createConfig({
|
|
4372
|
-
baseUrl:
|
|
4406
|
+
baseUrl: apiUrl,
|
|
4373
4407
|
headers: {
|
|
4374
4408
|
authorization: buildAuthHeader$1(config.apiKey),
|
|
4375
4409
|
"user-agent": USER_AGENT
|
|
4376
|
-
}
|
|
4410
|
+
},
|
|
4411
|
+
...this.timeoutMs !== null ? { fetch: wrapFetchWithTimeout(this.timeoutMs) } : {}
|
|
4377
4412
|
}));
|
|
4378
4413
|
}
|
|
4379
4414
|
toResult(result) {
|
|
4380
4415
|
const { data, error, response } = result;
|
|
4381
|
-
if (!response)
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4416
|
+
if (!response) {
|
|
4417
|
+
const isTimeout = error instanceof DOMException && error.name === "TimeoutError";
|
|
4418
|
+
const timeoutSuffix = this.timeoutMs !== null ? ` after ${Math.round(this.timeoutMs / 1e3)}s` : "";
|
|
4419
|
+
return err({
|
|
4420
|
+
message: isTimeout ? `Request timed out${timeoutSuffix}. Use --timeout to increase.` : `Network error: ${error instanceof Error ? error.message : String(error)}`,
|
|
4421
|
+
status: isTimeout ? 408 : null
|
|
4422
|
+
});
|
|
4423
|
+
}
|
|
4385
4424
|
if (!response.ok) {
|
|
4386
4425
|
const retryAfter = parseRetryAfter(response);
|
|
4387
4426
|
return err({
|
|
@@ -4810,10 +4849,6 @@ function printApiError(error) {
|
|
|
4810
4849
|
if (withErrors.success) for (const e of withErrors.data.errors) console.error(` ${typeof e === "string" ? e : e.message}`);
|
|
4811
4850
|
}
|
|
4812
4851
|
function outputSuccess({ argv, command, data, primaryId, startTime }) {
|
|
4813
|
-
if (argv.quiet) {
|
|
4814
|
-
if (primaryId) console.log(primaryId);
|
|
4815
|
-
return true;
|
|
4816
|
-
}
|
|
4817
4852
|
if (argv.json) {
|
|
4818
4853
|
const envelope = {
|
|
4819
4854
|
ok: true,
|
|
@@ -4824,6 +4859,10 @@ function outputSuccess({ argv, command, data, primaryId, startTime }) {
|
|
|
4824
4859
|
console.log(JSON.stringify(envelope, null, 2));
|
|
4825
4860
|
return true;
|
|
4826
4861
|
}
|
|
4862
|
+
if (argv.quiet) {
|
|
4863
|
+
if (primaryId) console.log(primaryId);
|
|
4864
|
+
return true;
|
|
4865
|
+
}
|
|
4827
4866
|
return false;
|
|
4828
4867
|
}
|
|
4829
4868
|
const DetailsWithCodeSchema = z.object({ code: z.string() });
|
|
@@ -4836,7 +4875,7 @@ function outputError({ argv, command, error, hint, exitCode }) {
|
|
|
4836
4875
|
const details = "details" in error ? error.details : void 0;
|
|
4837
4876
|
const retryAfter = "retryAfter" in error && typeof error.retryAfter === "number" ? error.retryAfter : null;
|
|
4838
4877
|
process.exitCode = exitCode ?? exitCodeFromHttpStatus(status);
|
|
4839
|
-
const code = extractErrorCode(details) ?? errorCodeFromHttpStatus(status);
|
|
4878
|
+
const code = extractErrorCode(details) ?? (status === null && exitCode !== void 0 ? errorCodeFromExitCode(exitCode) : errorCodeFromHttpStatus(status));
|
|
4840
4879
|
if (argv.json || argv.quiet) {
|
|
4841
4880
|
console.error(JSON.stringify({
|
|
4842
4881
|
ok: false,
|
|
@@ -4871,7 +4910,6 @@ function outputValidationError({ argv, command, message, hint }) {
|
|
|
4871
4910
|
});
|
|
4872
4911
|
}
|
|
4873
4912
|
function outputDryRun({ argv, command, plannedActions }) {
|
|
4874
|
-
if (argv.quiet) return;
|
|
4875
4913
|
if (argv.json) {
|
|
4876
4914
|
console.log(JSON.stringify({
|
|
4877
4915
|
ok: true,
|
|
@@ -4881,6 +4919,7 @@ function outputDryRun({ argv, command, plannedActions }) {
|
|
|
4881
4919
|
}, null, 2));
|
|
4882
4920
|
return;
|
|
4883
4921
|
}
|
|
4922
|
+
if (argv.quiet) return;
|
|
4884
4923
|
printSuccess("Dry run — no changes made.");
|
|
4885
4924
|
for (const action of plannedActions) {
|
|
4886
4925
|
printLabel("Action", action.action);
|
|
@@ -4958,6 +4997,19 @@ const upload = {
|
|
|
4958
4997
|
});
|
|
4959
4998
|
return;
|
|
4960
4999
|
}
|
|
5000
|
+
if (argv["dry-run"]) {
|
|
5001
|
+
outputDryRun({
|
|
5002
|
+
argv,
|
|
5003
|
+
command,
|
|
5004
|
+
plannedActions: [{
|
|
5005
|
+
action: "upload_asset",
|
|
5006
|
+
projectGroupId: argv.projectId,
|
|
5007
|
+
file: filePath,
|
|
5008
|
+
...argv.name ? { name: argv.name } : {}
|
|
5009
|
+
}]
|
|
5010
|
+
});
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
4961
5013
|
const config = resolveConfig({
|
|
4962
5014
|
dev: argv.dev,
|
|
4963
5015
|
apiUrl: argv.apiUrl
|
|
@@ -5097,6 +5149,18 @@ const remove$1 = {
|
|
|
5097
5149
|
}),
|
|
5098
5150
|
handler: async (argv) => {
|
|
5099
5151
|
const command = "assets remove";
|
|
5152
|
+
if (argv["dry-run"]) {
|
|
5153
|
+
outputDryRun({
|
|
5154
|
+
argv,
|
|
5155
|
+
command,
|
|
5156
|
+
plannedActions: [{
|
|
5157
|
+
action: "remove_asset",
|
|
5158
|
+
projectGroupId: argv.projectId,
|
|
5159
|
+
assetId: argv.assetId
|
|
5160
|
+
}]
|
|
5161
|
+
});
|
|
5162
|
+
return;
|
|
5163
|
+
}
|
|
5100
5164
|
const config = resolveConfig({
|
|
5101
5165
|
dev: argv.dev,
|
|
5102
5166
|
apiUrl: argv.apiUrl
|
|
@@ -5406,13 +5470,31 @@ const login = {
|
|
|
5406
5470
|
}).replace(/\/$/, "");
|
|
5407
5471
|
const nonInteractive = isNonInteractive(argv);
|
|
5408
5472
|
if (argv["api-key"]) {
|
|
5473
|
+
const apiKey = argv["api-key"];
|
|
5474
|
+
const probe = await new AnythingApiClient({
|
|
5475
|
+
apiKey,
|
|
5476
|
+
apiUrl
|
|
5477
|
+
}).getMe();
|
|
5478
|
+
if (probe.isErr()) {
|
|
5479
|
+
outputError({
|
|
5480
|
+
argv,
|
|
5481
|
+
command: "auth login",
|
|
5482
|
+
error: {
|
|
5483
|
+
message: `API key was rejected: ${probe.error.message}`,
|
|
5484
|
+
status: probe.error.status
|
|
5485
|
+
},
|
|
5486
|
+
hint: "Double-check the key and that it matches this API URL. Your existing login was left untouched.",
|
|
5487
|
+
exitCode: 4
|
|
5488
|
+
});
|
|
5489
|
+
return;
|
|
5490
|
+
}
|
|
5409
5491
|
saveConfig({
|
|
5410
|
-
apiKey
|
|
5492
|
+
apiKey,
|
|
5411
5493
|
apiUrl
|
|
5412
5494
|
});
|
|
5413
5495
|
const org = await selectAndSetOrg({
|
|
5414
5496
|
config: {
|
|
5415
|
-
apiKey
|
|
5497
|
+
apiKey,
|
|
5416
5498
|
apiUrl
|
|
5417
5499
|
},
|
|
5418
5500
|
json: argv.json,
|
|
@@ -5686,6 +5768,9 @@ const authCommand = {
|
|
|
5686
5768
|
//#endregion
|
|
5687
5769
|
//#region src/commands/database-connect.ts
|
|
5688
5770
|
const COMMAND$25 = "databases connect";
|
|
5771
|
+
function maskConnectionString(connectionString) {
|
|
5772
|
+
return connectionString.replace(/(\/\/[^:/?#@]+:)[^@/?#]*(@)/, "$1****$2");
|
|
5773
|
+
}
|
|
5689
5774
|
const databaseConnectCommand = {
|
|
5690
5775
|
command: "connect <databaseId>",
|
|
5691
5776
|
describe: "Print the connection string for a database",
|
|
@@ -5693,7 +5778,11 @@ const databaseConnectCommand = {
|
|
|
5693
5778
|
type: "string",
|
|
5694
5779
|
demandOption: true,
|
|
5695
5780
|
describe: "The database ID"
|
|
5696
|
-
}).
|
|
5781
|
+
}).option("mask", {
|
|
5782
|
+
type: "boolean",
|
|
5783
|
+
default: false,
|
|
5784
|
+
describe: "Redact the password in the connection string"
|
|
5785
|
+
}).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
5786
|
handler: async (argv) => {
|
|
5698
5787
|
const config = resolveConfig({
|
|
5699
5788
|
dev: argv.dev,
|
|
@@ -5720,13 +5809,17 @@ const databaseConnectCommand = {
|
|
|
5720
5809
|
});
|
|
5721
5810
|
return;
|
|
5722
5811
|
}
|
|
5812
|
+
const connectionString = argv.mask ? maskConnectionString(result.value.connectionString) : result.value.connectionString;
|
|
5723
5813
|
if (outputSuccess({
|
|
5724
5814
|
argv,
|
|
5725
5815
|
command: COMMAND$25,
|
|
5726
|
-
data:
|
|
5727
|
-
|
|
5816
|
+
data: {
|
|
5817
|
+
...result.value,
|
|
5818
|
+
connectionString
|
|
5819
|
+
},
|
|
5820
|
+
primaryId: connectionString
|
|
5728
5821
|
})) return;
|
|
5729
|
-
console.log(
|
|
5822
|
+
console.log(connectionString);
|
|
5730
5823
|
}
|
|
5731
5824
|
};
|
|
5732
5825
|
|
|
@@ -5791,6 +5884,19 @@ const databaseCreateCommand = {
|
|
|
5791
5884
|
describe: "Database name"
|
|
5792
5885
|
}).example("anything databases create --project pg_123", "Create a database for a project"),
|
|
5793
5886
|
handler: async (argv) => {
|
|
5887
|
+
const name = argv.name?.trim();
|
|
5888
|
+
if (!name) {
|
|
5889
|
+
outputError({
|
|
5890
|
+
argv,
|
|
5891
|
+
command: COMMAND$24,
|
|
5892
|
+
error: {
|
|
5893
|
+
message: "Database name is required. Pass --name <name>.",
|
|
5894
|
+
status: null
|
|
5895
|
+
},
|
|
5896
|
+
exitCode: 2
|
|
5897
|
+
});
|
|
5898
|
+
return;
|
|
5899
|
+
}
|
|
5794
5900
|
const config = resolveConfig({
|
|
5795
5901
|
dev: argv.dev,
|
|
5796
5902
|
apiUrl: argv.apiUrl
|
|
@@ -5831,8 +5937,8 @@ const databaseCreateCommand = {
|
|
|
5831
5937
|
plannedActions: [{
|
|
5832
5938
|
action: "create_database",
|
|
5833
5939
|
org: orgResult.orgId,
|
|
5834
|
-
|
|
5835
|
-
...argv.
|
|
5940
|
+
name,
|
|
5941
|
+
...argv.project ? { project: argv.project } : {}
|
|
5836
5942
|
}]
|
|
5837
5943
|
});
|
|
5838
5944
|
return;
|
|
@@ -5840,7 +5946,7 @@ const databaseCreateCommand = {
|
|
|
5840
5946
|
const result = await new AnythingApiClient(config.value).createDatabase({
|
|
5841
5947
|
organizationId: orgResult.orgId,
|
|
5842
5948
|
projectGroupId: argv.project ?? null,
|
|
5843
|
-
name
|
|
5949
|
+
name
|
|
5844
5950
|
});
|
|
5845
5951
|
if (result.isErr()) {
|
|
5846
5952
|
outputError({
|
|
@@ -6712,155 +6818,383 @@ const domainsCommand = {
|
|
|
6712
6818
|
};
|
|
6713
6819
|
|
|
6714
6820
|
//#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
|
|
6857
|
-
},
|
|
6858
|
-
{
|
|
6859
|
-
name: "--thread",
|
|
6860
|
-
type: "string",
|
|
6861
|
-
required: false
|
|
6821
|
+
//#region src/commands/submit.ts
|
|
6822
|
+
const POLL_INTERVAL_MS$1 = 2e3;
|
|
6823
|
+
const POLL_TIMEOUT_MS = 6e4;
|
|
6824
|
+
const STORE_CHOICES = ["app-store", "play-store"];
|
|
6825
|
+
async function waitForSubmission({ client, projectGroupId, submission }) {
|
|
6826
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
6827
|
+
let current = submission;
|
|
6828
|
+
while (current.status === "PENDING" && Date.now() < deadline) {
|
|
6829
|
+
const latestResult = await client.getProjectSubmission({
|
|
6830
|
+
projectGroupId,
|
|
6831
|
+
submissionId: current.id
|
|
6832
|
+
});
|
|
6833
|
+
if (latestResult.isErr()) return latestResult.map((value) => value.submission);
|
|
6834
|
+
current = latestResult.value.submission;
|
|
6835
|
+
if (current.status !== "PENDING") return latestResult.map((value) => value.submission);
|
|
6836
|
+
await setTimeout$1(POLL_INTERVAL_MS$1);
|
|
6837
|
+
}
|
|
6838
|
+
return ok(current);
|
|
6839
|
+
}
|
|
6840
|
+
function printSubmissionResult({ argv, command, pendingMessage, submission }) {
|
|
6841
|
+
const { projectGroupId: projectId, ...submissionRest } = submission;
|
|
6842
|
+
const submissionOut = {
|
|
6843
|
+
projectId,
|
|
6844
|
+
...submissionRest
|
|
6845
|
+
};
|
|
6846
|
+
if (submission.status === "FAILED") {
|
|
6847
|
+
printError(submission.errorMessage ?? "Submission failed.");
|
|
6848
|
+
process.exitCode = 1;
|
|
6849
|
+
return;
|
|
6850
|
+
}
|
|
6851
|
+
if (submission.status === "CREATED") {
|
|
6852
|
+
if (outputSuccess({
|
|
6853
|
+
argv,
|
|
6854
|
+
command,
|
|
6855
|
+
data: {
|
|
6856
|
+
success: true,
|
|
6857
|
+
submission: submissionOut
|
|
6862
6858
|
},
|
|
6863
|
-
|
|
6859
|
+
primaryId: submission.id
|
|
6860
|
+
})) return;
|
|
6861
|
+
printSuccess("App Store submission is ready.");
|
|
6862
|
+
printLabel("Submission ID", submission.id);
|
|
6863
|
+
printLabel("Launch URL", submission.launchUrl);
|
|
6864
|
+
printLabel("Auth URL", submission.authUrl);
|
|
6865
|
+
printLabel("Expires At", submission.expiresAt);
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6868
|
+
if (outputSuccess({
|
|
6869
|
+
argv,
|
|
6870
|
+
command,
|
|
6871
|
+
data: {
|
|
6872
|
+
success: true,
|
|
6873
|
+
submission
|
|
6874
|
+
},
|
|
6875
|
+
primaryId: submission.id
|
|
6876
|
+
})) return;
|
|
6877
|
+
printSuccess(pendingMessage);
|
|
6878
|
+
printLabel("Submission ID", submission.id);
|
|
6879
|
+
printLabel("Status", submission.status);
|
|
6880
|
+
printLabel("Next step", "Expo is still preparing the launch flow. Run the command again in a moment.");
|
|
6881
|
+
}
|
|
6882
|
+
const submitStatusCommand = {
|
|
6883
|
+
command: "status <projectId> <submissionId>",
|
|
6884
|
+
describe: "Check the status of an App Store submission",
|
|
6885
|
+
builder: (yargs) => yargs.positional("projectId", {
|
|
6886
|
+
type: "string",
|
|
6887
|
+
demandOption: true,
|
|
6888
|
+
describe: "The project ID"
|
|
6889
|
+
}).positional("submissionId", {
|
|
6890
|
+
type: "string",
|
|
6891
|
+
demandOption: true,
|
|
6892
|
+
describe: "The submission ID"
|
|
6893
|
+
}).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"),
|
|
6894
|
+
handler: async (argv) => {
|
|
6895
|
+
const command = "projects submit status";
|
|
6896
|
+
const config = resolveConfig({
|
|
6897
|
+
dev: argv.dev,
|
|
6898
|
+
apiUrl: argv.apiUrl
|
|
6899
|
+
});
|
|
6900
|
+
if (config.isErr()) {
|
|
6901
|
+
outputError({
|
|
6902
|
+
argv,
|
|
6903
|
+
command,
|
|
6904
|
+
error: {
|
|
6905
|
+
message: config.error.message,
|
|
6906
|
+
status: null
|
|
6907
|
+
},
|
|
6908
|
+
exitCode: 4
|
|
6909
|
+
});
|
|
6910
|
+
return;
|
|
6911
|
+
}
|
|
6912
|
+
const result = await new AnythingApiClient(config.value).getProjectSubmission({
|
|
6913
|
+
projectGroupId: argv.projectId,
|
|
6914
|
+
submissionId: argv.submissionId
|
|
6915
|
+
});
|
|
6916
|
+
if (result.isErr()) {
|
|
6917
|
+
outputError({
|
|
6918
|
+
argv,
|
|
6919
|
+
command,
|
|
6920
|
+
error: result.error
|
|
6921
|
+
});
|
|
6922
|
+
return;
|
|
6923
|
+
}
|
|
6924
|
+
printSubmissionResult({
|
|
6925
|
+
argv,
|
|
6926
|
+
command,
|
|
6927
|
+
pendingMessage: "Submission is still preparing.",
|
|
6928
|
+
submission: result.value.submission
|
|
6929
|
+
});
|
|
6930
|
+
}
|
|
6931
|
+
};
|
|
6932
|
+
const submitCommand = {
|
|
6933
|
+
command: "submit <projectId>",
|
|
6934
|
+
describe: "Start an App Store submission for an app",
|
|
6935
|
+
builder: (yargs) => yargs.command(submitStatusCommand).positional("projectId", {
|
|
6936
|
+
type: "string",
|
|
6937
|
+
demandOption: true,
|
|
6938
|
+
describe: "The project ID"
|
|
6939
|
+
}).option("store", {
|
|
6940
|
+
type: "string",
|
|
6941
|
+
choices: STORE_CHOICES,
|
|
6942
|
+
describe: "Submission target store"
|
|
6943
|
+
}).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"),
|
|
6944
|
+
handler: async (argv) => {
|
|
6945
|
+
const command = "projects submit";
|
|
6946
|
+
if (argv.store === void 0) {
|
|
6947
|
+
outputError({
|
|
6948
|
+
argv,
|
|
6949
|
+
command,
|
|
6950
|
+
error: {
|
|
6951
|
+
message: "Missing required argument: store",
|
|
6952
|
+
status: null
|
|
6953
|
+
},
|
|
6954
|
+
exitCode: 2
|
|
6955
|
+
});
|
|
6956
|
+
return;
|
|
6957
|
+
}
|
|
6958
|
+
const store = STORE_CHOICES.find((s) => s === argv.store);
|
|
6959
|
+
if (!store) {
|
|
6960
|
+
outputError({
|
|
6961
|
+
argv,
|
|
6962
|
+
command,
|
|
6963
|
+
error: {
|
|
6964
|
+
message: `Unsupported store: ${argv.store}`,
|
|
6965
|
+
status: null
|
|
6966
|
+
},
|
|
6967
|
+
exitCode: 2
|
|
6968
|
+
});
|
|
6969
|
+
return;
|
|
6970
|
+
}
|
|
6971
|
+
if (argv["dry-run"]) {
|
|
6972
|
+
outputDryRun({
|
|
6973
|
+
argv,
|
|
6974
|
+
command,
|
|
6975
|
+
plannedActions: [{
|
|
6976
|
+
action: "submit_project",
|
|
6977
|
+
projectGroupId: argv.projectId,
|
|
6978
|
+
store
|
|
6979
|
+
}]
|
|
6980
|
+
});
|
|
6981
|
+
return;
|
|
6982
|
+
}
|
|
6983
|
+
const config = resolveConfig({
|
|
6984
|
+
dev: argv.dev,
|
|
6985
|
+
apiUrl: argv.apiUrl
|
|
6986
|
+
});
|
|
6987
|
+
if (config.isErr()) {
|
|
6988
|
+
outputError({
|
|
6989
|
+
argv,
|
|
6990
|
+
command,
|
|
6991
|
+
error: {
|
|
6992
|
+
message: config.error.message,
|
|
6993
|
+
status: null
|
|
6994
|
+
},
|
|
6995
|
+
exitCode: 4
|
|
6996
|
+
});
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
const client = new AnythingApiClient(config.value);
|
|
7000
|
+
const startResult = await client.submitProject({
|
|
7001
|
+
projectGroupId: argv.projectId,
|
|
7002
|
+
store
|
|
7003
|
+
});
|
|
7004
|
+
if (startResult.isErr()) {
|
|
7005
|
+
outputError({
|
|
7006
|
+
argv,
|
|
7007
|
+
command,
|
|
7008
|
+
error: startResult.error
|
|
7009
|
+
});
|
|
7010
|
+
return;
|
|
7011
|
+
}
|
|
7012
|
+
const finalResult = await waitForSubmission({
|
|
7013
|
+
client,
|
|
7014
|
+
projectGroupId: argv.projectId,
|
|
7015
|
+
submission: startResult.value.submission
|
|
7016
|
+
});
|
|
7017
|
+
if (finalResult.isErr()) {
|
|
7018
|
+
outputError({
|
|
7019
|
+
argv,
|
|
7020
|
+
command,
|
|
7021
|
+
error: finalResult.error
|
|
7022
|
+
});
|
|
7023
|
+
return;
|
|
7024
|
+
}
|
|
7025
|
+
printSubmissionResult({
|
|
7026
|
+
argv,
|
|
7027
|
+
command,
|
|
7028
|
+
pendingMessage: "Submission started.",
|
|
7029
|
+
submission: finalResult.value
|
|
7030
|
+
});
|
|
7031
|
+
}
|
|
7032
|
+
};
|
|
7033
|
+
|
|
7034
|
+
//#endregion
|
|
7035
|
+
//#region src/commands/introspect.ts
|
|
7036
|
+
const commandTree = [
|
|
7037
|
+
{
|
|
7038
|
+
name: "auth login",
|
|
7039
|
+
flags: [{
|
|
7040
|
+
name: "--api-key",
|
|
7041
|
+
type: "string",
|
|
7042
|
+
required: false
|
|
7043
|
+
}, {
|
|
7044
|
+
name: "--dev",
|
|
7045
|
+
type: "boolean",
|
|
7046
|
+
required: false
|
|
7047
|
+
}],
|
|
7048
|
+
idempotent: true,
|
|
7049
|
+
destructive: false
|
|
7050
|
+
},
|
|
7051
|
+
{
|
|
7052
|
+
name: "auth logout",
|
|
7053
|
+
flags: [],
|
|
7054
|
+
idempotent: true,
|
|
7055
|
+
destructive: true
|
|
7056
|
+
},
|
|
7057
|
+
{
|
|
7058
|
+
name: "auth status",
|
|
7059
|
+
flags: [],
|
|
7060
|
+
idempotent: true,
|
|
7061
|
+
destructive: false
|
|
7062
|
+
},
|
|
7063
|
+
{
|
|
7064
|
+
name: "user",
|
|
7065
|
+
flags: [{
|
|
7066
|
+
name: "--brief",
|
|
7067
|
+
type: "boolean",
|
|
7068
|
+
required: false
|
|
7069
|
+
}],
|
|
7070
|
+
idempotent: true,
|
|
7071
|
+
destructive: false
|
|
7072
|
+
},
|
|
7073
|
+
{
|
|
7074
|
+
name: "orgs list",
|
|
7075
|
+
flags: [],
|
|
7076
|
+
idempotent: true,
|
|
7077
|
+
destructive: false
|
|
7078
|
+
},
|
|
7079
|
+
{
|
|
7080
|
+
name: "orgs get",
|
|
7081
|
+
flags: [{
|
|
7082
|
+
name: "<organizationId>",
|
|
7083
|
+
type: "string",
|
|
7084
|
+
required: true
|
|
7085
|
+
}],
|
|
7086
|
+
idempotent: true,
|
|
7087
|
+
destructive: false
|
|
7088
|
+
},
|
|
7089
|
+
{
|
|
7090
|
+
name: "orgs set",
|
|
7091
|
+
flags: [{
|
|
7092
|
+
name: "<org-id>",
|
|
7093
|
+
type: "string",
|
|
7094
|
+
required: true
|
|
7095
|
+
}],
|
|
7096
|
+
idempotent: true,
|
|
7097
|
+
destructive: false
|
|
7098
|
+
},
|
|
7099
|
+
{
|
|
7100
|
+
name: "orgs unset",
|
|
7101
|
+
flags: [],
|
|
7102
|
+
idempotent: true,
|
|
7103
|
+
destructive: false
|
|
7104
|
+
},
|
|
7105
|
+
{
|
|
7106
|
+
name: "orgs members",
|
|
7107
|
+
flags: [{
|
|
7108
|
+
name: "<organizationId>",
|
|
7109
|
+
type: "string",
|
|
7110
|
+
required: true
|
|
7111
|
+
}],
|
|
7112
|
+
idempotent: true,
|
|
7113
|
+
destructive: false
|
|
7114
|
+
},
|
|
7115
|
+
{
|
|
7116
|
+
name: "projects list",
|
|
7117
|
+
flags: [
|
|
7118
|
+
{
|
|
7119
|
+
name: "--org",
|
|
7120
|
+
type: "string",
|
|
7121
|
+
required: false
|
|
7122
|
+
},
|
|
7123
|
+
{
|
|
7124
|
+
name: "--search",
|
|
7125
|
+
type: "string",
|
|
7126
|
+
required: false
|
|
7127
|
+
},
|
|
7128
|
+
{
|
|
7129
|
+
name: "--limit",
|
|
7130
|
+
type: "number",
|
|
7131
|
+
required: false
|
|
7132
|
+
}
|
|
7133
|
+
],
|
|
7134
|
+
idempotent: true,
|
|
7135
|
+
destructive: false
|
|
7136
|
+
},
|
|
7137
|
+
{
|
|
7138
|
+
name: "projects create",
|
|
7139
|
+
flags: [
|
|
7140
|
+
{
|
|
7141
|
+
name: "--prompt",
|
|
7142
|
+
type: "string",
|
|
7143
|
+
required: true
|
|
7144
|
+
},
|
|
7145
|
+
{
|
|
7146
|
+
name: "--org",
|
|
7147
|
+
type: "string",
|
|
7148
|
+
required: false
|
|
7149
|
+
},
|
|
7150
|
+
{
|
|
7151
|
+
name: "--name",
|
|
7152
|
+
type: "string",
|
|
7153
|
+
required: false
|
|
7154
|
+
},
|
|
7155
|
+
{
|
|
7156
|
+
name: "--wait",
|
|
7157
|
+
type: "boolean",
|
|
7158
|
+
required: false
|
|
7159
|
+
},
|
|
7160
|
+
{
|
|
7161
|
+
name: "--no-wait",
|
|
7162
|
+
type: "boolean",
|
|
7163
|
+
required: false
|
|
7164
|
+
}
|
|
7165
|
+
],
|
|
7166
|
+
idempotent: false,
|
|
7167
|
+
destructive: false
|
|
7168
|
+
},
|
|
7169
|
+
{
|
|
7170
|
+
name: "projects get",
|
|
7171
|
+
flags: [{
|
|
7172
|
+
name: "<projectId>",
|
|
7173
|
+
type: "string",
|
|
7174
|
+
required: true
|
|
7175
|
+
}],
|
|
7176
|
+
idempotent: true,
|
|
7177
|
+
destructive: false
|
|
7178
|
+
},
|
|
7179
|
+
{
|
|
7180
|
+
name: "projects generate",
|
|
7181
|
+
flags: [
|
|
7182
|
+
{
|
|
7183
|
+
name: "<projectId>",
|
|
7184
|
+
type: "string",
|
|
7185
|
+
required: true
|
|
7186
|
+
},
|
|
7187
|
+
{
|
|
7188
|
+
name: "--prompt",
|
|
7189
|
+
type: "string",
|
|
7190
|
+
required: true
|
|
7191
|
+
},
|
|
7192
|
+
{
|
|
7193
|
+
name: "--thread",
|
|
7194
|
+
type: "string",
|
|
7195
|
+
required: false
|
|
7196
|
+
},
|
|
7197
|
+
{
|
|
6864
7198
|
name: "--new-thread",
|
|
6865
7199
|
type: "boolean",
|
|
6866
7200
|
required: false
|
|
@@ -6931,7 +7265,7 @@ const commandTree = [
|
|
|
6931
7265
|
name: "--store",
|
|
6932
7266
|
type: "string",
|
|
6933
7267
|
required: true,
|
|
6934
|
-
choices: [
|
|
7268
|
+
choices: [...STORE_CHOICES]
|
|
6935
7269
|
}],
|
|
6936
7270
|
idempotent: false,
|
|
6937
7271
|
destructive: false
|
|
@@ -7171,7 +7505,12 @@ const commandTree = [
|
|
|
7171
7505
|
{
|
|
7172
7506
|
name: "--env",
|
|
7173
7507
|
type: "string",
|
|
7174
|
-
required: false
|
|
7508
|
+
required: false,
|
|
7509
|
+
choices: [
|
|
7510
|
+
"development",
|
|
7511
|
+
"preview",
|
|
7512
|
+
"production"
|
|
7513
|
+
]
|
|
7175
7514
|
}
|
|
7176
7515
|
],
|
|
7177
7516
|
idempotent: false,
|
|
@@ -7291,7 +7630,7 @@ const commandTree = [
|
|
|
7291
7630
|
{
|
|
7292
7631
|
name: "--name",
|
|
7293
7632
|
type: "string",
|
|
7294
|
-
required:
|
|
7633
|
+
required: true
|
|
7295
7634
|
}
|
|
7296
7635
|
],
|
|
7297
7636
|
idempotent: false,
|
|
@@ -7317,6 +7656,10 @@ const commandTree = [
|
|
|
7317
7656
|
name: "<databaseId>",
|
|
7318
7657
|
type: "string",
|
|
7319
7658
|
required: true
|
|
7659
|
+
}, {
|
|
7660
|
+
name: "--mask",
|
|
7661
|
+
type: "boolean",
|
|
7662
|
+
required: false
|
|
7320
7663
|
}],
|
|
7321
7664
|
idempotent: true,
|
|
7322
7665
|
destructive: false
|
|
@@ -7473,7 +7816,13 @@ const commandTree = [
|
|
|
7473
7816
|
{
|
|
7474
7817
|
name: "--role",
|
|
7475
7818
|
type: "string",
|
|
7476
|
-
required: false
|
|
7819
|
+
required: false,
|
|
7820
|
+
choices: [
|
|
7821
|
+
"owner",
|
|
7822
|
+
"admin",
|
|
7823
|
+
"editor",
|
|
7824
|
+
"viewer"
|
|
7825
|
+
]
|
|
7477
7826
|
}
|
|
7478
7827
|
],
|
|
7479
7828
|
idempotent: false,
|
|
@@ -7512,7 +7861,13 @@ const commandTree = [
|
|
|
7512
7861
|
{
|
|
7513
7862
|
name: "<role>",
|
|
7514
7863
|
type: "string",
|
|
7515
|
-
required: true
|
|
7864
|
+
required: true,
|
|
7865
|
+
choices: [
|
|
7866
|
+
"owner",
|
|
7867
|
+
"admin",
|
|
7868
|
+
"editor",
|
|
7869
|
+
"viewer"
|
|
7870
|
+
]
|
|
7516
7871
|
},
|
|
7517
7872
|
{
|
|
7518
7873
|
name: "--org",
|
|
@@ -7703,7 +8058,10 @@ function readLinkedProject() {
|
|
|
7703
8058
|
try {
|
|
7704
8059
|
const raw = readFileSync(filePath, "utf8");
|
|
7705
8060
|
const data = JSON.parse(raw);
|
|
7706
|
-
if (data.
|
|
8061
|
+
if (typeof data.projectId === "string" && data.projectId.length > 0) return {
|
|
8062
|
+
orgId: typeof data.orgId === "string" && data.orgId.length > 0 ? data.orgId : null,
|
|
8063
|
+
projectId: data.projectId
|
|
8064
|
+
};
|
|
7707
8065
|
return null;
|
|
7708
8066
|
} catch {
|
|
7709
8067
|
return null;
|
|
@@ -7756,7 +8114,7 @@ const linkCommand = {
|
|
|
7756
8114
|
});
|
|
7757
8115
|
return;
|
|
7758
8116
|
}
|
|
7759
|
-
const orgId = getStoredOrgId() ??
|
|
8117
|
+
const orgId = getStoredOrgId() ?? null;
|
|
7760
8118
|
const dir = join(process.cwd(), ANYTHING_DIR$1);
|
|
7761
8119
|
mkdirSync(dir, { recursive: true });
|
|
7762
8120
|
writeFileSync(join(dir, PROJECT_FILE), JSON.stringify({
|
|
@@ -7785,19 +8143,23 @@ const unlinkCommand = {
|
|
|
7785
8143
|
handler: (argv) => {
|
|
7786
8144
|
const command = "unlink";
|
|
7787
8145
|
const dir = join(process.cwd(), ANYTHING_DIR$1);
|
|
7788
|
-
|
|
8146
|
+
const projectFile = getProjectFilePath();
|
|
8147
|
+
if (!existsSync(projectFile)) {
|
|
7789
8148
|
outputError({
|
|
7790
8149
|
argv,
|
|
7791
8150
|
command,
|
|
7792
8151
|
error: {
|
|
7793
|
-
message: "No
|
|
8152
|
+
message: "No linked project found in current directory.",
|
|
7794
8153
|
status: null
|
|
7795
8154
|
},
|
|
7796
8155
|
exitCode: 3
|
|
7797
8156
|
});
|
|
7798
8157
|
return;
|
|
7799
8158
|
}
|
|
7800
|
-
rmSync(
|
|
8159
|
+
rmSync(projectFile);
|
|
8160
|
+
try {
|
|
8161
|
+
if (existsSync(dir) && readdirSync(dir).length === 0) rmSync(dir, { recursive: true });
|
|
8162
|
+
} catch {}
|
|
7801
8163
|
if (outputSuccess({
|
|
7802
8164
|
argv,
|
|
7803
8165
|
command,
|
|
@@ -7999,12 +8361,19 @@ const llmContextCommand = {
|
|
|
7999
8361
|
|
|
8000
8362
|
//#endregion
|
|
8001
8363
|
//#region src/commands/members.ts
|
|
8364
|
+
const MEMBER_ROLE_CHOICES = [
|
|
8365
|
+
"owner",
|
|
8366
|
+
"admin",
|
|
8367
|
+
"editor",
|
|
8368
|
+
"viewer"
|
|
8369
|
+
];
|
|
8370
|
+
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
8002
8371
|
const membersListCommand = {
|
|
8003
8372
|
command: "list",
|
|
8004
8373
|
describe: "List organization members and pending invites",
|
|
8005
8374
|
builder: (yargs) => yargs.option("org", {
|
|
8006
8375
|
type: "string",
|
|
8007
|
-
describe: "Organization ID"
|
|
8376
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8008
8377
|
}).example("anything members list --org org_123", "List members"),
|
|
8009
8378
|
handler: async (argv) => {
|
|
8010
8379
|
const command = "members list";
|
|
@@ -8093,13 +8462,26 @@ const membersInviteCommand = {
|
|
|
8093
8462
|
describe: "Email address to invite"
|
|
8094
8463
|
}).option("org", {
|
|
8095
8464
|
type: "string",
|
|
8096
|
-
describe: "Organization ID"
|
|
8465
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8097
8466
|
}).option("role", {
|
|
8098
8467
|
type: "string",
|
|
8099
|
-
|
|
8468
|
+
choices: MEMBER_ROLE_CHOICES,
|
|
8469
|
+
describe: "Role to assign: owner, admin, editor, or viewer"
|
|
8100
8470
|
}).example("anything members invite user@example.com --org org_123", "Invite a member"),
|
|
8101
8471
|
handler: async (argv) => {
|
|
8102
8472
|
const command = "members invite";
|
|
8473
|
+
if (!EMAIL_PATTERN.test(argv.email)) {
|
|
8474
|
+
outputError({
|
|
8475
|
+
argv,
|
|
8476
|
+
command,
|
|
8477
|
+
error: {
|
|
8478
|
+
message: `Invalid email address: "${argv.email}".`,
|
|
8479
|
+
status: null
|
|
8480
|
+
},
|
|
8481
|
+
exitCode: 2
|
|
8482
|
+
});
|
|
8483
|
+
return;
|
|
8484
|
+
}
|
|
8103
8485
|
const config = resolveConfig({
|
|
8104
8486
|
dev: argv.dev,
|
|
8105
8487
|
apiUrl: argv.apiUrl
|
|
@@ -8179,7 +8561,7 @@ const membersRemoveCommand = {
|
|
|
8179
8561
|
describe: "Email address of the member to remove"
|
|
8180
8562
|
}).option("org", {
|
|
8181
8563
|
type: "string",
|
|
8182
|
-
describe: "Organization ID"
|
|
8564
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8183
8565
|
}).option("yes", {
|
|
8184
8566
|
type: "boolean",
|
|
8185
8567
|
default: false,
|
|
@@ -8277,10 +8659,11 @@ const membersRoleCommand = {
|
|
|
8277
8659
|
}).positional("role", {
|
|
8278
8660
|
type: "string",
|
|
8279
8661
|
demandOption: true,
|
|
8280
|
-
|
|
8662
|
+
choices: MEMBER_ROLE_CHOICES,
|
|
8663
|
+
describe: "New role: owner, admin, editor, or viewer"
|
|
8281
8664
|
}).option("org", {
|
|
8282
8665
|
type: "string",
|
|
8283
|
-
describe: "Organization ID"
|
|
8666
|
+
describe: "Organization ID (defaults to the active org)"
|
|
8284
8667
|
}).example("anything members role user@example.com admin --org org_123", "Change role to admin"),
|
|
8285
8668
|
handler: async (argv) => {
|
|
8286
8669
|
const command = "members role";
|
|
@@ -8317,6 +8700,19 @@ const membersRoleCommand = {
|
|
|
8317
8700
|
});
|
|
8318
8701
|
return;
|
|
8319
8702
|
}
|
|
8703
|
+
if (argv["dry-run"]) {
|
|
8704
|
+
outputDryRun({
|
|
8705
|
+
argv,
|
|
8706
|
+
command,
|
|
8707
|
+
plannedActions: [{
|
|
8708
|
+
action: "update_member_role",
|
|
8709
|
+
org: orgResult.orgId,
|
|
8710
|
+
email: argv.email,
|
|
8711
|
+
role: argv.role
|
|
8712
|
+
}]
|
|
8713
|
+
});
|
|
8714
|
+
return;
|
|
8715
|
+
}
|
|
8320
8716
|
const result = await new AnythingApiClient(config.value).updateMemberRole({
|
|
8321
8717
|
organizationId: orgResult.orgId,
|
|
8322
8718
|
email: argv.email,
|
|
@@ -8625,20 +9021,28 @@ const orgsCommand = {
|
|
|
8625
9021
|
|
|
8626
9022
|
//#endregion
|
|
8627
9023
|
//#region src/stream.ts
|
|
9024
|
+
function resultErrorMessage(error) {
|
|
9025
|
+
if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
|
|
9026
|
+
return "Operation failed";
|
|
9027
|
+
}
|
|
8628
9028
|
function createEmitter(argv) {
|
|
8629
9029
|
if (argv.quiet) return (_event) => {};
|
|
8630
9030
|
if (argv.json) return (event) => {
|
|
8631
9031
|
printNdjson(event);
|
|
8632
9032
|
};
|
|
8633
9033
|
return (event) => {
|
|
8634
|
-
if (event.type === "progress")
|
|
9034
|
+
if (event.type === "progress") {
|
|
9035
|
+
printStreamMarker(event.status === "complete" ? "done" : "progress", event.message ?? `${event.step}...`);
|
|
9036
|
+
return;
|
|
9037
|
+
}
|
|
9038
|
+
if (event.type === "result" && !event.ok) printError(`[error] ${resultErrorMessage(event.error)}`);
|
|
8635
9039
|
};
|
|
8636
9040
|
}
|
|
8637
9041
|
|
|
8638
9042
|
//#endregion
|
|
8639
9043
|
//#region src/watch-generation.ts
|
|
8640
9044
|
const TIMEOUT_MS = 300 * 1e3;
|
|
8641
|
-
const POLL_INTERVAL_MS
|
|
9045
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
8642
9046
|
const TERMINAL_SUCCESS_STATUSES = new Set(["COMPLETED", "VALID"]);
|
|
8643
9047
|
const TERMINAL_FAILURE_STATUSES = new Set([
|
|
8644
9048
|
"INVALID",
|
|
@@ -8762,7 +9166,7 @@ async function pollUntilTerminal({ client, projectGroupId, emit, sleepFn = sleep
|
|
|
8762
9166
|
while (Date.now() < deadlineMs) {
|
|
8763
9167
|
const result = await client.getProjectStatus({ projectGroupId });
|
|
8764
9168
|
if (result.isErr()) {
|
|
8765
|
-
await sleepFn(POLL_INTERVAL_MS
|
|
9169
|
+
await sleepFn(POLL_INTERVAL_MS);
|
|
8766
9170
|
continue;
|
|
8767
9171
|
}
|
|
8768
9172
|
const { status } = result.value;
|
|
@@ -8786,7 +9190,7 @@ async function pollUntilTerminal({ client, projectGroupId, emit, sleepFn = sleep
|
|
|
8786
9190
|
});
|
|
8787
9191
|
return false;
|
|
8788
9192
|
}
|
|
8789
|
-
await sleepFn(POLL_INTERVAL_MS
|
|
9193
|
+
await sleepFn(POLL_INTERVAL_MS);
|
|
8790
9194
|
}
|
|
8791
9195
|
emit({
|
|
8792
9196
|
type: "result",
|
|
@@ -8845,7 +9249,11 @@ const createCommand = {
|
|
|
8845
9249
|
}).option("name", {
|
|
8846
9250
|
type: "string",
|
|
8847
9251
|
describe: "App name (optional)"
|
|
8848
|
-
}).
|
|
9252
|
+
}).option("wait", {
|
|
9253
|
+
type: "boolean",
|
|
9254
|
+
default: true,
|
|
9255
|
+
describe: "Wait for generation to complete (use --no-wait to skip)"
|
|
9256
|
+
}).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
9257
|
handler: async (argv) => {
|
|
8850
9258
|
const config = resolveConfig({
|
|
8851
9259
|
dev: argv.dev,
|
|
@@ -8934,6 +9342,25 @@ const createCommand = {
|
|
|
8934
9342
|
status: "complete",
|
|
8935
9343
|
message: "Project created"
|
|
8936
9344
|
});
|
|
9345
|
+
if (!argv.wait) {
|
|
9346
|
+
if (argv.quiet) {
|
|
9347
|
+
console.log(result.value.projectGroupId);
|
|
9348
|
+
return;
|
|
9349
|
+
}
|
|
9350
|
+
if (argv.json) {
|
|
9351
|
+
printNdjson({
|
|
9352
|
+
type: "result",
|
|
9353
|
+
ok: true,
|
|
9354
|
+
data: result.value
|
|
9355
|
+
});
|
|
9356
|
+
return;
|
|
9357
|
+
}
|
|
9358
|
+
printStreamMarker("done", `project ${result.value.projectGroupId} created`);
|
|
9359
|
+
printSuccess("App created! Generation enqueued.");
|
|
9360
|
+
printLabel("Project Group ID", result.value.projectGroupId);
|
|
9361
|
+
printLabel("Revision ID", result.value.revisionId);
|
|
9362
|
+
return;
|
|
9363
|
+
}
|
|
8937
9364
|
emit({
|
|
8938
9365
|
type: "progress",
|
|
8939
9366
|
step: "generating",
|
|
@@ -9055,7 +9482,10 @@ const publishStatusCommand = {
|
|
|
9055
9482
|
}).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
9483
|
handler: async (argv) => {
|
|
9057
9484
|
const command = "projects publish status";
|
|
9058
|
-
const config = resolveConfig({
|
|
9485
|
+
const config = resolveConfig({
|
|
9486
|
+
dev: argv.dev,
|
|
9487
|
+
apiUrl: argv.apiUrl
|
|
9488
|
+
});
|
|
9059
9489
|
if (config.isErr()) {
|
|
9060
9490
|
outputError({
|
|
9061
9491
|
argv,
|
|
@@ -9079,14 +9509,23 @@ const publishStatusCommand = {
|
|
|
9079
9509
|
}
|
|
9080
9510
|
const { deployment } = result.value;
|
|
9081
9511
|
if (deployment.status === "FAILED") {
|
|
9082
|
-
|
|
9083
|
-
|
|
9512
|
+
const failure = getDeploymentError({
|
|
9513
|
+
result: {
|
|
9514
|
+
outcome: "completed",
|
|
9515
|
+
deployment
|
|
9516
|
+
},
|
|
9517
|
+
statusCommand: `anything deployments logs ${argv.deploymentId}`
|
|
9518
|
+
});
|
|
9519
|
+
outputError({
|
|
9084
9520
|
argv,
|
|
9085
9521
|
command,
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9522
|
+
error: {
|
|
9523
|
+
message: failure?.message ?? "Deployment failed (no logs available).",
|
|
9524
|
+
status: null
|
|
9525
|
+
},
|
|
9526
|
+
hint: `Inspect the full build logs with: anything deployments logs ${argv.deploymentId}`,
|
|
9527
|
+
exitCode: failure?.exitCode ?? 1
|
|
9528
|
+
});
|
|
9090
9529
|
return;
|
|
9091
9530
|
}
|
|
9092
9531
|
if (outputSuccess({
|
|
@@ -9338,7 +9777,7 @@ const list$1 = {
|
|
|
9338
9777
|
describe: "The project ID"
|
|
9339
9778
|
}).example("anything projects files list <id>", "List the files available in a project"),
|
|
9340
9779
|
handler: async (argv) => {
|
|
9341
|
-
const command = "files list";
|
|
9780
|
+
const command = "projects files list";
|
|
9342
9781
|
const config = resolveConfig({
|
|
9343
9782
|
dev: argv.dev,
|
|
9344
9783
|
apiUrl: argv.apiUrl
|
|
@@ -9393,7 +9832,7 @@ const get$1 = {
|
|
|
9393
9832
|
describe: "The file path"
|
|
9394
9833
|
}).example("anything projects files get <id> app/page.tsx", "Print a file to stdout"),
|
|
9395
9834
|
handler: async (argv) => {
|
|
9396
|
-
const command = "files get";
|
|
9835
|
+
const command = "projects files get";
|
|
9397
9836
|
const config = resolveConfig({
|
|
9398
9837
|
dev: argv.dev,
|
|
9399
9838
|
apiUrl: argv.apiUrl
|
|
@@ -9731,7 +10170,10 @@ const infoCommand = {
|
|
|
9731
10170
|
printLabel("Published URL", latestPublishedUrl);
|
|
9732
10171
|
printLabel("Created", new Date(info.createdAt).toLocaleString());
|
|
9733
10172
|
printLabel("Updated", new Date(info.updatedAt).toLocaleString());
|
|
9734
|
-
for (const url of info.publishedUrls)
|
|
10173
|
+
for (const url of info.publishedUrls) {
|
|
10174
|
+
if (url === latestPublishedUrl) continue;
|
|
10175
|
+
printLabel("Other Published URL", url);
|
|
10176
|
+
}
|
|
9735
10177
|
if (info.files.length > 0) {
|
|
9736
10178
|
console.log();
|
|
9737
10179
|
printTable({
|
|
@@ -10006,6 +10448,96 @@ const logsCommand = {
|
|
|
10006
10448
|
}
|
|
10007
10449
|
};
|
|
10008
10450
|
|
|
10451
|
+
//#endregion
|
|
10452
|
+
//#region src/format-assistant-message.ts
|
|
10453
|
+
const NAMED_ENTITIES = {
|
|
10454
|
+
""": "\"",
|
|
10455
|
+
"'": "'",
|
|
10456
|
+
"'": "'",
|
|
10457
|
+
"<": "<",
|
|
10458
|
+
">": ">",
|
|
10459
|
+
" ": " "
|
|
10460
|
+
};
|
|
10461
|
+
function decodeEntities(input) {
|
|
10462
|
+
return input.replace(/&(?:quot|apos|#39|lt|gt|nbsp);/g, (m) => NAMED_ENTITIES[m] ?? m).replace(/&/g, "&");
|
|
10463
|
+
}
|
|
10464
|
+
function stripTags(input) {
|
|
10465
|
+
return input.replace(/<[^>]+>/g, "");
|
|
10466
|
+
}
|
|
10467
|
+
function parseAttrs(attrString) {
|
|
10468
|
+
const attrs = {};
|
|
10469
|
+
const re = /([a-zA-Z][\w-]*)="([^"]*)"/g;
|
|
10470
|
+
let match;
|
|
10471
|
+
while ((match = re.exec(attrString)) !== null) {
|
|
10472
|
+
const [, key, value] = match;
|
|
10473
|
+
if (key !== void 0 && value !== void 0) attrs[key] = value;
|
|
10474
|
+
}
|
|
10475
|
+
return attrs;
|
|
10476
|
+
}
|
|
10477
|
+
function firstLine(text) {
|
|
10478
|
+
return (text.split("\n").map((l) => l.trim()).find(Boolean) ?? "").replace(/\*\*/g, "");
|
|
10479
|
+
}
|
|
10480
|
+
function indent(text) {
|
|
10481
|
+
return text.split("\n").map((l) => ` ${l}`).join("\n");
|
|
10482
|
+
}
|
|
10483
|
+
function parseTodos(raw) {
|
|
10484
|
+
if (!raw) return [];
|
|
10485
|
+
try {
|
|
10486
|
+
const parsed = JSON.parse(decodeEntities(raw));
|
|
10487
|
+
if (!Array.isArray(parsed)) return [];
|
|
10488
|
+
return parsed.filter((t) => !!t && typeof t === "object" && typeof t.content === "string").map((t) => ({
|
|
10489
|
+
content: t.content,
|
|
10490
|
+
status: typeof t.status === "string" ? t.status : "pending"
|
|
10491
|
+
}));
|
|
10492
|
+
} catch {
|
|
10493
|
+
return [];
|
|
10494
|
+
}
|
|
10495
|
+
}
|
|
10496
|
+
function renderBlock(attrs) {
|
|
10497
|
+
const uiType = attrs.uiType ?? "block";
|
|
10498
|
+
const text = decodeEntities(attrs.text ?? "").trim();
|
|
10499
|
+
const subtext = decodeEntities(attrs.subtext ?? "").trim();
|
|
10500
|
+
if (uiType === "todo-list") {
|
|
10501
|
+
const lines = [`[plan] ${text || "Plan"}${subtext ? ` — ${subtext}` : ""}`];
|
|
10502
|
+
for (const todo of parseTodos(attrs.todos)) {
|
|
10503
|
+
const box = todo.status === "completed" ? "[x]" : todo.status === "in_progress" ? "[~]" : "[ ]";
|
|
10504
|
+
lines.push(` ${box} ${todo.content}`);
|
|
10505
|
+
}
|
|
10506
|
+
return lines.join("\n");
|
|
10507
|
+
}
|
|
10508
|
+
if (uiType === "thinking") {
|
|
10509
|
+
const summary = firstLine(subtext) || text;
|
|
10510
|
+
return summary ? `[thinking] ${summary}` : null;
|
|
10511
|
+
}
|
|
10512
|
+
if (uiType === "database") {
|
|
10513
|
+
const code = decodeEntities(attrs.code ?? "").trim();
|
|
10514
|
+
const head = `[database] ${text || "change"}`;
|
|
10515
|
+
return code ? `${head}\n${indent(code)}` : head;
|
|
10516
|
+
}
|
|
10517
|
+
const parts = [text, subtext].filter(Boolean);
|
|
10518
|
+
if (parts.length === 0) return null;
|
|
10519
|
+
return `[${uiType}] ${parts.join(" — ")}`;
|
|
10520
|
+
}
|
|
10521
|
+
function formatAssistantMessage(raw) {
|
|
10522
|
+
const blockRe = /<file-based-block\b([^>]*)>([\s\S]*?)<\/file-based-block>/g;
|
|
10523
|
+
const segments = [];
|
|
10524
|
+
let lastIndex = 0;
|
|
10525
|
+
let hadBlock = false;
|
|
10526
|
+
let match;
|
|
10527
|
+
while ((match = blockRe.exec(raw)) !== null) {
|
|
10528
|
+
hadBlock = true;
|
|
10529
|
+
const between = stripTags(raw.slice(lastIndex, match.index)).trim();
|
|
10530
|
+
if (between) segments.push(decodeEntities(between));
|
|
10531
|
+
const rendered = renderBlock(parseAttrs(match[1] ?? ""));
|
|
10532
|
+
if (rendered) segments.push(rendered);
|
|
10533
|
+
lastIndex = blockRe.lastIndex;
|
|
10534
|
+
}
|
|
10535
|
+
if (!hadBlock) return decodeEntities(stripTags(raw)).trim();
|
|
10536
|
+
const tail = stripTags(raw.slice(lastIndex)).trim();
|
|
10537
|
+
if (tail) segments.push(decodeEntities(tail));
|
|
10538
|
+
return segments.filter(Boolean).join("\n");
|
|
10539
|
+
}
|
|
10540
|
+
|
|
10009
10541
|
//#endregion
|
|
10010
10542
|
//#region src/commands/messages.ts
|
|
10011
10543
|
const COMMAND$9 = "projects messages";
|
|
@@ -10014,7 +10546,13 @@ function formatMessage(msg) {
|
|
|
10014
10546
|
const status = msg.status === "VALID" ? styleText("green", msg.status) : msg.status === "BUILDING" ? styleText("yellow", msg.status) : styleText("red", msg.status);
|
|
10015
10547
|
console.log(styleText("dim", `─── ${time} ─── ${status} ───`));
|
|
10016
10548
|
if (msg.userMessage) console.log(styleText("bold", "You: ") + msg.userMessage);
|
|
10017
|
-
if (msg.assistantMessage)
|
|
10549
|
+
if (msg.assistantMessage) {
|
|
10550
|
+
const text = formatAssistantMessage(msg.assistantMessage);
|
|
10551
|
+
if (text) {
|
|
10552
|
+
console.log(styleText("bold", "Assistant:"));
|
|
10553
|
+
console.log(text);
|
|
10554
|
+
}
|
|
10555
|
+
}
|
|
10018
10556
|
console.log();
|
|
10019
10557
|
}
|
|
10020
10558
|
const messagesCommand = {
|
|
@@ -10061,12 +10599,15 @@ const messagesCommand = {
|
|
|
10061
10599
|
});
|
|
10062
10600
|
return;
|
|
10063
10601
|
}
|
|
10602
|
+
const { messages } = result.value;
|
|
10064
10603
|
if (outputSuccess({
|
|
10065
10604
|
argv,
|
|
10066
10605
|
command: COMMAND$9,
|
|
10067
|
-
data:
|
|
10606
|
+
data: { messages: messages.map((msg) => ({
|
|
10607
|
+
...msg,
|
|
10608
|
+
assistantText: msg.assistantMessage ? formatAssistantMessage(msg.assistantMessage) : null
|
|
10609
|
+
})) }
|
|
10068
10610
|
})) return;
|
|
10069
|
-
const { messages } = result.value;
|
|
10070
10611
|
if (messages.length === 0) {
|
|
10071
10612
|
console.log("No messages found.");
|
|
10072
10613
|
return;
|
|
@@ -10223,6 +10764,11 @@ const renameCommand = {
|
|
|
10223
10764
|
|
|
10224
10765
|
//#endregion
|
|
10225
10766
|
//#region src/commands/secrets.ts
|
|
10767
|
+
const secretEnvironmentChoices = [
|
|
10768
|
+
"development",
|
|
10769
|
+
"preview",
|
|
10770
|
+
"production"
|
|
10771
|
+
];
|
|
10226
10772
|
const add = {
|
|
10227
10773
|
command: "add <projectId>",
|
|
10228
10774
|
describe: "Add a secret to an app",
|
|
@@ -10239,10 +10785,11 @@ const add = {
|
|
|
10239
10785
|
describe: "Secret value. If omitted, reads stdin when piped."
|
|
10240
10786
|
}).option("env", {
|
|
10241
10787
|
type: "string",
|
|
10242
|
-
|
|
10788
|
+
choices: secretEnvironmentChoices,
|
|
10789
|
+
describe: "Target environment for the secret"
|
|
10243
10790
|
}).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
10791
|
handler: async (argv) => {
|
|
10245
|
-
const command = "secrets add";
|
|
10792
|
+
const command = "projects secrets add";
|
|
10246
10793
|
if (argv["dry-run"]) {
|
|
10247
10794
|
outputDryRun({
|
|
10248
10795
|
argv,
|
|
@@ -10251,7 +10798,7 @@ const add = {
|
|
|
10251
10798
|
action: "add_secret",
|
|
10252
10799
|
projectGroupId: argv.projectId,
|
|
10253
10800
|
name: argv.name,
|
|
10254
|
-
...argv.env ? { environment: argv.env } : {}
|
|
10801
|
+
...argv.env ? { environment: argv.env.toUpperCase() } : {}
|
|
10255
10802
|
}]
|
|
10256
10803
|
});
|
|
10257
10804
|
return;
|
|
@@ -10293,7 +10840,7 @@ const add = {
|
|
|
10293
10840
|
projectGroupId: argv.projectId,
|
|
10294
10841
|
displayName: argv.name,
|
|
10295
10842
|
value: valueResult.value,
|
|
10296
|
-
environment: argv.env
|
|
10843
|
+
environment: argv.env ? argv.env.toUpperCase() : null
|
|
10297
10844
|
});
|
|
10298
10845
|
if (result.isErr()) {
|
|
10299
10846
|
outputError({
|
|
@@ -10327,18 +10874,34 @@ const remove = {
|
|
|
10327
10874
|
type: "string",
|
|
10328
10875
|
demandOption: true,
|
|
10329
10876
|
describe: "The secret ID to remove"
|
|
10330
|
-
}).
|
|
10877
|
+
}).option("yes", {
|
|
10878
|
+
type: "boolean",
|
|
10879
|
+
default: false,
|
|
10880
|
+
describe: "Skip confirmation"
|
|
10881
|
+
}).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
10882
|
handler: async (argv) => {
|
|
10332
|
-
const command = "secrets remove";
|
|
10883
|
+
const command = "projects secrets remove";
|
|
10333
10884
|
if (argv["dry-run"]) {
|
|
10334
10885
|
outputDryRun({
|
|
10335
10886
|
argv,
|
|
10336
10887
|
command,
|
|
10337
|
-
plannedActions: [{
|
|
10338
|
-
action: "remove_secret",
|
|
10339
|
-
projectGroupId: argv.projectId,
|
|
10340
|
-
secretId: argv.secretId
|
|
10341
|
-
}]
|
|
10888
|
+
plannedActions: [{
|
|
10889
|
+
action: "remove_secret",
|
|
10890
|
+
projectGroupId: argv.projectId,
|
|
10891
|
+
secretId: argv.secretId
|
|
10892
|
+
}]
|
|
10893
|
+
});
|
|
10894
|
+
return;
|
|
10895
|
+
}
|
|
10896
|
+
if (!argv.yes) {
|
|
10897
|
+
outputError({
|
|
10898
|
+
argv,
|
|
10899
|
+
command,
|
|
10900
|
+
error: {
|
|
10901
|
+
message: "Removing a secret is destructive. Pass --yes to confirm.",
|
|
10902
|
+
status: null
|
|
10903
|
+
},
|
|
10904
|
+
exitCode: 2
|
|
10342
10905
|
});
|
|
10343
10906
|
return;
|
|
10344
10907
|
}
|
|
@@ -10388,7 +10951,7 @@ const list = {
|
|
|
10388
10951
|
describe: "The project ID"
|
|
10389
10952
|
}).example("anything projects secrets list <project-id>", "List secrets for an app"),
|
|
10390
10953
|
handler: async (argv) => {
|
|
10391
|
-
const command = "secrets list";
|
|
10954
|
+
const command = "projects secrets list";
|
|
10392
10955
|
const config = resolveConfig({
|
|
10393
10956
|
dev: argv.dev,
|
|
10394
10957
|
apiUrl: argv.apiUrl
|
|
@@ -10515,272 +11078,41 @@ function parseSecrets({ secretArgs, environment }) {
|
|
|
10515
11078
|
environment
|
|
10516
11079
|
});
|
|
10517
11080
|
}
|
|
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.");
|
|
11081
|
+
return {
|
|
11082
|
+
ok: true,
|
|
11083
|
+
value: secrets
|
|
11084
|
+
};
|
|
10769
11085
|
}
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
11086
|
+
function resolveSecretEnvironment(environment) {
|
|
11087
|
+
switch (environment) {
|
|
11088
|
+
case "development":
|
|
11089
|
+
case "preview":
|
|
11090
|
+
case "production": return environment;
|
|
11091
|
+
default: return null;
|
|
11092
|
+
}
|
|
11093
|
+
}
|
|
11094
|
+
const get = {
|
|
11095
|
+
command: "get [projectId]",
|
|
11096
|
+
describe: "Read project auth settings",
|
|
10773
11097
|
builder: (yargs) => yargs.positional("projectId", {
|
|
10774
11098
|
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"),
|
|
11099
|
+
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
11100
|
+
}).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
11101
|
handler: async (argv) => {
|
|
10783
|
-
const command = "projects
|
|
11102
|
+
const command = "projects settings auth get";
|
|
11103
|
+
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
11104
|
+
if (projectGroupId === null) {
|
|
11105
|
+
outputError({
|
|
11106
|
+
argv,
|
|
11107
|
+
command,
|
|
11108
|
+
error: {
|
|
11109
|
+
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
11110
|
+
status: null
|
|
11111
|
+
},
|
|
11112
|
+
exitCode: 2
|
|
11113
|
+
});
|
|
11114
|
+
return;
|
|
11115
|
+
}
|
|
10784
11116
|
const config = resolveConfig({
|
|
10785
11117
|
dev: argv.dev,
|
|
10786
11118
|
apiUrl: argv.apiUrl
|
|
@@ -10797,10 +11129,7 @@ const submitStatusCommand = {
|
|
|
10797
11129
|
});
|
|
10798
11130
|
return;
|
|
10799
11131
|
}
|
|
10800
|
-
const result = await new AnythingApiClient(config.value).
|
|
10801
|
-
projectGroupId: argv.projectId,
|
|
10802
|
-
submissionId: argv.submissionId
|
|
10803
|
-
});
|
|
11132
|
+
const result = await new AnythingApiClient(config.value).getProjectAuthSettings({ projectGroupId });
|
|
10804
11133
|
if (result.isErr()) {
|
|
10805
11134
|
outputError({
|
|
10806
11135
|
argv,
|
|
@@ -10809,102 +11138,151 @@ const submitStatusCommand = {
|
|
|
10809
11138
|
});
|
|
10810
11139
|
return;
|
|
10811
11140
|
}
|
|
10812
|
-
|
|
11141
|
+
if (outputSuccess({
|
|
10813
11142
|
argv,
|
|
10814
11143
|
command,
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
11144
|
+
data: result.value
|
|
11145
|
+
})) return;
|
|
11146
|
+
printAuthSettings(result.value);
|
|
10818
11147
|
}
|
|
10819
11148
|
};
|
|
10820
|
-
const
|
|
10821
|
-
command: "
|
|
10822
|
-
describe: "
|
|
10823
|
-
builder: (yargs) => yargs.
|
|
11149
|
+
const set = {
|
|
11150
|
+
command: "set [projectId]",
|
|
11151
|
+
describe: "Update project auth settings for a provider",
|
|
11152
|
+
builder: (yargs) => yargs.positional("projectId", {
|
|
10824
11153
|
type: "string",
|
|
11154
|
+
describe: "The project ID. Falls back to the current project set via `anything projects set`."
|
|
11155
|
+
}).option("provider", {
|
|
11156
|
+
choices: authProviderChoices,
|
|
10825
11157
|
demandOption: true,
|
|
10826
|
-
describe: "The
|
|
10827
|
-
}).option("
|
|
11158
|
+
describe: "The auth provider to update"
|
|
11159
|
+
}).option("enabled", {
|
|
11160
|
+
type: "boolean",
|
|
11161
|
+
demandOption: true,
|
|
11162
|
+
describe: "Whether to enable the provider. Use --no-enabled to disable it."
|
|
11163
|
+
}).option("secret", {
|
|
10828
11164
|
type: "string",
|
|
10829
|
-
|
|
10830
|
-
describe: "
|
|
10831
|
-
}).
|
|
11165
|
+
array: true,
|
|
11166
|
+
describe: "Provider secret in ENV_KEY=VALUE format. Repeat for multiple secrets."
|
|
11167
|
+
}).option("env", {
|
|
11168
|
+
choices: authEnvironmentChoices,
|
|
11169
|
+
default: "production",
|
|
11170
|
+
describe: "Environment for secrets passed via --secret"
|
|
11171
|
+
}).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
11172
|
handler: async (argv) => {
|
|
10833
|
-
const command = "projects
|
|
10834
|
-
|
|
11173
|
+
const command = "projects settings auth set";
|
|
11174
|
+
const projectGroupId = resolveProjectGroupId(argv.projectId);
|
|
11175
|
+
if (projectGroupId === null) {
|
|
10835
11176
|
outputError({
|
|
10836
11177
|
argv,
|
|
10837
11178
|
command,
|
|
10838
11179
|
error: {
|
|
10839
|
-
message: "
|
|
11180
|
+
message: "No project specified. Pass a project ID or run `anything projects set <project-id>`.",
|
|
10840
11181
|
status: null
|
|
10841
11182
|
},
|
|
10842
11183
|
exitCode: 2
|
|
10843
11184
|
});
|
|
10844
11185
|
return;
|
|
10845
11186
|
}
|
|
10846
|
-
|
|
11187
|
+
const secretEnvironment = resolveSecretEnvironment(argv.env);
|
|
11188
|
+
if (secretEnvironment === null) {
|
|
10847
11189
|
outputError({
|
|
10848
11190
|
argv,
|
|
10849
11191
|
command,
|
|
10850
11192
|
error: {
|
|
10851
|
-
message: "
|
|
11193
|
+
message: `Invalid --env value "${argv.env}".`,
|
|
10852
11194
|
status: null
|
|
10853
11195
|
},
|
|
10854
11196
|
exitCode: 2
|
|
10855
11197
|
});
|
|
10856
11198
|
return;
|
|
10857
11199
|
}
|
|
10858
|
-
const
|
|
10859
|
-
|
|
10860
|
-
|
|
11200
|
+
const secretsResult = parseSecrets({
|
|
11201
|
+
secretArgs: argv.secret ?? [],
|
|
11202
|
+
environment: secretEnvironment
|
|
10861
11203
|
});
|
|
10862
|
-
if (
|
|
11204
|
+
if (!secretsResult.ok) {
|
|
10863
11205
|
outputError({
|
|
10864
11206
|
argv,
|
|
10865
11207
|
command,
|
|
10866
11208
|
error: {
|
|
10867
|
-
message:
|
|
11209
|
+
message: secretsResult.error,
|
|
10868
11210
|
status: null
|
|
10869
11211
|
},
|
|
10870
|
-
exitCode:
|
|
11212
|
+
exitCode: 2
|
|
10871
11213
|
});
|
|
10872
11214
|
return;
|
|
10873
11215
|
}
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
11216
|
+
if (argv["dry-run"]) {
|
|
11217
|
+
outputDryRun({
|
|
11218
|
+
argv,
|
|
11219
|
+
command,
|
|
11220
|
+
plannedActions: [{
|
|
11221
|
+
action: "update_auth_settings",
|
|
11222
|
+
projectGroupId,
|
|
11223
|
+
provider: argv.provider,
|
|
11224
|
+
enabled: argv.enabled,
|
|
11225
|
+
environment: secretEnvironment,
|
|
11226
|
+
secretKeys: secretsResult.value.map((secret) => secret.envKey)
|
|
11227
|
+
}]
|
|
11228
|
+
});
|
|
11229
|
+
return;
|
|
11230
|
+
}
|
|
11231
|
+
const config = resolveConfig({
|
|
11232
|
+
dev: argv.dev,
|
|
11233
|
+
apiUrl: argv.apiUrl
|
|
10878
11234
|
});
|
|
10879
|
-
if (
|
|
11235
|
+
if (config.isErr()) {
|
|
10880
11236
|
outputError({
|
|
10881
11237
|
argv,
|
|
10882
11238
|
command,
|
|
10883
|
-
error:
|
|
11239
|
+
error: {
|
|
11240
|
+
message: config.error.message,
|
|
11241
|
+
status: null
|
|
11242
|
+
},
|
|
11243
|
+
exitCode: 4
|
|
10884
11244
|
});
|
|
10885
11245
|
return;
|
|
10886
11246
|
}
|
|
10887
|
-
const
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
11247
|
+
const result = await new AnythingApiClient(config.value).updateProjectAuthSettings({
|
|
11248
|
+
projectGroupId,
|
|
11249
|
+
provider: argv.provider,
|
|
11250
|
+
enabled: argv.enabled,
|
|
11251
|
+
secrets: secretsResult.value,
|
|
11252
|
+
enableForAllModules: false
|
|
10891
11253
|
});
|
|
10892
|
-
if (
|
|
11254
|
+
if (result.isErr()) {
|
|
10893
11255
|
outputError({
|
|
10894
11256
|
argv,
|
|
10895
11257
|
command,
|
|
10896
|
-
error:
|
|
11258
|
+
error: result.error
|
|
10897
11259
|
});
|
|
10898
11260
|
return;
|
|
10899
11261
|
}
|
|
10900
|
-
|
|
11262
|
+
if (outputSuccess({
|
|
10901
11263
|
argv,
|
|
10902
11264
|
command,
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
11265
|
+
data: result.value
|
|
11266
|
+
})) return;
|
|
11267
|
+
printSuccess("Auth settings updated.");
|
|
11268
|
+
printAuthSettings(result.value);
|
|
10906
11269
|
}
|
|
10907
11270
|
};
|
|
11271
|
+
const authSettingsCommand = {
|
|
11272
|
+
command: "auth <command>",
|
|
11273
|
+
describe: "Manage auth-related project settings",
|
|
11274
|
+
builder: (yargs) => yargs.command(get).command(set).demandCommand(),
|
|
11275
|
+
handler: () => {}
|
|
11276
|
+
};
|
|
11277
|
+
|
|
11278
|
+
//#endregion
|
|
11279
|
+
//#region src/commands/settings.ts
|
|
11280
|
+
const settingsCommand = {
|
|
11281
|
+
command: "settings <command>",
|
|
11282
|
+
describe: "Inspect and update project settings",
|
|
11283
|
+
builder: (yargs) => yargs.command(authSettingsCommand).example("anything projects settings auth get <project-id>", "Inspect project auth settings").demandCommand(),
|
|
11284
|
+
handler: () => {}
|
|
11285
|
+
};
|
|
10908
11286
|
|
|
10909
11287
|
//#endregion
|
|
10910
11288
|
//#region src/commands/unpublish.ts
|
|
@@ -10922,6 +11300,17 @@ const unpublishCommand = {
|
|
|
10922
11300
|
describe: "Confirm unpublishing without prompting"
|
|
10923
11301
|
}).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
11302
|
handler: async (argv) => {
|
|
11303
|
+
if (argv["dry-run"]) {
|
|
11304
|
+
outputDryRun({
|
|
11305
|
+
argv,
|
|
11306
|
+
command: COMMAND$6,
|
|
11307
|
+
plannedActions: [{
|
|
11308
|
+
action: "unpublish_project",
|
|
11309
|
+
projectGroupId: argv.projectId
|
|
11310
|
+
}]
|
|
11311
|
+
});
|
|
11312
|
+
return;
|
|
11313
|
+
}
|
|
10925
11314
|
if (!argv.yes && !isNonInteractive(argv)) {
|
|
10926
11315
|
outputError({
|
|
10927
11316
|
argv,
|
|
@@ -10934,17 +11323,6 @@ const unpublishCommand = {
|
|
|
10934
11323
|
});
|
|
10935
11324
|
return;
|
|
10936
11325
|
}
|
|
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
11326
|
const config = resolveConfig({
|
|
10949
11327
|
dev: argv.dev,
|
|
10950
11328
|
apiUrl: argv.apiUrl
|
|
@@ -11002,6 +11380,17 @@ const deleteProjectCommand = {
|
|
|
11002
11380
|
describe: "Confirm deletion without prompting"
|
|
11003
11381
|
}).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
11382
|
handler: async (argv) => {
|
|
11383
|
+
if (argv["dry-run"]) {
|
|
11384
|
+
outputDryRun({
|
|
11385
|
+
argv,
|
|
11386
|
+
command: COMMAND$5,
|
|
11387
|
+
plannedActions: [{
|
|
11388
|
+
action: "delete_project",
|
|
11389
|
+
projectGroupId: argv.projectId
|
|
11390
|
+
}]
|
|
11391
|
+
});
|
|
11392
|
+
return;
|
|
11393
|
+
}
|
|
11005
11394
|
if (!argv.yes && !isNonInteractive(argv)) {
|
|
11006
11395
|
outputError({
|
|
11007
11396
|
argv,
|
|
@@ -11014,17 +11403,6 @@ const deleteProjectCommand = {
|
|
|
11014
11403
|
});
|
|
11015
11404
|
return;
|
|
11016
11405
|
}
|
|
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
11406
|
const config = resolveConfig({
|
|
11029
11407
|
dev: argv.dev,
|
|
11030
11408
|
apiUrl: argv.apiUrl
|
|
@@ -11044,10 +11422,12 @@ const deleteProjectCommand = {
|
|
|
11044
11422
|
const startTime = performance.now();
|
|
11045
11423
|
const result = await new AnythingApiClient(config.value).deleteProject({ projectGroupId: argv.projectId });
|
|
11046
11424
|
if (result.isErr()) {
|
|
11425
|
+
const hint = result.error.status === 404 ? "If the project ID is correct, project deletion may not be enabled for your account." : void 0;
|
|
11047
11426
|
outputError({
|
|
11048
11427
|
argv,
|
|
11049
11428
|
command: COMMAND$5,
|
|
11050
|
-
error: result.error
|
|
11429
|
+
error: result.error,
|
|
11430
|
+
hint
|
|
11051
11431
|
});
|
|
11052
11432
|
return;
|
|
11053
11433
|
}
|
|
@@ -11153,11 +11533,16 @@ const projectsSetCommand = {
|
|
|
11153
11533
|
return;
|
|
11154
11534
|
}
|
|
11155
11535
|
setStoredProjectGroupId(result.value.id);
|
|
11156
|
-
if (
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11536
|
+
if (outputSuccess({
|
|
11537
|
+
argv,
|
|
11538
|
+
command: "projects set",
|
|
11539
|
+
data: {
|
|
11540
|
+
projectId: result.value.id,
|
|
11541
|
+
name: result.value.name
|
|
11542
|
+
},
|
|
11543
|
+
primaryId: result.value.id
|
|
11544
|
+
})) return;
|
|
11545
|
+
printSuccess(`Current project set to ${result.value.name} (${result.value.id})`);
|
|
11161
11546
|
}
|
|
11162
11547
|
};
|
|
11163
11548
|
const projectsUnsetCommand = {
|
|
@@ -11166,8 +11551,12 @@ const projectsUnsetCommand = {
|
|
|
11166
11551
|
builder: (yargs) => yargs.example("anything projects unset", "Clear the saved project"),
|
|
11167
11552
|
handler: (argv) => {
|
|
11168
11553
|
clearStoredProjectGroupId();
|
|
11169
|
-
if (
|
|
11170
|
-
|
|
11554
|
+
if (outputSuccess({
|
|
11555
|
+
argv,
|
|
11556
|
+
command: "projects unset",
|
|
11557
|
+
data: { projectId: null }
|
|
11558
|
+
})) return;
|
|
11559
|
+
printSuccess("Current project cleared.");
|
|
11171
11560
|
}
|
|
11172
11561
|
};
|
|
11173
11562
|
const projectsCommand = {
|
|
@@ -11181,7 +11570,8 @@ const projectsCommand = {
|
|
|
11181
11570
|
//#region src/commands/pull.ts
|
|
11182
11571
|
const ANYTHING_DIR = ".anything";
|
|
11183
11572
|
const FILES_DIR = "files";
|
|
11184
|
-
|
|
11573
|
+
const DEFAULT_TIMEOUT_SECONDS = 60;
|
|
11574
|
+
async function pullFiles({ client, projectGroupId, argv }) {
|
|
11185
11575
|
const listResult = await client.listProjectFiles({ projectGroupId });
|
|
11186
11576
|
if (listResult.isErr()) {
|
|
11187
11577
|
printApiError(listResult.error);
|
|
@@ -11190,6 +11580,7 @@ async function pullFiles({ client, projectGroupId }) {
|
|
|
11190
11580
|
}
|
|
11191
11581
|
const filesDir = join(process.cwd(), ANYTHING_DIR, FILES_DIR);
|
|
11192
11582
|
if (!existsSync(filesDir)) mkdirSync(filesDir, { recursive: true });
|
|
11583
|
+
const totalFiles = listResult.value.files.length;
|
|
11193
11584
|
const pulled = [];
|
|
11194
11585
|
for (const file of listResult.value.files) {
|
|
11195
11586
|
const fileResult = await client.getProjectFile({
|
|
@@ -11205,6 +11596,12 @@ async function pullFiles({ client, projectGroupId }) {
|
|
|
11205
11596
|
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
11206
11597
|
writeFileSync(destPath, fileResult.value.file.content);
|
|
11207
11598
|
pulled.push(file.path);
|
|
11599
|
+
if (argv.json) printNdjson({
|
|
11600
|
+
type: "progress",
|
|
11601
|
+
file: file.path,
|
|
11602
|
+
completed: pulled.length,
|
|
11603
|
+
total: totalFiles
|
|
11604
|
+
});
|
|
11208
11605
|
}
|
|
11209
11606
|
return pulled;
|
|
11210
11607
|
}
|
|
@@ -11231,8 +11628,13 @@ const pullCommand = {
|
|
|
11231
11628
|
}).option("env", {
|
|
11232
11629
|
type: "boolean",
|
|
11233
11630
|
describe: "Write secret names to .env.example only"
|
|
11631
|
+
}).option("timeout", {
|
|
11632
|
+
type: "number",
|
|
11633
|
+
default: DEFAULT_TIMEOUT_SECONDS,
|
|
11634
|
+
describe: "Request timeout in seconds"
|
|
11234
11635
|
}).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
11636
|
handler: async (argv) => {
|
|
11637
|
+
const startTime = performance.now();
|
|
11236
11638
|
const linked = readLinkedProject();
|
|
11237
11639
|
if (!linked) {
|
|
11238
11640
|
printError("No linked project. Run `anything link <project-id>` first.");
|
|
@@ -11248,7 +11650,8 @@ const pullCommand = {
|
|
|
11248
11650
|
process.exitCode = 1;
|
|
11249
11651
|
return;
|
|
11250
11652
|
}
|
|
11251
|
-
const
|
|
11653
|
+
const timeoutSeconds = argv.timeout ?? DEFAULT_TIMEOUT_SECONDS;
|
|
11654
|
+
const client = new AnythingApiClient(config.value, { timeoutMs: timeoutSeconds * 1e3 });
|
|
11252
11655
|
const pullBoth = !argv.files && !argv.env;
|
|
11253
11656
|
const projectResult = await client.getProject({ projectGroupId: linked.projectId });
|
|
11254
11657
|
if (projectResult.isErr()) {
|
|
@@ -11261,7 +11664,8 @@ const pullCommand = {
|
|
|
11261
11664
|
if (pullBoth || argv.files) {
|
|
11262
11665
|
pulledFiles = await pullFiles({
|
|
11263
11666
|
client,
|
|
11264
|
-
projectGroupId: linked.projectId
|
|
11667
|
+
projectGroupId: linked.projectId,
|
|
11668
|
+
argv
|
|
11265
11669
|
});
|
|
11266
11670
|
if (pulledFiles === null) return;
|
|
11267
11671
|
}
|
|
@@ -11276,6 +11680,7 @@ const pullCommand = {
|
|
|
11276
11680
|
if (outputSuccess({
|
|
11277
11681
|
argv,
|
|
11278
11682
|
command: "pull",
|
|
11683
|
+
startTime,
|
|
11279
11684
|
data: {
|
|
11280
11685
|
projectId: linked.projectId,
|
|
11281
11686
|
projectName: projectResult.value.name,
|
|
@@ -11296,9 +11701,9 @@ const pullCommand = {
|
|
|
11296
11701
|
//#region src/commands/ship.ts
|
|
11297
11702
|
const COMMAND$4 = "ship";
|
|
11298
11703
|
const shipCommand = {
|
|
11299
|
-
command: "ship",
|
|
11704
|
+
command: "ship [prompt]",
|
|
11300
11705
|
describe: "Create or update + generate + publish in one shot",
|
|
11301
|
-
builder: (yargs) => yargs.
|
|
11706
|
+
builder: (yargs) => yargs.positional("prompt", {
|
|
11302
11707
|
type: "string",
|
|
11303
11708
|
describe: "What to build or change. Reads stdin if omitted."
|
|
11304
11709
|
}).option("project", {
|
|
@@ -11321,7 +11726,7 @@ const shipCommand = {
|
|
|
11321
11726
|
type: "boolean",
|
|
11322
11727
|
default: true,
|
|
11323
11728
|
describe: "Wait for deployment to complete (use --no-wait to skip)"
|
|
11324
|
-
}).example("anything ship
|
|
11729
|
+
}).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
11730
|
handler: async (argv) => {
|
|
11326
11731
|
const promptResult = await resolveTextInput({
|
|
11327
11732
|
value: argv.prompt ?? null,
|
|
@@ -11575,13 +11980,14 @@ const skillCommand = {
|
|
|
11575
11980
|
}),
|
|
11576
11981
|
handler: async (argv) => {
|
|
11577
11982
|
if (argv.path) {
|
|
11578
|
-
if (
|
|
11579
|
-
|
|
11983
|
+
if (outputSuccess({
|
|
11984
|
+
argv,
|
|
11985
|
+
command: "skill",
|
|
11986
|
+
data: {
|
|
11580
11987
|
name: "anything-cli",
|
|
11581
11988
|
path: skillRootPath
|
|
11582
|
-
}
|
|
11583
|
-
|
|
11584
|
-
}
|
|
11989
|
+
}
|
|
11990
|
+
})) return;
|
|
11585
11991
|
console.log(skillRootPath);
|
|
11586
11992
|
return;
|
|
11587
11993
|
}
|
|
@@ -11594,15 +12000,16 @@ const skillCommand = {
|
|
|
11594
12000
|
process.exitCode = 1;
|
|
11595
12001
|
return;
|
|
11596
12002
|
}
|
|
11597
|
-
if (
|
|
11598
|
-
|
|
12003
|
+
if (outputSuccess({
|
|
12004
|
+
argv,
|
|
12005
|
+
command: "skill",
|
|
12006
|
+
data: {
|
|
11599
12007
|
name: "anything-cli",
|
|
11600
12008
|
path: skillRootPath,
|
|
11601
12009
|
file: relativePath,
|
|
11602
12010
|
content
|
|
11603
|
-
}
|
|
11604
|
-
|
|
11605
|
-
}
|
|
12011
|
+
}
|
|
12012
|
+
})) return;
|
|
11606
12013
|
process.stdout.write(content);
|
|
11607
12014
|
}
|
|
11608
12015
|
};
|
|
@@ -12090,6 +12497,11 @@ const userCommand = {
|
|
|
12090
12497
|
command: "user",
|
|
12091
12498
|
aliases: ["whoami"],
|
|
12092
12499
|
describe: "Show current user and organization context",
|
|
12500
|
+
builder: (yargs) => yargs.option("brief", {
|
|
12501
|
+
type: "boolean",
|
|
12502
|
+
default: false,
|
|
12503
|
+
describe: "Show only identity essentials (id, name, email, active org)"
|
|
12504
|
+
}).example("anything user --brief", "Show just the current identity").example("anything whoami --brief --json", "Identity essentials as JSON"),
|
|
12093
12505
|
handler: async (argv) => {
|
|
12094
12506
|
const config = resolveConfig({
|
|
12095
12507
|
dev: argv.dev,
|
|
@@ -12128,10 +12540,29 @@ const userCommand = {
|
|
|
12128
12540
|
defaultOrganizationHasCredits: defaultOrganization !== null ? BigInt(defaultOrganization.creditBalance) > 0n : null
|
|
12129
12541
|
};
|
|
12130
12542
|
const activeOrg = activeOrgId ? result.value.organizations.find((o) => o.id === activeOrgId) ?? null : null;
|
|
12131
|
-
if (argv.quiet) {
|
|
12543
|
+
if (argv.quiet && !argv.json) {
|
|
12132
12544
|
console.log(result.value.id);
|
|
12133
12545
|
return;
|
|
12134
12546
|
}
|
|
12547
|
+
if (argv.brief) {
|
|
12548
|
+
const briefData = {
|
|
12549
|
+
id: result.value.id,
|
|
12550
|
+
name: result.value.name ?? null,
|
|
12551
|
+
email: result.value.email ?? null,
|
|
12552
|
+
activeOrgId: activeOrgId ?? null,
|
|
12553
|
+
activeOrgName: activeOrg?.name ?? null
|
|
12554
|
+
};
|
|
12555
|
+
if (outputSuccess({
|
|
12556
|
+
argv,
|
|
12557
|
+
command: COMMAND,
|
|
12558
|
+
data: briefData
|
|
12559
|
+
})) return;
|
|
12560
|
+
printLabel("Name", briefData.name);
|
|
12561
|
+
printLabel("Email", briefData.email);
|
|
12562
|
+
printLabel("User ID", briefData.id);
|
|
12563
|
+
printLabel("Active Org", activeOrg ? `${activeOrg.name} (${activeOrgId})` : null);
|
|
12564
|
+
return;
|
|
12565
|
+
}
|
|
12135
12566
|
if (outputSuccess({
|
|
12136
12567
|
argv,
|
|
12137
12568
|
command: COMMAND,
|